comparison libgsmefr/d_gains.c @ 53:49dd1ac8e75b

libgsmefr: import most *.c files from ETSI source
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 25 Nov 2022 16:18:21 +0000
parents
children a18782a7d270
comparison
equal deleted inserted replaced
52:988fd7ff514f 53:49dd1ac8e75b
1 /*************************************************************************
2 *
3 * FILE NAME: D_GAINS.C
4 *
5 * FUNCTIONS DEFINED IN THIS FILE:
6 *
7 * d_gain_pitch(), d_gain_code() and gmed5()
8 *
9 * MA prediction is performed on the innovation energy
10 * ( in dB/(20*log10(2)) ) with mean removed.
11 *************************************************************************/
12
13 #include "typedef.h"
14 #include "basic_op.h"
15 #include "oper_32b.h"
16 #include "count.h"
17 #include "sig_proc.h"
18
19 #include "gains_tb.h"
20
21 #include "cnst.h"
22 #include "dtx.h"
23
24 extern Word16 gain_code_old_rx[4 * DTX_HANGOVER];
25
26 /* Static variables for bad frame handling */
27
28 /* Variables used by d_gain_pitch: */
29 Word16 pbuf[5], past_gain_pit, prev_gp;
30
31 /* Variables used by d_gain_code: */
32 Word16 gbuf[5], past_gain_code, prev_gc;
33
34 /* Static variables for CNI (used by d_gain_code) */
35
36 Word16 gcode0_CN, gain_code_old_CN, gain_code_new_CN, gain_code_muting_CN;
37
38 /* Memories of gain dequantization: */
39
40 /* past quantized energies. */
41 /* initialized to -14.0/constant, constant = 20*Log10(2) */
42
43 Word16 past_qua_en[4];
44
45 /* MA prediction coeff */
46 Word16 pred[4];
47
48 /*************************************************************************
49 *
50 * FUNCTION: gmed5
51 *
52 * PURPOSE: calculates 5-point median.
53 *
54 * DESCRIPTION:
55 *
56 *************************************************************************/
57
58 Word16 gmed5 ( /* out : index of the median value (0...4) */
59 Word16 ind[] /* in : Past gain values */
60 )
61 {
62 Word16 i, j, ix = 0, tmp[5];
63 Word16 max, tmp2[5];
64
65 for (i = 0; i < 5; i++)
66 {
67 tmp2[i] = ind[i]; move16 ();
68 }
69
70 for (i = 0; i < 5; i++)
71 {
72 max = -8192; move16 ();
73 for (j = 0; j < 5; j++)
74 {
75 test ();
76 if (sub (tmp2[j], max) >= 0)
77 {
78 max = tmp2[j]; move16 ();
79 ix = j; move16 ();
80 }
81 }
82 tmp2[ix] = -16384; move16 ();
83 tmp[i] = ix; move16 ();
84 }
85
86 return (ind[tmp[2]]);
87 }
88
89 /*************************************************************************
90 *
91 * FUNCTION: d_gain_pitch
92 *
93 * PURPOSE: decodes the pitch gain using the received index.
94 *
95 * DESCRIPTION:
96 * In case of no frame erasure, the gain is obtained from the
97 * quantization table at the given index; otherwise, a downscaled
98 * past gain is used.
99 *
100 *************************************************************************/
101
102 Word16 d_gain_pitch ( /* out : quantized pitch gain */
103 Word16 index, /* in : index of quantization */
104 Word16 bfi, /* in : bad frame indicator (good = 0) */
105 Word16 state,
106 Word16 prev_bf,
107 Word16 rxdtx_ctrl
108 )
109 {
110 static const Word16 pdown[7] =
111 {
112 32767, 32112, 32112, 26214,
113 9830, 6553, 6553
114 };
115
116 Word16 gain, tmp, i;
117
118 test ();
119 if (bfi == 0)
120 {
121 test (); logic16 ();
122 if ((rxdtx_ctrl & RX_SP_FLAG) != 0)
123 {
124 gain = shr (qua_gain_pitch[index], 2); move16 ();
125
126 test ();
127 if (prev_bf != 0)
128 {
129 test ();
130 if (sub (gain, prev_gp) > 0)
131 {
132 gain = prev_gp;
133 }
134 }
135 }
136 else
137 {
138 gain = 0; move16 ();
139 }
140 prev_gp = gain; move16 ();
141 }
142 else
143 {
144 test (); logic16 ();
145 if ((rxdtx_ctrl & RX_SP_FLAG) != 0)
146 {
147 tmp = gmed5 (pbuf); move16 ();
148
149 test ();
150 if (sub (tmp, past_gain_pit) < 0)
151 {
152 past_gain_pit = tmp; move16 ();
153 }
154 gain = mult (pdown[state], past_gain_pit);
155 }
156 else
157 {
158 gain = 0; move16 ();
159 }
160 }
161
162 past_gain_pit = gain; move16 ();
163
164 test ();
165 if (sub (past_gain_pit, 4096) > 0) /* if (past_gain_pit > 1.0) */
166 {
167 past_gain_pit = 4096; move16 ();
168 }
169 for (i = 1; i < 5; i++)
170 {
171 pbuf[i - 1] = pbuf[i]; move16 ();
172 }
173
174 pbuf[4] = past_gain_pit; move16 ();
175
176 return gain;
177 }
178
179 /*************************************************************************
180 *
181 * FUNCTION: d_gain_code
182 *
183 * PURPOSE: decode the fixed codebook gain using the received index.
184 *
185 * DESCRIPTION:
186 * The received index gives the gain correction factor gamma.
187 * The quantized gain is given by g_q = g0 * gamma
188 * where g0 is the predicted gain.
189 * To find g0, 4th order MA prediction is applied to the mean-removed
190 * innovation energy in dB.
191 * In case of frame erasure, downscaled past gain is used.
192 *
193 *************************************************************************/
194
195 /* average innovation energy. */
196 /* MEAN_ENER = 36.0/constant, constant = 20*Log10(2) */
197 #define MEAN_ENER 783741L /* 36/(20*log10(2)) */
198
199 void d_gain_code (
200 Word16 index, /* input : received quantization index */
201 Word16 code[], /* input : innovation codevector */
202 Word16 lcode, /* input : codevector length */
203 Word16 *gain_code, /* output: decoded innovation gain */
204 Word16 bfi, /* input : bad frame indicator */
205 Word16 state,
206 Word16 prev_bf,
207 Word16 rxdtx_ctrl,
208 Word16 i_subfr,
209 Word16 rx_dtx_state
210 )
211 {
212 static const Word16 cdown[7] =
213 {
214 32767, 32112, 32112, 32112,
215 32112, 32112, 22937
216 };
217
218 Word16 i, tmp;
219 Word16 gcode0, exp, frac, av_pred_en;
220 Word32 ener, ener_code;
221
222 test (); test (); logic16 ();
223 if (((rxdtx_ctrl & RX_UPD_SID_QUANT_MEM) != 0) && (i_subfr == 0))
224 {
225 gcode0_CN = update_gcode0_CN (gain_code_old_rx); move16 ();
226 gcode0_CN = shl (gcode0_CN, 4);
227 }
228
229 /* Handle cases of comfort noise fixed codebook gain decoding in
230 which past valid SID frames are repeated */
231
232 test (); test (); test (); logic16 (); logic16 (); logic16 ();
233 if (((rxdtx_ctrl & RX_NO_TRANSMISSION) != 0)
234 || ((rxdtx_ctrl & RX_INVALID_SID_FRAME) != 0)
235 || ((rxdtx_ctrl & RX_LOST_SID_FRAME) != 0))
236 {
237
238 test (); logic16 ();
239 if ((rxdtx_ctrl & RX_NO_TRANSMISSION) != 0)
240 {
241 /* DTX active: no transmission. Interpolate gain values
242 in memory */
243 test ();
244 if (i_subfr == 0)
245 {
246 *gain_code = interpolate_CN_param (gain_code_old_CN,
247 gain_code_new_CN, rx_dtx_state);
248 move16 ();
249 }
250 else
251 {
252 *gain_code = prev_gc; move16 ();
253 }
254 }
255 else
256 { /* Invalid or lost SID frame:
257 use gain values from last good SID frame */
258 gain_code_old_CN = gain_code_new_CN; move16 ();
259 *gain_code = gain_code_new_CN; move16 ();
260
261 /* reset table of past quantized energies */
262 for (i = 0; i < 4; i++)
263 {
264 past_qua_en[i] = -2381; move16 ();
265 }
266 }
267
268 test (); logic16 ();
269 if ((rxdtx_ctrl & RX_DTX_MUTING) != 0)
270 {
271 /* attenuate the gain value by 0.75 dB in each subframe */
272 /* (total of 3 dB per frame) */
273 gain_code_muting_CN = mult (gain_code_muting_CN, 30057);
274 *gain_code = gain_code_muting_CN; move16 ();
275 }
276 else
277 {
278 /* Prepare for DTX muting by storing last good gain value */
279 gain_code_muting_CN = gain_code_new_CN; move16 ();
280 }
281
282 past_gain_code = *gain_code; move16 ();
283
284 for (i = 1; i < 5; i++)
285 {
286 gbuf[i - 1] = gbuf[i]; move16 ();
287 }
288
289 gbuf[4] = past_gain_code; move16 ();
290 prev_gc = past_gain_code; move16 ();
291
292 return;
293 }
294
295 /*----------------- Test erasure ---------------*/
296
297 test ();
298 if (bfi != 0)
299 {
300 tmp = gmed5 (gbuf); move16 ();
301 test ();
302 if (sub (tmp, past_gain_code) < 0)
303 {
304 past_gain_code = tmp; move16 ();
305 }
306 past_gain_code = mult (past_gain_code, cdown[state]);
307 *gain_code = past_gain_code; move16 ();
308
309 av_pred_en = 0; move16 ();
310 for (i = 0; i < 4; i++)
311 {
312 av_pred_en = add (av_pred_en, past_qua_en[i]);
313 }
314
315 /* av_pred_en = 0.25*av_pred_en - 4/(20Log10(2)) */
316 av_pred_en = mult (av_pred_en, 8192); /* *= 0.25 */
317
318 /* if (av_pred_en < -14/(20Log10(2))) av_pred_en = .. */
319 test ();
320 if (sub (av_pred_en, -2381) < 0)
321 {
322 av_pred_en = -2381; move16 ();
323 }
324 for (i = 3; i > 0; i--)
325 {
326 past_qua_en[i] = past_qua_en[i - 1]; move16 ();
327 }
328 past_qua_en[0] = av_pred_en; move16 ();
329 for (i = 1; i < 5; i++)
330 {
331 gbuf[i - 1] = gbuf[i]; move16 ();
332 }
333 gbuf[4] = past_gain_code; move16 ();
334
335 /* Use the most recent comfort noise fixed codebook gain value
336 for updating the fixed codebook gain history */
337 test ();
338 if (gain_code_new_CN == 0)
339 {
340 tmp = prev_gc; move16 ();
341 }
342 else
343 {
344 tmp = gain_code_new_CN;
345 }
346
347 update_gain_code_history_rx (tmp, gain_code_old_rx);
348
349 test ();
350 if (sub (i_subfr, (3 * L_SUBFR)) == 0)
351 {
352 gain_code_old_CN = *gain_code; move16 ();
353 }
354 return;
355 }
356
357 test (); logic16 ();
358 if ((rxdtx_ctrl & RX_SP_FLAG) != 0)
359 {
360
361 /*-------------- Decode codebook gain ---------------*/
362
363 /*-------------------------------------------------------------------*
364 * energy of code: *
365 * ~~~~~~~~~~~~~~~ *
366 * ener_code = 10 * Log10(energy/lcode) / constant *
367 * = 1/2 * Log2(energy/lcode) *
368 * constant = 20*Log10(2) *
369 *-------------------------------------------------------------------*/
370
371 /* ener_code = log10(ener_code/lcode) / (20*log10(2)) */
372 ener_code = 0; move32 ();
373 for (i = 0; i < lcode; i++)
374 {
375 ener_code = L_mac (ener_code, code[i], code[i]);
376 }
377 /* ener_code = ener_code / lcode */
378 ener_code = L_mult (round (ener_code), 26214);
379
380 /* ener_code = 1/2 * Log2(ener_code) */
381 Log2 (ener_code, &exp, &frac);
382 ener_code = L_Comp (sub (exp, 30), frac);
383
384 /* predicted energy */
385
386 ener = MEAN_ENER; move32 ();
387 for (i = 0; i < 4; i++)
388 {
389 ener = L_mac (ener, past_qua_en[i], pred[i]);
390 }
391
392 /*-------------------------------------------------------------------*
393 * predicted codebook gain *
394 * ~~~~~~~~~~~~~~~~~~~~~~~ *
395 * gcode0 = Pow10( (ener*constant - ener_code*constant) / 20 ) *
396 * = Pow2(ener-ener_code) *
397 * constant = 20*Log10(2) *
398 *-------------------------------------------------------------------*/
399
400 ener = L_shr (L_sub (ener, ener_code), 1);
401 L_Extract (ener, &exp, &frac);
402
403 gcode0 = extract_l (Pow2 (exp, frac)); /* predicted gain */
404
405 gcode0 = shl (gcode0, 4);
406
407 *gain_code = mult (qua_gain_code[index], gcode0); move16 ();
408
409 test ();
410 if (prev_bf != 0)
411 {
412 test ();
413 if (sub (*gain_code, prev_gc) > 0)
414 {
415 *gain_code = prev_gc; move16 ();
416 }
417 }
418 /*-------------------------------------------------------------------*
419 * update table of past quantized energies *
420 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *
421 * past_qua_en = 20 * Log10(qua_gain_code) / constant *
422 * = Log2(qua_gain_code) *
423 * constant = 20*Log10(2) *
424 *-------------------------------------------------------------------*/
425
426 for (i = 3; i > 0; i--)
427 {
428 past_qua_en[i] = past_qua_en[i - 1]; move16 ();
429 }
430 Log2 (L_deposit_l (qua_gain_code[index]), &exp, &frac);
431
432 past_qua_en[0] = shr (frac, 5); move16 ();
433 past_qua_en[0] = add (past_qua_en[0], shl (sub (exp, 11), 10));
434 move16 ();
435
436 update_gain_code_history_rx (*gain_code, gain_code_old_rx);
437
438 if (sub (i_subfr, (3 * L_SUBFR)) == 0)
439 {
440 gain_code_old_CN = *gain_code; move16 ();
441 }
442 }
443 else
444 {
445 test (); test (); logic16 ();
446 if (((rxdtx_ctrl & RX_FIRST_SID_UPDATE) != 0) && (i_subfr == 0))
447 {
448 gain_code_new_CN = mult (gcode0_CN, qua_gain_code[index]);
449
450 /*---------------------------------------------------------------*
451 * reset table of past quantized energies *
452 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *
453 *---------------------------------------------------------------*/
454
455 for (i = 0; i < 4; i++)
456 {
457 past_qua_en[i] = -2381; move16 ();
458 }
459 }
460 test (); test (); logic16 ();
461 if (((rxdtx_ctrl & RX_CONT_SID_UPDATE) != 0) && (i_subfr == 0))
462 {
463 gain_code_old_CN = gain_code_new_CN; move16 ();
464 gain_code_new_CN = mult (gcode0_CN, qua_gain_code[index]);
465 move16 ();
466 }
467 test ();
468 if (i_subfr == 0)
469 {
470 *gain_code = interpolate_CN_param (gain_code_old_CN,
471 gain_code_new_CN,
472 rx_dtx_state); move16 ();
473 }
474 else
475 {
476 *gain_code = prev_gc; move16 ();
477 }
478 }
479
480 past_gain_code = *gain_code; move16 ();
481
482 for (i = 1; i < 5; i++)
483 {
484 gbuf[i - 1] = gbuf[i]; move16 ();
485 }
486 gbuf[4] = past_gain_code; move16 ();
487 prev_gc = past_gain_code; move16 ();
488
489 return;
490 }