FreeCalypso > hg > gsm-codec-lib
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 } |