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