• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &ltpg, 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