FreeCalypso > hg > gsm-codec-lib
comparison libgsmefr/dtx_common.c @ 119:c1d53064b410
libgsmefr: split dtx.c into dtx_{common,dec,enc}.c
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sat, 10 Dec 2022 02:25:20 +0000 |
parents | libgsmefr/dtx.c@58b64224d4ac |
children | 7bc011aceb7f |
comparison
equal
deleted
inserted
replaced
118:cc08498ed21b | 119:c1d53064b410 |
---|---|
1 /* | |
2 * This file is a product of splitting ETSI EFR dtx.c into parts; | |
3 * the present module is the common part for both the encoder and | |
4 * the decoder. | |
5 */ | |
6 | |
7 #include "gsm_efr.h" | |
8 #include "typedef.h" | |
9 #include "namespace.h" | |
10 #include "basic_op.h" | |
11 #include "cnst.h" | |
12 #include "sig_proc.h" | |
13 #include "memops.h" | |
14 #include "no_count.h" | |
15 #include "dtx.h" | |
16 #include "dtx_defs.h" | |
17 | |
18 /************************************************************************* | |
19 * | |
20 * FUNCTION NAME: update_lsf_history | |
21 * | |
22 * PURPOSE: Update the LSF parameter history. The LSF parameters kept | |
23 * in the buffer are used later for computing the reference | |
24 * LSF parameter vector and the averaged LSF parameter vector. | |
25 * | |
26 * INPUTS: lsf1[0..9] LSF vector of the 1st half of the frame | |
27 * lsf2[0..9] LSF vector of the 2nd half of the frame | |
28 * lsf_old[0..DTX_HANGOVER-1][0..M-1] | |
29 * Old LSF history | |
30 * | |
31 * OUTPUTS: lsf_old[0..DTX_HANGOVER-1][0..M-1] | |
32 * Updated LSF history | |
33 * | |
34 * RETURN VALUE: none | |
35 * | |
36 *************************************************************************/ | |
37 | |
38 void update_lsf_history ( | |
39 Word16 lsf1[M], | |
40 Word16 lsf2[M], | |
41 Word16 lsf_old[DTX_HANGOVER][M] | |
42 ) | |
43 { | |
44 Word16 i, j, temp; | |
45 | |
46 /* shift LSF data to make room for LSFs from current frame */ | |
47 /* This can also be implemented by using circular buffering */ | |
48 | |
49 for (i = DTX_HANGOVER - 1; i > 0; i--) | |
50 { | |
51 for (j = 0; j < M; j++) | |
52 { | |
53 lsf_old[i][j] = lsf_old[i - 1][j]; move16 (); | |
54 } | |
55 } | |
56 | |
57 /* Store new LSF data to lsf_old buffer */ | |
58 | |
59 for (i = 0; i < M; i++) | |
60 { | |
61 temp = add (shr (lsf1[i], 1), shr (lsf2[i], 1)); | |
62 lsf_old[0][i] = temp; move16 (); | |
63 } | |
64 | |
65 return; | |
66 } | |
67 | |
68 /************************************************************************* | |
69 * | |
70 * FUNCTION NAME: update_lsf_p_CN | |
71 * | |
72 * PURPOSE: Update the reference LSF parameter vector. The reference | |
73 * vector is computed by averaging the quantized LSF parameter | |
74 * vectors which exist in the LSF parameter history. | |
75 * | |
76 * INPUTS: lsf_old[0..DTX_HANGOVER-1][0..M-1] | |
77 * LSF parameter history | |
78 * | |
79 * OUTPUTS: lsf_p_CN[0..9] Computed reference LSF parameter vector | |
80 * | |
81 * RETURN VALUE: none | |
82 * | |
83 *************************************************************************/ | |
84 | |
85 void update_lsf_p_CN ( | |
86 Word16 lsf_old[DTX_HANGOVER][M], | |
87 Word16 lsf_p_CN[M] | |
88 ) | |
89 { | |
90 Word16 i, j; | |
91 Word32 L_temp; | |
92 | |
93 for (j = 0; j < M; j++) | |
94 { | |
95 L_temp = L_mult (INV_DTX_HANGOVER, lsf_old[0][j]); | |
96 for (i = 1; i < DTX_HANGOVER; i++) | |
97 { | |
98 L_temp = L_mac (L_temp, INV_DTX_HANGOVER, lsf_old[i][j]); | |
99 } | |
100 lsf_p_CN[j] = round (L_temp); move16 (); | |
101 } | |
102 | |
103 return; | |
104 } | |
105 | |
106 /************************************************************************* | |
107 * | |
108 * FUNCTION NAME: update_gcode0_CN | |
109 * | |
110 * PURPOSE: Update the reference fixed codebook gain parameter value. | |
111 * The reference value is computed by averaging the quantized | |
112 * fixed codebook gain parameter values which exist in the | |
113 * fixed codebook gain parameter history. | |
114 * | |
115 * INPUTS: gain_code_old[0..4*DTX_HANGOVER-1] | |
116 * fixed codebook gain parameter history | |
117 * | |
118 * OUTPUTS: none | |
119 * | |
120 * RETURN VALUE: Computed reference fixed codebook gain | |
121 * | |
122 *************************************************************************/ | |
123 | |
124 Word16 update_gcode0_CN ( | |
125 Word16 gain_code_old[4 * DTX_HANGOVER] | |
126 ) | |
127 { | |
128 Word16 i, j; | |
129 Word32 L_temp, L_ret; | |
130 | |
131 L_ret = 0L; move32 (); | |
132 for (i = 0; i < DTX_HANGOVER; i++) | |
133 { | |
134 L_temp = L_mult (0x1fff, gain_code_old[4 * i]); | |
135 for (j = 1; j < 4; j++) | |
136 { | |
137 L_temp = L_mac (L_temp, 0x1fff, gain_code_old[4 * i + j]); | |
138 } | |
139 L_ret = L_mac (L_ret, INV_DTX_HANGOVER, extract_h (L_temp)); | |
140 } | |
141 | |
142 return extract_h (L_ret); | |
143 } | |
144 | |
145 /************************************************************************* | |
146 * | |
147 * FUNCTION NAME: build_CN_code | |
148 * | |
149 * PURPOSE: Compute the comfort noise fixed codebook excitation. The | |
150 * gains of the pulses are always +/-1. | |
151 * | |
152 * INPUTS: *seed Old CN generator shift register state | |
153 * | |
154 * OUTPUTS: cod[0..39] Generated comfort noise fixed codebook vector | |
155 * *seed Updated CN generator shift register state | |
156 * | |
157 * RETURN VALUE: none | |
158 * | |
159 *************************************************************************/ | |
160 | |
161 void build_CN_code ( | |
162 Word16 cod[], | |
163 Word32 *seed | |
164 ) | |
165 { | |
166 Word16 i, j, k; | |
167 | |
168 for (i = 0; i < L_SUBFR; i++) | |
169 { | |
170 cod[i] = 0; move16 (); | |
171 } | |
172 | |
173 for (k = 0; k < NB_PULSE; k++) | |
174 { | |
175 i = pseudonoise (seed, 2); /* generate pulse position */ | |
176 i = shr (extract_l (L_mult (i, 10)), 1); | |
177 i = add (i, k); | |
178 | |
179 j = pseudonoise (seed, 1); /* generate sign */ | |
180 | |
181 test (); | |
182 if (j > 0) | |
183 { | |
184 cod[i] = 4096; move16 (); | |
185 } | |
186 else | |
187 { | |
188 cod[i] = -4096; move16 (); | |
189 } | |
190 } | |
191 | |
192 return; | |
193 } | |
194 | |
195 /************************************************************************* | |
196 * | |
197 * FUNCTION NAME: pseudonoise | |
198 * | |
199 * PURPOSE: Generate a random integer value to use in comfort noise | |
200 * generation. The algorithm uses polynomial x^31 + x^3 + 1 | |
201 * (length of PN sequence is 2^31 - 1). | |
202 * | |
203 * INPUTS: *shift_reg Old CN generator shift register state | |
204 * | |
205 * | |
206 * OUTPUTS: *shift_reg Updated CN generator shift register state | |
207 * | |
208 * RETURN VALUE: Generated random integer value | |
209 * | |
210 *************************************************************************/ | |
211 | |
212 Word16 pseudonoise ( | |
213 Word32 *shift_reg, | |
214 Word16 no_bits | |
215 ) | |
216 { | |
217 Word16 noise_bits, Sn, i; | |
218 | |
219 noise_bits = 0; move16 (); | |
220 for (i = 0; i < no_bits; i++) | |
221 { | |
222 /* State n == 31 */ | |
223 test (); logic32 (); | |
224 if ((*shift_reg & 0x00000001L) != 0) | |
225 { | |
226 Sn = 1; move16 (); | |
227 } | |
228 else | |
229 { | |
230 Sn = 0; move16 (); | |
231 } | |
232 | |
233 /* State n == 3 */ | |
234 test (); logic32 (); | |
235 if ((*shift_reg & 0x10000000L) != 0) | |
236 { | |
237 Sn = Sn ^ 1; logic16 (); | |
238 } | |
239 else | |
240 { | |
241 Sn = Sn ^ 0; logic16 (); | |
242 } | |
243 | |
244 noise_bits = shl (noise_bits, 1); | |
245 noise_bits = noise_bits | (extract_l (*shift_reg) & 1); | |
246 logic16 (); logic16 (); | |
247 | |
248 *shift_reg = L_shr (*shift_reg, 1); move32 (); | |
249 test (); logic16 (); | |
250 if (Sn & 1) | |
251 { | |
252 *shift_reg = *shift_reg | 0x40000000L; move32 (); logic32 (); | |
253 } | |
254 } | |
255 | |
256 return noise_bits; | |
257 } |