comparison libtwamr/gc_pred.c @ 336:7f99b8ed30e5

libtwamr: integrate gc_pred.c
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 18 Apr 2024 23:02:35 +0000
parents
children
comparison
equal deleted inserted replaced
335:03198f6b0427 336:7f99b8ed30e5
1 /*
2 *****************************************************************************
3 *
4 * GSM AMR-NB speech codec R98 Version 7.6.0 December 12, 2001
5 * R99 Version 3.3.0
6 * REL-4 Version 4.1.0
7 *
8 *****************************************************************************
9 *
10 * File : gc_pred.c
11 * Purpose : codebook gain MA prediction
12 *
13 *****************************************************************************
14 */
15
16 /*
17 *****************************************************************************
18 * MODULE INCLUDE FILE AND VERSION ID
19 *****************************************************************************
20 */
21 #include "namespace.h"
22 #include "gc_pred.h"
23
24 /*
25 *****************************************************************************
26 * INCLUDE FILES
27 *****************************************************************************
28 */
29 #include "typedef.h"
30 #include "basic_op.h"
31 #include "oper_32b.h"
32 #include "cnst.h"
33 #include "no_count.h"
34 #include "log2.h"
35 #include "memops.h"
36
37 /*
38 *****************************************************************************
39 * LOCAL VARIABLES AND TABLES
40 *****************************************************************************
41 */
42
43 #define NPRED 4 /* number of prediction taps */
44
45 /* MA prediction coefficients (Q13) */
46 static const Word16 pred[NPRED] = {5571, 4751, 2785, 1556};
47
48 /* average innovation energy. */
49 /* MEAN_ENER = 36.0/constant, constant = 20*Log10(2) */
50 #define MEAN_ENER_MR122 783741L /* 36/(20*log10(2)) (Q17) */
51
52 /* MA prediction coefficients (Q6) */
53 static const Word16 pred_MR122[NPRED] = {44, 37, 22, 12};
54
55 /* minimum quantized energy: -14 dB */
56 #define MIN_ENERGY -14336 /* 14 Q10 */
57 #define MIN_ENERGY_MR122 -2381 /* 14 / (20*log10(2)) Q10 */
58 /*
59 *****************************************************************************
60 * PUBLIC PROGRAM CODE
61 *****************************************************************************
62 */
63 /*************************************************************************
64 *
65 * Function: gc_pred_reset
66 * Purpose: Initializes state memory to zero
67 *
68 **************************************************************************
69 */
70 void gc_pred_reset (gc_predState *state)
71 {
72 Word16 i;
73
74 for(i = 0; i < NPRED; i++)
75 {
76 state->past_qua_en[i] = MIN_ENERGY;
77 state->past_qua_en_MR122[i] = MIN_ENERGY_MR122;
78 }
79 }
80
81 /*************************************************************************
82 *
83 * FUNCTION: gc_pred_copy()
84 *
85 * PURPOSE: Copy MA predictor state variable
86 *
87 *************************************************************************/
88 void
89 gc_pred_copy(
90 gc_predState *st_src, /* i : State struct */
91 gc_predState *st_dest /* o : State struct */
92 )
93 {
94 Copy (st_src->past_qua_en, st_dest->past_qua_en, NPRED);
95 Copy (st_src->past_qua_en_MR122, st_dest->past_qua_en_MR122, NPRED);
96 }
97
98 /*************************************************************************
99 *
100 * FUNCTION: gc_pred()
101 *
102 * PURPOSE: MA prediction of the innovation energy
103 * (in dB/(20*log10(2))) with mean removed).
104 *
105 *************************************************************************/
106 void
107 gc_pred(
108 gc_predState *st, /* i/o: State struct */
109 enum Mode mode, /* i : AMR mode */
110 Word16 *code, /* i : innovative codebook vector (L_SUBFR) */
111 /* MR122: Q12, other modes: Q13 */
112 Word16 *exp_gcode0, /* o : exponent of predicted gain factor, Q0 */
113 Word16 *frac_gcode0,/* o : fraction of predicted gain factor Q15 */
114 Word16 *exp_en, /* o : exponent of innovation energy, Q0 */
115 /* (only calculated for MR795) */
116 Word16 *frac_en /* o : fraction of innovation energy, Q15 */
117 /* (only calculated for MR795) */
118 )
119 {
120 Word16 i;
121 Word32 ener_code;
122 Word16 exp, frac;
123
124 /*-------------------------------------------------------------------*
125 * energy of code: *
126 * ~~~~~~~~~~~~~~~ *
127 * ener_code = sum(code[i]^2) *
128 *-------------------------------------------------------------------*/
129 ener_code = L_mac((Word32) 0, code[0], code[0]);
130 /* MR122: Q12*Q12 -> Q25 */
131 /* others: Q13*Q13 -> Q27 */
132 for (i = 1; i < L_SUBFR; i++)
133 ener_code = L_mac(ener_code, code[i], code[i]);
134
135 test ();
136 if (sub (mode, MR122) == 0)
137 {
138 Word32 ener;
139
140 /* ener_code = ener_code / lcode; lcode = 40; 1/40 = 26214 Q20 */
141 ener_code = L_mult (round (ener_code), 26214); /* Q9 * Q20 -> Q30 */
142
143 /*-------------------------------------------------------------------*
144 * energy of code: *
145 * ~~~~~~~~~~~~~~~ *
146 * ener_code(Q17) = 10 * Log10(energy) / constant *
147 * = 1/2 * Log2(energy) *
148 * constant = 20*Log10(2) *
149 *-------------------------------------------------------------------*/
150 /* ener_code = 1/2 * Log2(ener_code); Note: Log2=log2+30 */
151 Log2(ener_code, &exp, &frac);
152 ener_code = L_Comp (sub (exp, 30), frac); /* Q16 for log() */
153 /* ->Q17 for 1/2 log()*/
154
155 /*-------------------------------------------------------------------*
156 * predicted energy: *
157 * ~~~~~~~~~~~~~~~~~ *
158 * ener(Q24) = (Emean + sum{pred[i]*past_en[i]})/constant *
159 * = MEAN_ENER + sum(pred[i]*past_qua_en[i]) *
160 * constant = 20*Log10(2) *
161 *-------------------------------------------------------------------*/
162
163 ener = MEAN_ENER_MR122; move32 (); /* Q24 (Q17) */
164 for (i = 0; i < NPRED; i++)
165 {
166 ener = L_mac (ener, st->past_qua_en_MR122[i], pred_MR122[i]);
167 /* Q10 * Q13 -> Q24 */
168 /* Q10 * Q6 -> Q17 */
169 }
170
171 /*-------------------------------------------------------------------*
172 * predicted codebook gain *
173 * ~~~~~~~~~~~~~~~~~~~~~~~ *
174 * gc0 = Pow10( (ener*constant - ener_code*constant) / 20 ) *
175 * = Pow2(ener-ener_code) *
176 * = Pow2(int(d)+frac(d)) *
177 * *
178 * (store exp and frac for pow2()) *
179 *-------------------------------------------------------------------*/
180
181 ener = L_shr (L_sub (ener, ener_code), 1); /* Q16 */
182 L_Extract(ener, exp_gcode0, frac_gcode0);
183 }
184 else /* all modes except 12.2 */
185 {
186 Word32 L_tmp;
187 Word16 exp_code, gcode0;
188
189 /*-----------------------------------------------------------------*
190 * Compute: means_ener - 10log10(ener_code/ L_sufr) *
191 *-----------------------------------------------------------------*/
192
193 exp_code = norm_l (ener_code);
194 ener_code = L_shl (ener_code, exp_code);
195
196 /* Log2 = log2 + 27 */
197 Log2_norm (ener_code, exp_code, &exp, &frac);
198
199 /* fact = 10/log2(10) = 3.01 = 24660 Q13 */
200 L_tmp = Mpy_32_16(exp, frac, -24660); /* Q0.Q15 * Q13 -> Q14 */
201
202 /* L_tmp = means_ener - 10log10(ener_code/L_SUBFR)
203 * = means_ener - 10log10(ener_code) + 10log10(L_SUBFR)
204 * = K - fact * Log2(ener_code)
205 * = K - fact * log2(ener_code) - fact*27
206 *
207 * ==> K = means_ener + fact*27 + 10log10(L_SUBFR)
208 *
209 * means_ener = 33 = 540672 Q14 (MR475, MR515, MR59)
210 * means_ener = 28.75 = 471040 Q14 (MR67)
211 * means_ener = 30 = 491520 Q14 (MR74)
212 * means_ener = 36 = 589824 Q14 (MR795)
213 * means_ener = 33 = 540672 Q14 (MR102)
214 * 10log10(L_SUBFR) = 16.02 = 262481.51 Q14
215 * fact * 27 = 1331640 Q14
216 * -----------------------------------------
217 * (MR475, MR515, MR59) K = 2134793.51 Q14 ~= 16678 * 64 * 2
218 * (MR67) K = 2065161.51 Q14 ~= 32268 * 32 * 2
219 * (MR74) K = 2085641.51 Q14 ~= 32588 * 32 * 2
220 * (MR795) K = 2183945.51 Q14 ~= 17062 * 64 * 2
221 * (MR102) K = 2134793.51 Q14 ~= 16678 * 64 * 2
222 */
223
224 if (test (), sub (mode, MR102) == 0)
225 {
226 /* mean = 33 dB */
227 L_tmp = L_mac(L_tmp, 16678, 64); /* Q14 */
228 }
229 else if (test (), sub (mode, MR795) == 0)
230 {
231 /* ener_code = <xn xn> * 2^27*2^exp_code
232 frac_en = ener_code / 2^16
233 = <xn xn> * 2^11*2^exp_code
234 <xn xn> = <xn xn>*2^11*2^exp * 2^exp_en
235 := frac_en * 2^exp_en
236
237 ==> exp_en = -11-exp_code;
238 */
239 *frac_en = extract_h (ener_code); move16 ();
240 *exp_en = sub (-11, exp_code); move16 ();
241
242 /* mean = 36 dB */
243 L_tmp = L_mac(L_tmp, 17062, 64); /* Q14 */
244 }
245 else if (test (), sub (mode, MR74) == 0)
246 {
247 /* mean = 30 dB */
248 L_tmp = L_mac(L_tmp, 32588, 32); /* Q14 */
249 }
250 else if (test (), sub (mode, MR67) == 0)
251 {
252 /* mean = 28.75 dB */
253 L_tmp = L_mac(L_tmp, 32268, 32); /* Q14 */
254 }
255 else /* MR59, MR515, MR475 */
256 {
257 /* mean = 33 dB */
258 L_tmp = L_mac(L_tmp, 16678, 64); /* Q14 */
259 }
260
261 /*-----------------------------------------------------------------*
262 * Compute gcode0. *
263 * = Sum(i=0,3) pred[i]*past_qua_en[i] - ener_code + mean_ener *
264 *-----------------------------------------------------------------*/
265
266 L_tmp = L_shl(L_tmp, 10); /* Q24 */
267 for (i = 0; i < 4; i++)
268 L_tmp = L_mac(L_tmp, pred[i], st->past_qua_en[i]);
269 /* Q13 * Q10 -> Q24 */
270
271 gcode0 = extract_h(L_tmp); /* Q8 */
272
273 /*-----------------------------------------------------------------*
274 * gcode0 = pow(10.0, gcode0/20) *
275 * = pow(2, 3.3219*gcode0/20) *
276 * = pow(2, 0.166*gcode0) *
277 *-----------------------------------------------------------------*/
278
279 /* 5439 Q15 = 0.165985 */
280 /* (correct: 1/(20*log10(2)) 0.166096 = 5443 Q15) */
281 test ();
282 if (sub (mode, MR74) == 0) /* For IS641 bitexactness */
283 L_tmp = L_mult(gcode0, 5439); /* Q8 * Q15 -> Q24 */
284 else
285 L_tmp = L_mult(gcode0, 5443); /* Q8 * Q15 -> Q24 */
286
287 L_tmp = L_shr(L_tmp, 8); /* -> Q16 */
288 L_Extract(L_tmp, exp_gcode0, frac_gcode0); /* -> Q0.Q15 */
289 }
290 }
291
292
293 /*************************************************************************
294 *
295 * FUNCTION: gc_pred_update()
296 *
297 * PURPOSE: update MA predictor with last quantized energy
298 *
299 *************************************************************************/
300 void gc_pred_update(
301 gc_predState *st, /* i/o: State struct */
302 Word16 qua_ener_MR122, /* i : quantized energy for update, Q10 */
303 /* (log2(qua_err)) */
304 Word16 qua_ener /* i : quantized energy for update, Q10 */
305 /* (20*log10(qua_err)) */
306 )
307 {
308 Word16 i;
309
310 for (i = 3; i > 0; i--)
311 {
312 st->past_qua_en[i] = st->past_qua_en[i - 1]; move16 ();
313 st->past_qua_en_MR122[i] = st->past_qua_en_MR122[i - 1]; move16 ();
314 }
315
316 st->past_qua_en_MR122[0] = qua_ener_MR122; /* log2 (qua_err), Q10 */
317 move16 ();
318 st->past_qua_en[0] = qua_ener; /* 20*log10(qua_err), Q10 */
319 move16 ();
320 }
321
322 /*************************************************************************
323 *
324 * FUNCTION: gc_pred_average_limited()
325 *
326 * PURPOSE: get average of MA predictor state values (with a lower limit)
327 * [used in error concealment]
328 *
329 *************************************************************************/
330 void gc_pred_average_limited(
331 gc_predState *st, /* i: State struct */
332 Word16 *ener_avg_MR122, /* o: everaged quantized energy, Q10 */
333 /* (log2(qua_err)) */
334 Word16 *ener_avg /* o: averaged quantized energy, Q10 */
335 /* (20*log10(qua_err)) */
336 )
337 {
338 Word16 av_pred_en;
339 Word16 i;
340
341 /* do average in MR122 mode (log2() domain) */
342 av_pred_en = 0; move16 ();
343 for (i = 0; i < NPRED; i++)
344 {
345 av_pred_en = add (av_pred_en, st->past_qua_en_MR122[i]);
346 }
347
348 /* av_pred_en = 0.25*av_pred_en */
349 av_pred_en = mult (av_pred_en, 8192);
350
351 /* if (av_pred_en < -14/(20Log10(2))) av_pred_en = .. */
352 test ();
353 if (sub (av_pred_en, MIN_ENERGY_MR122) < 0)
354 {
355 av_pred_en = MIN_ENERGY_MR122; move16 ();
356 }
357 *ener_avg_MR122 = av_pred_en; move16 ();
358
359 /* do average for other modes (20*log10() domain) */
360 av_pred_en = 0; move16 ();
361 for (i = 0; i < NPRED; i++)
362 {
363 av_pred_en = add (av_pred_en, st->past_qua_en[i]);
364 }
365
366 /* av_pred_en = 0.25*av_pred_en */
367 av_pred_en = mult (av_pred_en, 8192);
368
369 /* if (av_pred_en < -14) av_pred_en = .. */
370 test ();
371 if (sub (av_pred_en, MIN_ENERGY) < 0)
372 {
373 av_pred_en = MIN_ENERGY; move16 ();
374 }
375 *ener_avg = av_pred_en; move16 ();
376 }