FreeCalypso > hg > gsm-codec-lib
comparison libgsmefr/dtx_enc.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 | cf39a90f5196 |
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 encoder-specific part. | |
4 */ | |
5 | |
6 #include "gsm_efr.h" | |
7 #include "typedef.h" | |
8 #include "namespace.h" | |
9 #include "basic_op.h" | |
10 #include "cnst.h" | |
11 #include "sig_proc.h" | |
12 #include "memops.h" | |
13 #include "no_count.h" | |
14 #include "dtx.h" | |
15 #include "dtx_defs.h" | |
16 #include "enc_state.h" | |
17 | |
18 /************************************************************************* | |
19 * | |
20 * FUNCTION NAME: reset_tx_dtx | |
21 * | |
22 * PURPOSE: Resets the static variables of the TX DTX handler to their | |
23 * initial values | |
24 * | |
25 *************************************************************************/ | |
26 | |
27 void reset_tx_dtx (struct EFR_encoder_state *st) | |
28 { | |
29 Word16 i; | |
30 | |
31 /* suppose infinitely long speech period before start */ | |
32 | |
33 st->txdtx_hangover = DTX_HANGOVER; | |
34 st->txdtx_N_elapsed = 0x7fff; | |
35 st->txdtx_ctrl = TX_SP_FLAG | TX_VAD_FLAG; | |
36 | |
37 for (i = 0; i < 6; i++) | |
38 { | |
39 st->old_CN_mem_tx[i] = 0; | |
40 } | |
41 | |
42 for (i = 0; i < DTX_HANGOVER; i++) | |
43 { | |
44 st->lsf_old_tx[i][0] = 1384; | |
45 st->lsf_old_tx[i][1] = 2077; | |
46 st->lsf_old_tx[i][2] = 3420; | |
47 st->lsf_old_tx[i][3] = 5108; | |
48 st->lsf_old_tx[i][4] = 6742; | |
49 st->lsf_old_tx[i][5] = 8122; | |
50 st->lsf_old_tx[i][6] = 9863; | |
51 st->lsf_old_tx[i][7] = 11092; | |
52 st->lsf_old_tx[i][8] = 12714; | |
53 st->lsf_old_tx[i][9] = 13701; | |
54 } | |
55 | |
56 for (i = 0; i < 4 * DTX_HANGOVER; i++) | |
57 { | |
58 st->gain_code_old_tx[i] = 0; | |
59 } | |
60 | |
61 st->L_pn_seed_tx = PN_INITIAL_SEED; | |
62 | |
63 st->buf_p_tx = 0; | |
64 return; | |
65 } | |
66 | |
67 /************************************************************************* | |
68 * | |
69 * FUNCTION NAME: tx_dtx | |
70 * | |
71 * PURPOSE: DTX handler of the speech encoder. Determines when to add | |
72 * the hangover period to the end of the speech burst, and | |
73 * also determines when to use old SID parameters, and when | |
74 * to update the SID parameters. This function also initializes | |
75 * the pseudo noise generator shift register. | |
76 * | |
77 * Operation of the TX DTX handler is based on the VAD flag | |
78 * given as input from the speech encoder. | |
79 * | |
80 * INPUTS: VAD_flag Voice activity decision | |
81 * *txdtx_ctrl Old encoder DTX control word | |
82 * | |
83 * OUTPUTS: *txdtx_ctrl Updated encoder DTX control word | |
84 * L_pn_seed_tx Initialized pseudo noise generator shift | |
85 * register (global variable) | |
86 * | |
87 * RETURN VALUE: none | |
88 * | |
89 *************************************************************************/ | |
90 | |
91 void tx_dtx ( | |
92 struct EFR_encoder_state *st, | |
93 Word16 VAD_flag | |
94 ) | |
95 { | |
96 /* N_elapsed (frames since last SID update) is incremented. If SID | |
97 is updated N_elapsed is cleared later in this function */ | |
98 | |
99 st->txdtx_N_elapsed = add (st->txdtx_N_elapsed, 1); | |
100 | |
101 /* If voice activity was detected, reset hangover counter */ | |
102 | |
103 if (sub (VAD_flag, 1) == 0) | |
104 { | |
105 st->txdtx_hangover = DTX_HANGOVER; | |
106 st->txdtx_ctrl = TX_SP_FLAG | TX_VAD_FLAG; | |
107 } | |
108 else | |
109 { | |
110 if (st->txdtx_hangover == 0) | |
111 { | |
112 /* Hangover period is over, SID should be updated */ | |
113 | |
114 st->txdtx_N_elapsed = 0; | |
115 | |
116 /* Check if this is the first frame after hangover period */ | |
117 if ((st->txdtx_ctrl & TX_HANGOVER_ACTIVE) != 0) | |
118 { | |
119 st->txdtx_ctrl = TX_PREV_HANGOVER_ACTIVE | |
120 | TX_SID_UPDATE; | |
121 st->L_pn_seed_tx = PN_INITIAL_SEED; | |
122 } | |
123 else | |
124 { | |
125 st->txdtx_ctrl = TX_SID_UPDATE; | |
126 } | |
127 } | |
128 else | |
129 { | |
130 /* Hangover period is not over, update hangover counter */ | |
131 st->txdtx_hangover = sub (st->txdtx_hangover, 1); | |
132 | |
133 /* Check if elapsed time from last SID update is greater than | |
134 threshold. If not, set SP=0 (although hangover period is not | |
135 over) and use old SID parameters for new SID frame. | |
136 N_elapsed counter must be summed with hangover counter in order | |
137 to avoid erroneus SP=1 decision in case when N_elapsed is grown | |
138 bigger than threshold and hangover period is still active */ | |
139 | |
140 if (sub (add (st->txdtx_N_elapsed, st->txdtx_hangover), | |
141 DTX_ELAPSED_THRESHOLD) < 0) | |
142 { | |
143 /* old SID frame should be used */ | |
144 st->txdtx_ctrl = TX_USE_OLD_SID; | |
145 } | |
146 else | |
147 { | |
148 if ((st->txdtx_ctrl & TX_HANGOVER_ACTIVE) != 0) | |
149 { | |
150 st->txdtx_ctrl = TX_PREV_HANGOVER_ACTIVE | |
151 | TX_HANGOVER_ACTIVE | |
152 | TX_SP_FLAG; | |
153 } | |
154 else | |
155 { | |
156 st->txdtx_ctrl = TX_HANGOVER_ACTIVE | |
157 | TX_SP_FLAG; | |
158 } | |
159 } | |
160 } | |
161 } | |
162 | |
163 return; | |
164 } | |
165 | |
166 /************************************************************************* | |
167 * | |
168 * FUNCTION NAME: CN_encoding | |
169 * | |
170 * PURPOSE: Encoding of the comfort noise parameters into a SID frame. | |
171 * Use old SID parameters if necessary. Set the parameter | |
172 * indices not used by comfort noise parameters to zero. | |
173 * | |
174 * INPUTS: params[0..56] Comfort noise parameter frame from the | |
175 * speech encoder | |
176 * txdtx_ctrl TX DTX handler control word | |
177 * | |
178 * OUTPUTS: params[0..56] Comfort noise encoded parameter frame | |
179 * | |
180 * RETURN VALUE: none | |
181 * | |
182 *************************************************************************/ | |
183 | |
184 void CN_encoding ( | |
185 struct EFR_encoder_state *st, | |
186 Word16 params[], | |
187 Word16 txdtx_ctrl | |
188 ) | |
189 { | |
190 Word16 i; | |
191 | |
192 if ((txdtx_ctrl & TX_SID_UPDATE) != 0) | |
193 { | |
194 /* Store new CN parameters in memory to be used later as old | |
195 CN parameters */ | |
196 | |
197 /* LPC parameter indices */ | |
198 for (i = 0; i < 5; i++) | |
199 { | |
200 st->old_CN_mem_tx[i] = params[i]; | |
201 } | |
202 /* Codebook index computed in last subframe */ | |
203 st->old_CN_mem_tx[5] = params[56]; | |
204 } | |
205 if ((txdtx_ctrl & TX_USE_OLD_SID) != 0) | |
206 { | |
207 /* Use old CN parameters previously stored in memory */ | |
208 for (i = 0; i < 5; i++) | |
209 { | |
210 params[i] = st->old_CN_mem_tx[i]; | |
211 } | |
212 params[17] = st->old_CN_mem_tx[5]; | |
213 params[30] = st->old_CN_mem_tx[5]; | |
214 params[43] = st->old_CN_mem_tx[5]; | |
215 params[56] = st->old_CN_mem_tx[5]; | |
216 } | |
217 /* Set all the rest of the parameters to zero (SID codeword will | |
218 be written later) */ | |
219 for (i = 0; i < 12; i++) | |
220 { | |
221 params[i + 5] = 0; | |
222 params[i + 18] = 0; | |
223 params[i + 31] = 0; | |
224 params[i + 44] = 0; | |
225 } | |
226 | |
227 return; | |
228 } | |
229 | |
230 /************************************************************************* | |
231 * | |
232 * FUNCTION NAME: aver_lsf_history | |
233 * | |
234 * PURPOSE: Compute the averaged LSF parameter vector. Computation is | |
235 * performed by averaging the LSF parameter vectors which exist | |
236 * in the LSF parameter history, together with the LSF | |
237 * parameter vectors of the current frame. | |
238 * | |
239 * INPUTS: lsf_old[0..DTX_HANGOVER-1][0..M-1] | |
240 * LSF parameter history | |
241 * lsf1[0..M-1] LSF vector of the 1st half of the frame | |
242 * lsf2[0..M-1] LSF vector of the 2nd half of the frame | |
243 * | |
244 * OUTPUTS: lsf_aver[0..M-1] Averaged LSF parameter vector | |
245 * | |
246 * RETURN VALUE: none | |
247 * | |
248 *************************************************************************/ | |
249 | |
250 void aver_lsf_history ( | |
251 Word16 lsf_old[DTX_HANGOVER][M], | |
252 Word16 lsf1[M], | |
253 Word16 lsf2[M], | |
254 Word16 lsf_aver[M] | |
255 ) | |
256 { | |
257 Word16 i, j; | |
258 Word32 L_temp; | |
259 | |
260 for (j = 0; j < M; j++) | |
261 { | |
262 L_temp = L_mult (0x3fff, lsf1[j]); | |
263 L_temp = L_mac (L_temp, 0x3fff, lsf2[j]); | |
264 L_temp = L_mult (INV_DTX_HANGOVER_P1, extract_h (L_temp)); | |
265 | |
266 for (i = 0; i < DTX_HANGOVER; i++) | |
267 { | |
268 L_temp = L_mac (L_temp, INV_DTX_HANGOVER_P1, lsf_old[i][j]); | |
269 } | |
270 | |
271 lsf_aver[j] = extract_h (L_temp); move16 (); | |
272 } | |
273 | |
274 return; | |
275 } | |
276 | |
277 /************************************************************************* | |
278 * | |
279 * FUNCTION NAME: update_gain_code_history_tx | |
280 * | |
281 * PURPOSE: Update the fixed codebook gain parameter history of the | |
282 * encoder. The fixed codebook gain parameters kept in the buffer | |
283 * are used later for computing the reference fixed codebook | |
284 * gain parameter value and the averaged fixed codebook gain | |
285 * parameter value. | |
286 * | |
287 * INPUTS: new_gain_code New fixed codebook gain value | |
288 * | |
289 * gain_code_old_tx[0..4*DTX_HANGOVER-1] | |
290 * Old fixed codebook gain history of encoder | |
291 * | |
292 * OUTPUTS: gain_code_old_tx[0..4*DTX_HANGOVER-1] | |
293 * Updated fixed codebook gain history of encoder | |
294 * | |
295 * RETURN VALUE: none | |
296 * | |
297 *************************************************************************/ | |
298 | |
299 void update_gain_code_history_tx ( | |
300 struct EFR_encoder_state *st, | |
301 Word16 new_gain_code | |
302 ) | |
303 { | |
304 /* Circular buffer */ | |
305 st->gain_code_old_tx[st->buf_p_tx] = new_gain_code; | |
306 | |
307 if (sub (st->buf_p_tx, (4 * DTX_HANGOVER - 1)) == 0) | |
308 { | |
309 st->buf_p_tx = 0; | |
310 } | |
311 else | |
312 { | |
313 st->buf_p_tx = add (st->buf_p_tx, 1); | |
314 } | |
315 | |
316 return; | |
317 } | |
318 | |
319 /************************************************************************* | |
320 * | |
321 * FUNCTION NAME: compute_CN_excitation_gain | |
322 * | |
323 * PURPOSE: Compute the unquantized fixed codebook gain. Computation is | |
324 * based on the energy of the Linear Prediction residual signal. | |
325 * | |
326 * INPUTS: res2[0..39] Linear Prediction residual signal | |
327 * | |
328 * OUTPUTS: none | |
329 * | |
330 * RETURN VALUE: Unquantized fixed codebook gain | |
331 * | |
332 *************************************************************************/ | |
333 | |
334 Word16 compute_CN_excitation_gain ( | |
335 Word16 res2[L_SUBFR] | |
336 ) | |
337 { | |
338 Word16 i, norm, norm1, temp, overfl; | |
339 Word32 L_temp; | |
340 | |
341 /* Compute the energy of the LP residual signal */ | |
342 | |
343 norm = 0; move16 (); | |
344 do | |
345 { | |
346 overfl = 0; move16 (); | |
347 | |
348 L_temp = 0L; move32 (); | |
349 for (i = 0; i < L_SUBFR; i++) | |
350 { | |
351 temp = shr (res2[i], norm); | |
352 L_temp = L_mac (L_temp, temp, temp); | |
353 } | |
354 | |
355 test (); | |
356 if (L_sub (L_temp, MAX_32) == 0) | |
357 { | |
358 norm = add (norm, 1); | |
359 overfl = 1; move16 (); /* Set the overflow flag */ | |
360 } | |
361 test (); | |
362 } | |
363 while (overfl != 0); | |
364 | |
365 L_temp = L_add (L_temp, 1L); /* Avoid the case of all zeros */ | |
366 | |
367 /* Take the square root of the obtained energy value (sqroot is a 2nd | |
368 order Taylor series approximation) */ | |
369 | |
370 norm1 = norm_l (L_temp); | |
371 temp = extract_h (L_shl (L_temp, norm1)); | |
372 L_temp = L_mult (temp, temp); | |
373 L_temp = L_sub (805306368L, L_shr (L_temp, 3)); | |
374 L_temp = L_add (L_temp, L_mult (24576, temp)); | |
375 | |
376 temp = extract_h (L_temp); | |
377 test (); logic16 (); | |
378 if ((norm1 & 0x0001) != 0) | |
379 { | |
380 temp = mult_r (temp, 23170); | |
381 norm1 = sub (norm1, 1); | |
382 } | |
383 /* Divide the result of sqroot operation by sqroot(10) */ | |
384 | |
385 temp = mult_r (temp, 10362); | |
386 | |
387 /* Re-scale to get the final value */ | |
388 | |
389 norm1 = shr (norm1, 1); | |
390 norm1 = sub (norm1, norm); | |
391 | |
392 test (); | |
393 if (norm1 >= 0) | |
394 { | |
395 temp = shr (temp, norm1); | |
396 } | |
397 else | |
398 { | |
399 temp = shl (temp, abs_s (norm1)); | |
400 } | |
401 | |
402 return temp; | |
403 } | |
404 | |
405 /************************************************************************* | |
406 * | |
407 * FUNCTION NAME: aver_gain_code_history | |
408 * | |
409 * PURPOSE: Compute the averaged fixed codebook gain parameter value. | |
410 * Computation is performed by averaging the fixed codebook | |
411 * gain parameter values which exist in the fixed codebook | |
412 * gain parameter history, together with the fixed codebook | |
413 * gain parameter value of the current subframe. | |
414 * | |
415 * INPUTS: CN_excitation_gain | |
416 * Unquantized fixed codebook gain value | |
417 * of the current subframe | |
418 * gain_code_old[0..4*DTX_HANGOVER-1] | |
419 * fixed codebook gain parameter history | |
420 * | |
421 * OUTPUTS: none | |
422 * | |
423 * RETURN VALUE: Averaged fixed codebook gain value | |
424 * | |
425 *************************************************************************/ | |
426 | |
427 Word16 aver_gain_code_history ( | |
428 Word16 CN_excitation_gain, | |
429 Word16 gain_code_old[4 * DTX_HANGOVER] | |
430 ) | |
431 { | |
432 Word16 i; | |
433 Word32 L_ret; | |
434 | |
435 L_ret = L_mult (0x470, CN_excitation_gain); | |
436 | |
437 for (i = 0; i < (4 * DTX_HANGOVER); i++) | |
438 { | |
439 L_ret = L_mac (L_ret, 0x470, gain_code_old[i]); | |
440 } | |
441 return extract_h (L_ret); | |
442 } |