OSDN Git Service

original
[gb-231r1-is01/Gingerbread_2.3.3_r1_IS01.git] / frameworks / base / media / libstagefright / codecs / amrnb / enc / src / qgain795.cpp
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
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
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
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 }