1 /* ------------------------------------------------------------------
2 * Copyright (C) 1998-2009 PacketVideo
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13 * express or implied.
14 * See the License for the specific language governing permissions
15 * and limitations under the License.
16 * -------------------------------------------------------------------
17 */
18 /****************************************************************************************
19 Portions of this file are derived from the following 3GPP standard:
20
21 3GPP TS 26.073
22 ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
23 Available from http://www.3gpp.org
24
25 (C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
26 Permission to distribute, modify and use this file under the standard license
27 terms listed above has been obtained from the copyright holder.
28 ****************************************************************************************/
29 /*
30 ------------------------------------------------------------------------------
31
32
33
34 Pathname: ./audio/gsm-amr/c/src/qgain795.c
35 Functions: MR795_gain_code_quant3
36 MR795_gain_code_quant_mod
37 MR795_gain_quant
38
39 Date: 02/04/2002
40
41 ------------------------------------------------------------------------------
42 REVISION HISTORY
43
44 Description: Updated template used to PV coding template.
45 Changed to accept the pOverflow flag for EPOC compatibility.
46
47 Description:
48 (1) Removed optimization -- mult(i, 3, pOverflow) is NOT the same as adding
49 i to itself 3 times. The reason is because the mult function does a
50 right shift by 15, which will obliterate smaller numbers.
51
52 Description: Replaced OSCL mem type functions and eliminated include
53 files that now are chosen by OSCL definitions
54
55 Description: Replaced "int" and/or "char" with OSCL defined types.
56
57 Description: Changed round function name to pv_round to avoid conflict with
58 round function in C standard library.
59
60 Description: Added #ifdef __cplusplus around extern'ed table.
61
62 Description:
63
64 ------------------------------------------------------------------------------
65 MODULE DESCRIPTION
66
67
68 ------------------------------------------------------------------------------
69 */
70
71 /*----------------------------------------------------------------------------
72 ; INCLUDES
73 ----------------------------------------------------------------------------*/
74 #include "qgain795.h"
75 #include "typedef.h"
76 #include "basic_op.h"
77 #include "cnst.h"
78 #include "log2.h"
79 #include "pow2.h"
80 #include "sqrt_l.h"
81 #include "g_adapt.h"
82 #include "calc_en.h"
83 #include "q_gain_p.h"
84
85
86 /*--------------------------------------------------------------------------*/
87 #ifdef __cplusplus
88 extern "C"
89 {
90 #endif
91
92 /*----------------------------------------------------------------------------
93 ; MACROS
94 ; Define module specific macros here
95 ----------------------------------------------------------------------------*/
96
97 /*----------------------------------------------------------------------------
98 ; DEFINES
99 ; Include all pre-processor statements here. Include conditional
100 ; compile variables also.
101 ----------------------------------------------------------------------------*/
102 #define NB_QUA_CODE 32
103
104 /*----------------------------------------------------------------------------
105 ; LOCAL FUNCTION DEFINITIONS
106 ; Function Prototype declaration
107 ----------------------------------------------------------------------------*/
108
109 /*----------------------------------------------------------------------------
110 ; LOCAL VARIABLE DEFINITIONS
111 ; Variable declaration - defined here and used outside this module
112 ----------------------------------------------------------------------------*/
113
114 /*----------------------------------------------------------------------------
115 ; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
116 ; Declare variables used in this module but defined elsewhere
117 ----------------------------------------------------------------------------*/
118 extern const Word16 qua_gain_code[NB_QUA_CODE*3];
119
120
121 /*--------------------------------------------------------------------------*/
122 #ifdef __cplusplus
123 }
124 #endif
125
126 /*
127 ------------------------------------------------------------------------------
128 FUNCTION NAME: MR795_gain_code_quant3
129 ------------------------------------------------------------------------------
130 INPUT AND OUTPUT DEFINITIONS
131
132 Inputs:
133 exp_gcode0 -- Word16 -- predicted CB gain (exponent), Q0
134 gcode0 -- Word16 -- predicted CB gain (norm.)
135 g_pitch_cand[] -- Word16 array -- Pitch gain candidates (3), Q14
136 g_pitch_cind[] -- Word16 array -- Pitch gain cand. indices (3), Q0
137 frac_coeff[] -- Word16 array -- coefficients (5), Q15
138 exp_coeff[] -- Word16 array -- energy coefficients (5), Q0
139 coefficients from calc_filt_ener()
140
141 Outputs:
142 gain_pit -- Pointer to Word16 -- Pitch gain, Q14
143 gain_pit_ind -- Pointer to Word16 -- Pitch gain index, Q0
144 gain_cod -- Pointer to Word16 -- Code gain, Q1
145 gain_cod_ind -- Pointer to Word16 -- Code gain index, Q0
146 qua_ener_MR122 -- Pointer to Word16 -- quantized energy error, Q10
147 (for MR122 MA predictor update)
148
149 qua_ener -- Pointer to Word16 -- quantized energy error, Q10
150 (for other MA predictor update)
151
152 pOverflow -- Pointer to Flag -- overflow indicator
153
154 Returns:
155 None
156
157 Global Variables Used:
158 None
159
160 Local Variables Needed:
161 None
162
163 ------------------------------------------------------------------------------
164 FUNCTION DESCRIPTION
165
166 PURPOSE: Pre-quantization of codebook gains, given three possible
167 LTP gains (using predicted codebook gain)
168 ------------------------------------------------------------------------------
169 REQUIREMENTS
170
171 None
172
173 ------------------------------------------------------------------------------
174 REFERENCES
175
176 qgain795.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
177
178 ------------------------------------------------------------------------------
179 PSEUDO-CODE
180
181
182 ------------------------------------------------------------------------------
183 RESOURCES USED [optional]
184
185 When the code is written for a specific target processor the
186 the resources used should be documented below.
187
188 HEAP MEMORY USED: x bytes
189
190 STACK MEMORY USED: x bytes
191
192 CLOCK CYCLES: (cycle count equation for this function) + (variable
193 used to represent cycle count for each subroutine
194 called)
195 where: (cycle count variable) = cycle count for [subroutine
196 name]
197
198 ------------------------------------------------------------------------------
199 CAUTION [optional]
200 [State any special notes, constraints or cautions for users of this function]
201
202 ------------------------------------------------------------------------------
203 */
204
205 static void
MR795_gain_code_quant3(Word16 exp_gcode0,Word16 gcode0,Word16 g_pitch_cand[],Word16 g_pitch_cind[],Word16 frac_coeff[],Word16 exp_coeff[],Word16 * gain_pit,Word16 * gain_pit_ind,Word16 * gain_cod,Word16 * gain_cod_ind,Word16 * qua_ener_MR122,Word16 * qua_ener,Flag * pOverflow)206 MR795_gain_code_quant3(
207 Word16 exp_gcode0, /* i : predicted CB gain (exponent), Q0 */
208 Word16 gcode0, /* i : predicted CB gain (norm.), Q14 */
209 Word16 g_pitch_cand[], /* i : Pitch gain candidates (3), Q14 */
210 Word16 g_pitch_cind[], /* i : Pitch gain cand. indices (3), Q0 */
211 Word16 frac_coeff[], /* i : coefficients (5), Q15 */
212 Word16 exp_coeff[], /* i : energy coefficients (5), Q0 */
213 /* coefficients from calc_filt_ener()*/
214 Word16 *gain_pit, /* o : Pitch gain, Q14 */
215 Word16 *gain_pit_ind, /* o : Pitch gain index, Q0 */
216 Word16 *gain_cod, /* o : Code gain, Q1 */
217 Word16 *gain_cod_ind, /* o : Code gain index, Q0 */
218 Word16 *qua_ener_MR122, /* o : quantized energy error, Q10 */
219 /* (for MR122 MA predictor update) */
220 Word16 *qua_ener, /* o : quantized energy error, Q10 */
221 /* (for other MA predictor update) */
222 Flag *pOverflow /* o : overflow indicator */
223 )
224 {
225 const Word16 *p;
226 Word16 i;
227 Word16 j;
228 Word16 cod_ind;
229 Word16 pit_ind;
230 Word16 e_max;
231 Word16 exp_code;
232 Word16 g_pitch;
233 Word16 g2_pitch;
234 Word16 g_code;
235 Word16 g2_code_h;
236 Word16 g2_code_l;
237 Word16 g_pit_cod_h;
238 Word16 g_pit_cod_l;
239 Word16 coeff[5];
240 Word16 coeff_lo[5];
241 Word16 exp_max[5];
242 Word32 L_tmp;
243 Word32 L_tmp0;
244 Word32 dist_min;
245
246 /*
247 * The error energy (sum) to be minimized consists of five terms, t[0..4].
248 *
249 * t[0] = gp^2 * <y1 y1>
250 * t[1] = -2*gp * <xn y1>
251 * t[2] = gc^2 * <y2 y2>
252 * t[3] = -2*gc * <xn y2>
253 * t[4] = 2*gp*gc * <y1 y2>
254 *
255 */
256
257 /* determine the scaling exponent for g_code: ec = ec0 - 10 */
258 exp_code = sub(exp_gcode0, 10, pOverflow);
259
260 /* calculate exp_max[i] = s[i]-1 */
261 exp_max[0] = sub(exp_coeff[0], 13, pOverflow);
262 exp_max[1] = sub(exp_coeff[1], 14, pOverflow);
263 exp_max[2] = add(exp_coeff[2], add(15, shl(exp_code, 1, pOverflow), pOverflow), pOverflow);
264 exp_max[3] = add(exp_coeff[3], exp_code, pOverflow);
265 exp_max[4] = add(exp_coeff[4], add(exp_code, 1, pOverflow), pOverflow);
266
267
268 /*-------------------------------------------------------------------*
269 * Find maximum exponent: *
270 * ~~~~~~~~~~~~~~~~~~~~~~ *
271 * *
272 * For the sum operation, all terms must have the same scaling; *
273 * that scaling should be low enough to prevent overflow. There- *
274 * fore, the maximum scale is determined and all coefficients are *
275 * re-scaled: *
276 * *
277 * e_max = max(exp_max[i]) + 1; *
278 * e = exp_max[i]-e_max; e <= 0! *
279 * c[i] = c[i]*2^e *
280 *-------------------------------------------------------------------*/
281
282 e_max = exp_max[0];
283 for (i = 1; i < 5; i++) /* implemented flattened */
284 {
285 if (exp_max[i] > e_max)
286 {
287 e_max = exp_max[i];
288 }
289 }
290
291 e_max = add(e_max, 1, pOverflow); /* To avoid overflow */
292
293 for (i = 0; i < 5; i++)
294 {
295 j = sub(e_max, exp_max[i], pOverflow);
296 L_tmp = L_deposit_h(frac_coeff[i]);
297 L_tmp = L_shr(L_tmp, j, pOverflow);
298 L_Extract(L_tmp, &coeff[i], &coeff_lo[i], pOverflow);
299 }
300
301
302 /*-------------------------------------------------------------------*
303 * Codebook search: *
304 * ~~~~~~~~~~~~~~~~ *
305 * *
306 * For each of the candiates LTP gains in g_pitch_cand[], the terms *
307 * t[0..4] are calculated from the values in the table (and the *
308 * pitch gain candidate) and summed up; the result is the mean *
309 * squared error for the LPT/CB gain pair. The index for the mini- *
310 * mum MSE is stored and finally used to retrieve the quantized CB *
311 * gain *
312 *-------------------------------------------------------------------*/
313
314 /* start with "infinite" MSE */
315 dist_min = MAX_32;
316 cod_ind = 0;
317 pit_ind = 0;
318
319 /* loop through LTP gain candidates */
320 for (j = 0; j < 3; j++)
321 {
322 /* pre-calculate terms only dependent on pitch gain */
323 g_pitch = g_pitch_cand[j];
324 g2_pitch = mult(g_pitch, g_pitch, pOverflow);
325 L_tmp0 = Mpy_32_16(coeff[0], coeff_lo[0], g2_pitch, pOverflow);
326 L_tmp0 = Mac_32_16(L_tmp0, coeff[1], coeff_lo[1], g_pitch, pOverflow);
327
328 p = &qua_gain_code[0];
329 for (i = 0; i < NB_QUA_CODE; i++)
330 {
331 g_code = *p++; /* this is g_fac Q11 */
332 p++; /* skip log2(g_fac) */
333 p++; /* skip 20*log10(g_fac) */
334
335 g_code = mult(g_code, gcode0, pOverflow);
336
337 L_tmp = L_mult(g_code, g_code, pOverflow);
338 L_Extract(L_tmp, &g2_code_h, &g2_code_l, pOverflow);
339
340 L_tmp = L_mult(g_code, g_pitch, pOverflow);
341 L_Extract(L_tmp, &g_pit_cod_h, &g_pit_cod_l, pOverflow);
342
343 L_tmp = Mac_32(L_tmp0, coeff[2], coeff_lo[2],
344 g2_code_h, g2_code_l, pOverflow);
345 L_tmp = Mac_32_16(L_tmp, coeff[3], coeff_lo[3],
346 g_code, pOverflow);
347 L_tmp = Mac_32(L_tmp, coeff[4], coeff_lo[4],
348 g_pit_cod_h, g_pit_cod_l, pOverflow);
349
350 /* store table index if MSE for this index is lower
351 than the minimum MSE seen so far; also store the
352 pitch gain for this (so far) lowest MSE */
353 if (L_tmp < dist_min)
354 {
355 dist_min = L_tmp;
356 cod_ind = i;
357 pit_ind = j;
358 }
359 }
360 }
361
362 /*------------------------------------------------------------------*
363 * read quantized gains and new values for MA predictor memories *
364 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *
365 *------------------------------------------------------------------*/
366
367 /* Read the quantized gains */
368 p = &qua_gain_code[
369 add(add(cod_ind, cod_ind, pOverflow), cod_ind, pOverflow)];
370
371 g_code = *p++;
372 *qua_ener_MR122 = *p++;
373 *qua_ener = *p;
374
375 /*------------------------------------------------------------------*
376 * calculate final fixed codebook gain: *
377 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *
378 * *
379 * gc = gc0 * g *
380 *------------------------------------------------------------------*/
381
382 L_tmp = L_mult(g_code, gcode0, pOverflow);
383 L_tmp = L_shr(L_tmp, sub(9, exp_gcode0, pOverflow), pOverflow);
384 *gain_cod = extract_h(L_tmp);
385 *gain_cod_ind = cod_ind;
386 *gain_pit = g_pitch_cand[pit_ind];
387 *gain_pit_ind = g_pitch_cind[pit_ind];
388 }
389
390
391 /*
392 ------------------------------------------------------------------------------
393 FUNCTION NAME: MR795_gain_code_quant_mod
394 ------------------------------------------------------------------------------
395 INPUT AND OUTPUT DEFINITIONS
396
397 Inputs:
398 gain_pit -- Word16 -- pitch gain, Q14
399 exp_gcode0 -- Word16 -- predicted CB gain (exponent), Q0
400 gcode0 -- Word16 -- predicted CB gain (norm.), Q14
401 frac_en[] -- Word16 array -- energy coefficients (4), fraction part, Q15
402 exp_en[] -- Word16 array -- energy coefficients (4), exponent part, Q0
403 alpha -- Word16 -- gain adaptor factor (>0), Q15
404
405 gain_cod_unq -- Word16 -- Code gain (unquantized)
406 (scaling: Q10 - exp_gcode0)
407
408 gain_cod -- Pointer to Word16 -- Code gain (pre-/quantized), Q1
409
410 Outputs:
411 qua_ener_MR122 -- Pointer to Word16 -- quantized energy error, Q10
412 (for MR122 MA predictor update)
413 qua_ener -- Pointer to Word16 -- quantized energy error, Q10
414 (for other MA predictor update)
415 pOverflow -- Pointer to Flag -- overflow indicator
416
417 Returns:
418 index of quantization (Word16)
419
420 Global Variables Used:
421 None
422
423 Local Variables Needed:
424 None
425
426 ------------------------------------------------------------------------------
427 FUNCTION DESCRIPTION
428
429 PURPOSE: Modified quantization of the MR795 codebook gain
430
431 Uses pre-computed energy coefficients in frac_en[]/exp_en[]
432
433 frac_en[0]*2^exp_en[0] = <res res> // LP residual energy
434 frac_en[1]*2^exp_en[1] = <exc exc> // LTP residual energy
435 frac_en[2]*2^exp_en[2] = <exc code> // LTP/CB innovation dot product
436 frac_en[3]*2^exp_en[3] = <code code> // CB innovation energy
437 ------------------------------------------------------------------------------
438 REQUIREMENTS
439
440 None
441
442 ------------------------------------------------------------------------------
443 REFERENCES
444
445 qgain795.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
446
447 ------------------------------------------------------------------------------
448 PSEUDO-CODE
449
450
451 ------------------------------------------------------------------------------
452 RESOURCES USED [optional]
453
454 When the code is written for a specific target processor the
455 the resources used should be documented below.
456
457 HEAP MEMORY USED: x bytes
458
459 STACK MEMORY USED: x bytes
460
461 CLOCK CYCLES: (cycle count equation for this function) + (variable
462 used to represent cycle count for each subroutine
463 called)
464 where: (cycle count variable) = cycle count for [subroutine
465 name]
466
467 ------------------------------------------------------------------------------
468 CAUTION [optional]
469 [State any special notes, constraints or cautions for users of this function]
470
471 ------------------------------------------------------------------------------
472 */
473
474 static Word16
MR795_gain_code_quant_mod(Word16 gain_pit,Word16 exp_gcode0,Word16 gcode0,Word16 frac_en[],Word16 exp_en[],Word16 alpha,Word16 gain_cod_unq,Word16 * gain_cod,Word16 * qua_ener_MR122,Word16 * qua_ener,Flag * pOverflow)475 MR795_gain_code_quant_mod( /* o : index of quantization. */
476 Word16 gain_pit, /* i : pitch gain, Q14 */
477 Word16 exp_gcode0, /* i : predicted CB gain (exponent), Q0 */
478 Word16 gcode0, /* i : predicted CB gain (norm.), Q14 */
479 Word16 frac_en[], /* i : energy coefficients (4),
480 fraction part, Q15 */
481 Word16 exp_en[], /* i : energy coefficients (4),
482 eponent part, Q0 */
483 Word16 alpha, /* i : gain adaptor factor (>0), Q15 */
484 Word16 gain_cod_unq, /* i : Code gain (unquantized) */
485 /* (scaling: Q10 - exp_gcode0) */
486 Word16 *gain_cod, /* i/o: Code gain (pre-/quantized), Q1 */
487 Word16 *qua_ener_MR122, /* o : quantized energy error, Q10 */
488 /* (for MR122 MA predictor update) */
489 Word16 *qua_ener, /* o : quantized energy error, Q10 */
490 /* (for other MA predictor update) */
491 Flag *pOverflow /* o : overflow indicator */
492 )
493 {
494 const Word16 *p;
495 Word16 i;
496 Word16 index;
497 Word16 tmp;
498 Word16 one_alpha;
499 Word16 exp;
500 Word16 e_max;
501
502 Word16 g2_pitch;
503 Word16 g_code;
504 Word16 g2_code_h;
505 Word16 g2_code_l;
506 Word16 d2_code_h;
507 Word16 d2_code_l;
508 Word16 coeff[5];
509 Word16 coeff_lo[5];
510 Word16 exp_coeff[5];
511 Word32 L_tmp;
512 Word32 L_t0;
513 Word32 L_t1;
514 Word32 dist_min;
515 Word16 gain_code;
516
517 /*
518 Steps in calculation of the error criterion (dist):
519 ---------------------------------------------------
520
521 underlined = constant; alp = FLP value of alpha, alpha = FIP
522 ----------
523
524
525 ExEn = gp^2 * LtpEn + 2.0*gp*gc[i] * XC + gc[i]^2 * InnEn;
526 ------------ ------ -- -----
527
528 aExEn= alp * ExEn
529 = alp*gp^2*LtpEn + 2.0*alp*gp*XC* gc[i] + alp*InnEn* gc[i]^2
530 -------------- ------------- ---------
531
532 = t[1] + t[2] + t[3]
533
534 dist = d1 + d2;
535
536 d1 = (1.0 - alp) * InnEn * (gcu - gc[i])^2 = t[4]
537 ------------------- ---
538
539 d2 = alp * (ResEn - 2.0 * sqrt(ResEn*ExEn) + ExEn);
540 --- ----- --- -----
541
542 = alp * (sqrt(ExEn) - sqrt(ResEn))^2
543 --- -----------
544
545 = (sqrt(aExEn) - sqrt(alp*ResEn))^2
546 ---------------
547
548 = (sqrt(aExEn) - t[0] )^2
549 ----
550
551 */
552
553 /*
554 * calculate scalings of the constant terms
555 */
556 gain_code = shl(*gain_cod, sub(10, exp_gcode0, pOverflow), pOverflow); /* Q1 -> Q11 (-ec0) */
557 g2_pitch = mult(gain_pit, gain_pit, pOverflow); /* Q14 -> Q13 */
558 /* 0 < alpha <= 0.5 => 0.5 <= 1-alpha < 1, i.e one_alpha is normalized */
559 one_alpha = add(sub(32767, alpha, pOverflow), 1, pOverflow); /* 32768 - alpha */
560
561
562 /* alpha <= 0.5 -> mult. by 2 to keep precision; compensate in exponent */
563 L_t1 = L_mult(alpha, frac_en[1], pOverflow);
564 L_t1 = L_shl(L_t1, 1, pOverflow);
565 tmp = extract_h(L_t1);
566
567 /* directly store in 32 bit variable because no further mult. required */
568 L_t1 = L_mult(tmp, g2_pitch, pOverflow);
569 exp_coeff[1] = sub(exp_en[1], 15, pOverflow);
570
571
572 tmp = extract_h(L_shl(L_mult(alpha, frac_en[2], pOverflow), 1, pOverflow));
573 coeff[2] = mult(tmp, gain_pit, pOverflow);
574 exp = sub(exp_gcode0, 10, pOverflow);
575 exp_coeff[2] = add(exp_en[2], exp, pOverflow);
576
577
578 /* alpha <= 0.5 -> mult. by 2 to keep precision; compensate in exponent */
579 coeff[3] = extract_h(L_shl(L_mult(alpha, frac_en[3], pOverflow), 1, pOverflow));
580 exp = sub(shl(exp_gcode0, 1, pOverflow), 7, pOverflow);
581 exp_coeff[3] = add(exp_en[3], exp, pOverflow);
582
583
584 coeff[4] = mult(one_alpha, frac_en[3], pOverflow);
585 exp_coeff[4] = add(exp_coeff[3], 1, pOverflow);
586
587
588 L_tmp = L_mult(alpha, frac_en[0], pOverflow);
589 /* sqrt_l returns normalized value and 2*exponent
590 -> result = val >> (exp/2)
591 exp_coeff holds 2*exponent for c[0] */
592 /* directly store in 32 bit variable because no further mult. required */
593 L_t0 = sqrt_l_exp(L_tmp, &exp, pOverflow); /* normalization included in sqrt_l_exp */
594 exp = add(exp, 47, pOverflow);
595 exp_coeff[0] = sub(exp_en[0], exp, pOverflow);
596
597 /*
598 * Determine the maximum exponent occuring in the distance calculation
599 * and adjust all fractions accordingly (including a safety margin)
600 *
601 */
602
603 /* find max(e[1..4],e[0]+31) */
604 e_max = add(exp_coeff[0], 31, pOverflow);
605 for (i = 1; i <= 4; i++)
606 {
607 if (exp_coeff[i] > e_max)
608 {
609 e_max = exp_coeff[i];
610 }
611 }
612
613 /* scale c[1] (requires no further multiplication) */
614 tmp = sub(e_max, exp_coeff[1], pOverflow);
615 L_t1 = L_shr(L_t1, tmp, pOverflow);
616
617 /* scale c[2..4] (used in Mpy_32_16 in the quantizer loop) */
618 for (i = 2; i <= 4; i++)
619 {
620 tmp = sub(e_max, exp_coeff[i], pOverflow);
621 L_tmp = L_deposit_h(coeff[i]);
622 L_tmp = L_shr(L_tmp, tmp, pOverflow);
623 L_Extract(L_tmp, &coeff[i], &coeff_lo[i], pOverflow);
624 }
625
626 /* scale c[0] (requires no further multiplication) */
627 exp = sub(e_max, 31, pOverflow); /* new exponent */
628 tmp = sub(exp, exp_coeff[0], pOverflow);
629 L_t0 = L_shr(L_t0, shr(tmp, 1, pOverflow), pOverflow);
630 /* perform correction by 1/sqrt(2) if exponent difference is odd */
631 if ((tmp & 0x1) != 0)
632 {
633 L_Extract(L_t0, &coeff[0], &coeff_lo[0], pOverflow);
634 L_t0 = Mpy_32_16(coeff[0], coeff_lo[0],
635 23170, pOverflow); /* 23170 Q15 = 1/sqrt(2)*/
636 }
637
638 /* search the quantizer table for the lowest value
639 of the search criterion */
640 dist_min = MAX_32;
641 index = 0;
642 p = &qua_gain_code[0];
643
644 for (i = 0; i < NB_QUA_CODE; i++)
645 {
646 g_code = *p++; /* this is g_fac (Q11) */
647 p++; /* skip log2(g_fac) */
648 p++; /* skip 20*log10(g_fac) */
649 g_code = mult(g_code, gcode0, pOverflow);
650
651 /* only continue if gc[i] < 2.0*gc
652 which is equiv. to g_code (Q10-ec0) < gain_code (Q11-ec0) */
653
654 if (g_code >= gain_code)
655 {
656 break;
657 }
658
659 L_tmp = L_mult(g_code, g_code, pOverflow);
660 L_Extract(L_tmp, &g2_code_h, &g2_code_l, pOverflow);
661
662 tmp = sub(g_code, gain_cod_unq, pOverflow);
663 L_tmp = L_mult(tmp, tmp, pOverflow);
664 L_Extract(L_tmp, &d2_code_h, &d2_code_l, pOverflow);
665
666 /* t2, t3, t4 */
667 L_tmp = Mac_32_16(L_t1, coeff[2], coeff_lo[2], g_code, pOverflow);
668 L_tmp = Mac_32(L_tmp, coeff[3], coeff_lo[3], g2_code_h, g2_code_l, pOverflow);
669
670 L_tmp = sqrt_l_exp(L_tmp, &exp, pOverflow);
671 L_tmp = L_shr(L_tmp, shr(exp, 1, pOverflow), pOverflow);
672
673 /* d2 */
674 tmp = pv_round(L_sub(L_tmp, L_t0, pOverflow), pOverflow);
675 L_tmp = L_mult(tmp, tmp, pOverflow);
676
677 /* dist */
678 L_tmp = Mac_32(L_tmp, coeff[4], coeff_lo[4], d2_code_h, d2_code_l, pOverflow);
679
680 /* store table index if distance measure for this
681 index is lower than the minimum seen so far */
682 if (L_tmp < dist_min)
683 {
684 dist_min = L_tmp;
685 index = i;
686 }
687 }
688
689 /*------------------------------------------------------------------*
690 * read quantized gains and new values for MA predictor memories *
691 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *
692 *------------------------------------------------------------------*/
693
694 /* Read the quantized gains */
695 p = &qua_gain_code[add(add(index, index, pOverflow), index, pOverflow)];
696 g_code = *p++;
697 *qua_ener_MR122 = *p++;
698 *qua_ener = *p;
699
700 /*------------------------------------------------------------------*
701 * calculate final fixed codebook gain: *
702 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *
703 * *
704 * gc = gc0 * g *
705 *------------------------------------------------------------------*/
706
707 L_tmp = L_mult(g_code, gcode0, pOverflow);
708 L_tmp = L_shr(L_tmp, sub(9, exp_gcode0, pOverflow), pOverflow);
709 *gain_cod = extract_h(L_tmp);
710
711 return index;
712 }
713
714 /*
715 ------------------------------------------------------------------------------
716 FUNCTION NAME: MR795_gain_quant
717 ------------------------------------------------------------------------------
718 INPUT AND OUTPUT DEFINITIONS
719 MR795_gain_quant(
720
721
722 Inputs:
723 adapt_st -- Pointer to GainAdaptState -- gain adapter state structure
724 res -- Word16 array -- LP residual, Q0
725 exc -- Word16 array -- LTP excitation (unfiltered), Q0
726 code -- Word16 array -- CB innovation (unfiltered), Q13
727 frac_coeff -- Word16 array -- coefficients (5), Q15
728 exp_coeff -- Word16 array -- energy coefficients (5), Q0
729 coefficients from calc_filt_ener()
730 exp_code_en -- Word16 -- innovation energy (exponent), Q0
731 frac_code_en -- Word16 -- innovation energy (fraction), Q15
732 exp_gcode0 -- Word16 -- predicted CB gain (exponent), Q0
733 frac_gcode0 -- Word16 -- predicted CB gain (fraction), Q15
734 L_subfr -- Word16 -- Subframe length
735 cod_gain_frac -- Word16 -- opt. codebook gain (fraction),Q15
736 cod_gain_exp -- Word16 -- opt. codebook gain (exponent), Q0
737 gp_limit -- Word16 -- pitch gain limit
738 gain_pit -- Pointer to Word16 -- Pitch gain, Q14
739
740 Output
741 adapt_st -- Pointer to GainAdaptState -- gain adapter state structure
742 gain_pit -- Pointer to Word16 -- Pitch gain, Q14
743
744 gain_pit -- Pointer to Word16 -- Pitch gain, Q14
745 gain_cod -- Pointer to Word16 -- Code gain, Q1
746 qua_ener_MR122 -- Pointer to Word16 -- quantized energy error, Q10
747 (for MR122 MA predictor update)
748
749 qua_ener -- Pointer to Word16 -- quantized energy error, Q10
750 (for other MA predictor update)
751
752 anap -- Double Pointer to Word16 -- Index of quantization
753 (first gain pitch, then code pitch)
754
755 pOverflow -- Pointer to Flag -- overflow indicator
756
757 Returns:
758 None
759
760 Global Variables Used:
761 None
762
763 Local Variables Needed:
764 None
765
766 ------------------------------------------------------------------------------
767 FUNCTION DESCRIPTION
768
769 pitch and codebook quantization for MR795
770 ------------------------------------------------------------------------------
771 REQUIREMENTS
772
773 None
774
775 ------------------------------------------------------------------------------
776 REFERENCES
777
778 qgain795.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
779
780 ------------------------------------------------------------------------------
781 PSEUDO-CODE
782
783
784 ------------------------------------------------------------------------------
785 RESOURCES USED [optional]
786
787 When the code is written for a specific target processor the
788 the resources used should be documented below.
789
790 HEAP MEMORY USED: x bytes
791
792 STACK MEMORY USED: x bytes
793
794 CLOCK CYCLES: (cycle count equation for this function) + (variable
795 used to represent cycle count for each subroutine
796 called)
797 where: (cycle count variable) = cycle count for [subroutine
798 name]
799
800 ------------------------------------------------------------------------------
801 CAUTION [optional]
802 [State any special notes, constraints or cautions for users of this function]
803
804 ------------------------------------------------------------------------------
805 */
806
807 void
MR795_gain_quant(GainAdaptState * adapt_st,Word16 res[],Word16 exc[],Word16 code[],Word16 frac_coeff[],Word16 exp_coeff[],Word16 exp_code_en,Word16 frac_code_en,Word16 exp_gcode0,Word16 frac_gcode0,Word16 L_subfr,Word16 cod_gain_frac,Word16 cod_gain_exp,Word16 gp_limit,Word16 * gain_pit,Word16 * gain_cod,Word16 * qua_ener_MR122,Word16 * qua_ener,Word16 ** anap,Flag * pOverflow)808 MR795_gain_quant(
809 GainAdaptState *adapt_st, /* i/o: gain adapter state structure */
810 Word16 res[], /* i : LP residual, Q0 */
811 Word16 exc[], /* i : LTP excitation (unfiltered), Q0 */
812 Word16 code[], /* i : CB innovation (unfiltered), Q13 */
813 Word16 frac_coeff[], /* i : coefficients (5), Q15 */
814 Word16 exp_coeff[], /* i : energy coefficients (5), Q0 */
815 /* coefficients from calc_filt_ener() */
816 Word16 exp_code_en, /* i : innovation energy (exponent), Q0 */
817 Word16 frac_code_en, /* i : innovation energy (fraction), Q15 */
818 Word16 exp_gcode0, /* i : predicted CB gain (exponent), Q0 */
819 Word16 frac_gcode0, /* i : predicted CB gain (fraction), Q15 */
820 Word16 L_subfr, /* i : Subframe length */
821 Word16 cod_gain_frac, /* i : opt. codebook gain (fraction),Q15 */
822 Word16 cod_gain_exp, /* i : opt. codebook gain (exponent), Q0 */
823 Word16 gp_limit, /* i : pitch gain limit */
824 Word16 *gain_pit, /* i/o: Pitch gain, Q14 */
825 Word16 *gain_cod, /* o : Code gain, Q1 */
826 Word16 *qua_ener_MR122, /* o : quantized energy error, Q10 */
827 /* (for MR122 MA predictor update) */
828 Word16 *qua_ener, /* o : quantized energy error, Q10 */
829 /* (for other MA predictor update) */
830 Word16 **anap, /* o : Index of quantization */
831 /* (first gain pitch, then code pitch)*/
832 Flag *pOverflow /* o : overflow indicator */
833 )
834 {
835 Word16 frac_en[4];
836 Word16 exp_en[4];
837 Word16 ltpg, alpha, gcode0;
838 Word16 g_pitch_cand[3]; /* pitch gain candidates Q14 */
839 Word16 g_pitch_cind[3]; /* pitch gain indices Q0 */
840 Word16 gain_pit_index;
841 Word16 gain_cod_index;
842 Word16 exp;
843 Word16 gain_cod_unq; /* code gain (unq.) Q(10-exp_gcode0) */
844
845
846 /* get list of candidate quantized pitch gain values
847 * and corresponding quantization indices
848 */
849 gain_pit_index = q_gain_pitch(MR795, gp_limit, gain_pit,
850 g_pitch_cand, g_pitch_cind, pOverflow);
851
852 /*-------------------------------------------------------------------*
853 * predicted codebook gain *
854 * ~~~~~~~~~~~~~~~~~~~~~~~ *
855 * gc0 = 2^exp_gcode0 + 2^frac_gcode0 *
856 * *
857 * gcode0 (Q14) = 2^14*2^frac_gcode0 = gc0 * 2^(14-exp_gcode0) *
858 *-------------------------------------------------------------------*/
859 gcode0 = (Word16)(Pow2(14, frac_gcode0, pOverflow)); /* Q14 */
860
861 /* pre-quantization of codebook gain
862 * (using three pitch gain candidates);
863 * result: best guess of pitch gain and code gain
864 */
865 MR795_gain_code_quant3(
866 exp_gcode0, gcode0, g_pitch_cand, g_pitch_cind,
867 frac_coeff, exp_coeff,
868 gain_pit, &gain_pit_index, gain_cod, &gain_cod_index,
869 qua_ener_MR122, qua_ener, pOverflow);
870
871 /* calculation of energy coefficients and LTP coding gain */
872 calc_unfilt_energies(res, exc, code, *gain_pit, L_subfr,
873 frac_en, exp_en, <pg, pOverflow);
874
875 /* run gain adaptor, calculate alpha factor to balance LTP/CB gain
876 * (this includes the gain adaptor update)
877 * Note: ltpg = 0 if frac_en[0] == 0, so the update is OK in that case
878 */
879 gain_adapt(adapt_st, ltpg, *gain_cod, &alpha, pOverflow);
880
881 /* if this is a very low energy signal (threshold: see
882 * calc_unfilt_energies) or alpha <= 0 then don't run the modified quantizer
883 */
884 if (frac_en[0] != 0 && alpha > 0)
885 {
886 /* innovation energy <cod cod> was already computed in gc_pred() */
887 /* (this overwrites the LtpResEn which is no longer needed) */
888 frac_en[3] = frac_code_en;
889 exp_en[3] = exp_code_en;
890
891 /* store optimum codebook gain in Q(10-exp_gcode0) */
892 exp = add(sub(cod_gain_exp, exp_gcode0, pOverflow), 10, pOverflow);
893 gain_cod_unq = shl(cod_gain_frac, exp, pOverflow);
894
895 /* run quantization with modified criterion */
896 gain_cod_index = MR795_gain_code_quant_mod(
897 *gain_pit, exp_gcode0, gcode0,
898 frac_en, exp_en, alpha, gain_cod_unq,
899 gain_cod, qua_ener_MR122, qua_ener, pOverflow); /* function result */
900 }
901
902 *(*anap)++ = gain_pit_index;
903 *(*anap)++ = gain_cod_index;
904 }
905