Home | History | Annotate | Download | only in src
      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 }
    905