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 }