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/qua_gain.c
     35  Functions:
     36 
     37      Date: 02/05/2002
     38 
     39 ------------------------------------------------------------------------------
     40  REVISION HISTORY
     41 
     42  Description: Updated template used to PV coding template.
     43  Changed to accept the pOverflow flag for EPOC compatibility.
     44 
     45  Description: Changed include files to lowercase.
     46 
     47  Description:  Replaced OSCL mem type functions and eliminated include
     48                files that now are chosen by OSCL definitions
     49 
     50  Description:  Replaced "int" and/or "char" with OSCL defined types.
     51 
     52  Description: Added #ifdef __cplusplus around extern'ed table.
     53 
     54  Description:
     55 
     56 ------------------------------------------------------------------------------
     57  MODULE DESCRIPTION
     58 
     59     Quantization of pitch and codebook gains.
     60 ------------------------------------------------------------------------------
     61 */
     62 
     63 /*----------------------------------------------------------------------------
     64 ; INCLUDES
     65 ----------------------------------------------------------------------------*/
     66 #include "qua_gain.h"
     67 #include "typedef.h"
     68 #include "basic_op.h"
     69 
     70 #include "mode.h"
     71 #include "cnst.h"
     72 #include "pow2.h"
     73 #include "gc_pred.h"
     74 
     75 /*--------------------------------------------------------------------------*/
     76 #ifdef __cplusplus
     77 extern "C"
     78 {
     79 #endif
     80 
     81     /*----------------------------------------------------------------------------
     82     ; MACROS
     83     ; Define module specific macros here
     84     ----------------------------------------------------------------------------*/
     85 
     86     /*----------------------------------------------------------------------------
     87     ; DEFINES
     88     ; Include all pre-processor statements here. Include conditional
     89     ; compile variables also.
     90     ----------------------------------------------------------------------------*/
     91 
     92     /*----------------------------------------------------------------------------
     93     ; LOCAL FUNCTION DEFINITIONS
     94     ; Function Prototype declaration
     95     ----------------------------------------------------------------------------*/
     96 
     97     /*----------------------------------------------------------------------------
     98     ; LOCAL VARIABLE DEFINITIONS
     99     ; Variable declaration - defined here and used outside this module
    100     ----------------------------------------------------------------------------*/
    101 
    102     /*----------------------------------------------------------------------------
    103     ; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
    104     ; Declare variables used in this module but defined elsewhere
    105     ----------------------------------------------------------------------------*/
    106     extern const Word16 table_gain_lowrates[];
    107     extern const Word16 table_gain_highrates[];
    108 
    109     /*--------------------------------------------------------------------------*/
    110 #ifdef __cplusplus
    111 }
    112 #endif
    113 
    114 /*
    115 ------------------------------------------------------------------------------
    116  FUNCTION NAME:
    117 ------------------------------------------------------------------------------
    118  INPUT AND OUTPUT DEFINITIONS
    119 
    120 
    121  Inputs:
    122     mode -- enum Mode -- AMR mode
    123     Word16 exp_gcode0  -- Word16 -- predicted CB gain (exponent),       Q0
    124     Word16 frac_gcode0 -- Word16 -- predicted CB gain (fraction),      Q15
    125     Word16 frac_coeff -- Word16 Array -- energy coeff. (5), fraction part, Q15
    126     Word16 exp_coeff  -- Word16 Array -- energy coeff. (5), exponent part,  Q0
    127                                     (frac_coeff and exp_coeff computed in
    128                                     calc_filt_energies())
    129 
    130     Word16 gp_limit -- Word16 --  pitch gain limit
    131 
    132  Outputs:
    133     Word16 *gain_pit -- Pointer to Word16 -- Pitch gain,               Q14
    134     Word16 *gain_cod -- Pointer to Word16 -- Code gain,                Q1
    135     Word16 *qua_ener_MR122 -- Pointer to Word16 -- quantized energy error,  Q10
    136                                                 (for MR122 MA predictor update)
    137     Word16 *qua_ener -- Pointer to Word16 -- quantized energy error,        Q10
    138                                                 (for other MA predictor update)
    139     Flag   *pOverflow -- Pointer to Flag -- overflow indicator
    140 
    141  Returns:
    142     Word16 -- index of quantization.
    143 
    144  Global Variables Used:
    145 
    146 
    147  Local Variables Needed:
    148     None
    149 
    150 ------------------------------------------------------------------------------
    151  FUNCTION DESCRIPTION
    152 
    153     Quantization of pitch and codebook gains.
    154 ------------------------------------------------------------------------------
    155  REQUIREMENTS
    156 
    157  None
    158 
    159 ------------------------------------------------------------------------------
    160  REFERENCES
    161 
    162  qua_gain.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
    163 
    164 ------------------------------------------------------------------------------
    165  PSEUDO-CODE
    166 
    167 
    168 ------------------------------------------------------------------------------
    169  RESOURCES USED [optional]
    170 
    171  When the code is written for a specific target processor the
    172  the resources used should be documented below.
    173 
    174  HEAP MEMORY USED: x bytes
    175 
    176  STACK MEMORY USED: x bytes
    177 
    178  CLOCK CYCLES: (cycle count equation for this function) + (variable
    179                 used to represent cycle count for each subroutine
    180                 called)
    181      where: (cycle count variable) = cycle count for [subroutine
    182                                      name]
    183 
    184 ------------------------------------------------------------------------------
    185  CAUTION [optional]
    186  [State any special notes, constraints or cautions for users of this function]
    187 
    188 ------------------------------------------------------------------------------
    189 */
    190 
    191 
    192 Word16
    193 Qua_gain(                   /* o  : index of quantization.                 */
    194     enum Mode mode,         /* i  : AMR mode                               */
    195     Word16 exp_gcode0,      /* i  : predicted CB gain (exponent),      Q0  */
    196     Word16 frac_gcode0,     /* i  : predicted CB gain (fraction),      Q15 */
    197     Word16 frac_coeff[],    /* i  : energy coeff. (5), fraction part,  Q15 */
    198     Word16 exp_coeff[],     /* i  : energy coeff. (5), exponent part,  Q0  */
    199     /*      (frac_coeff and exp_coeff computed in  */
    200     /*       calc_filt_energies())                 */
    201     Word16 gp_limit,        /* i  : pitch gain limit                       */
    202     Word16 *gain_pit,       /* o  : Pitch gain,                        Q14 */
    203     Word16 *gain_cod,       /* o  : Code gain,                         Q1  */
    204     Word16 *qua_ener_MR122, /* o  : quantized energy error,            Q10 */
    205     /*      (for MR122 MA predictor update)        */
    206     Word16 *qua_ener,       /* o  : quantized energy error,            Q10 */
    207     /*      (for other MA predictor update)        */
    208     Flag   *pOverflow       /* o  : overflow indicator                     */
    209 )
    210 {
    211     const Word16 *p;
    212     Word16 i;
    213     Word16 j;
    214     Word16 index = 0;
    215     Word16 gcode0;
    216     Word16 e_max;
    217     Word16 temp;
    218     Word16 exp_code;
    219     Word16 g_pitch;
    220     Word16 g2_pitch;
    221     Word16 g_code;
    222     Word16 g2_code;
    223     Word16 g_pit_cod;
    224     Word16 coeff[5];
    225     Word16 coeff_lo[5];
    226     Word16 exp_max[5];
    227     Word32 L_tmp;
    228     Word32 L_tmp2;
    229     Word32 dist_min;
    230     const Word16 *table_gain;
    231     Word16 table_len;
    232 
    233     if (mode == MR102 || mode == MR74 || mode == MR67)
    234     {
    235         table_len = VQ_SIZE_HIGHRATES;
    236         table_gain = table_gain_highrates;
    237     }
    238     else
    239     {
    240         table_len = VQ_SIZE_LOWRATES;
    241         table_gain = table_gain_lowrates;
    242     }
    243 
    244     /*-------------------------------------------------------------------*
    245      *  predicted codebook gain                                          *
    246      *  ~~~~~~~~~~~~~~~~~~~~~~~                                          *
    247      *  gc0     = 2^exp_gcode0 + 2^frac_gcode0                           *
    248      *                                                                   *
    249      *  gcode0 (Q14) = 2^14*2^frac_gcode0 = gc0 * 2^(14-exp_gcode0)      *
    250      *-------------------------------------------------------------------*/
    251 
    252     gcode0 = (Word16)(Pow2(14, frac_gcode0, pOverflow));
    253 
    254     /*-------------------------------------------------------------------*
    255      *  Scaling considerations:                                          *
    256      *  ~~~~~~~~~~~~~~~~~~~~~~~                                          *
    257      *-------------------------------------------------------------------*/
    258 
    259     /*
    260      * The error energy (sum) to be minimized consists of five terms, t[0..4].
    261      *
    262      *                      t[0] =    gp^2  * <y1 y1>
    263      *                      t[1] = -2*gp    * <xn y1>
    264      *                      t[2] =    gc^2  * <y2 y2>
    265      *                      t[3] = -2*gc    * <xn y2>
    266      *                      t[4] =  2*gp*gc * <y1 y2>
    267      *
    268      */
    269 
    270     /* determine the scaling exponent for g_code: ec = ec0 - 11 */
    271     exp_code = sub(exp_gcode0, 11, pOverflow);
    272 
    273     /* calculate exp_max[i] = s[i]-1 */
    274     exp_max[0] = sub(exp_coeff[0], 13, pOverflow);
    275     exp_max[1] = sub(exp_coeff[1], 14, pOverflow);
    276 
    277     temp = shl(exp_code, 1, pOverflow);
    278     temp = add(15, temp, pOverflow);
    279     exp_max[2] = add(exp_coeff[2], temp, pOverflow);
    280 
    281     exp_max[3] = add(exp_coeff[3], exp_code, pOverflow);
    282 
    283     temp = add(1, exp_code, pOverflow);
    284     exp_max[4] = add(exp_coeff[4], temp, pOverflow);
    285 
    286 
    287     /*-------------------------------------------------------------------*
    288      *  Find maximum exponent:                                           *
    289      *  ~~~~~~~~~~~~~~~~~~~~~~                                           *
    290      *                                                                   *
    291      *  For the sum operation, all terms must have the same scaling;     *
    292      *  that scaling should be low enough to prevent overflow. There-    *
    293      *  fore, the maximum scale is determined and all coefficients are   *
    294      *  re-scaled:                                                       *
    295      *                                                                   *
    296      *    e_max = max(exp_max[i]) + 1;                                   *
    297      *    e = exp_max[i]-e_max;         e <= 0!                          *
    298      *    c[i] = c[i]*2^e                                                *
    299      *-------------------------------------------------------------------*/
    300 
    301     e_max = exp_max[0];
    302     for (i = 1; i < 5; i++)
    303     {
    304         if (exp_max[i] > e_max)
    305         {
    306             e_max = exp_max[i];
    307         }
    308     }
    309 
    310     e_max = add(e_max, 1, pOverflow);      /* To avoid overflow */
    311 
    312     for (i = 0; i < 5; i++)
    313     {
    314         j = sub(e_max, exp_max[i], pOverflow);
    315         L_tmp = L_deposit_h(frac_coeff[i]);
    316         L_tmp = L_shr(L_tmp, j, pOverflow);
    317         L_Extract(L_tmp, &coeff[i], &coeff_lo[i], pOverflow);
    318     }
    319 
    320 
    321     /*-------------------------------------------------------------------*
    322      *  Codebook search:                                                 *
    323      *  ~~~~~~~~~~~~~~~~                                                 *
    324      *                                                                   *
    325      *  For each pair (g_pitch, g_fac) in the table calculate the        *
    326      *  terms t[0..4] and sum them up; the result is the mean squared    *
    327      *  error for the quantized gains from the table. The index for the  *
    328      *  minimum MSE is stored and finally used to retrieve the quantized *
    329      *  gains                                                            *
    330      *-------------------------------------------------------------------*/
    331 
    332     /* start with "infinite" MSE */
    333     dist_min = MAX_32;
    334 
    335     p = &table_gain[0];
    336 
    337     for (i = 0; i < table_len; i++)
    338     {
    339         g_pitch = *p++;
    340         g_code = *p++;                   /* this is g_fac        */
    341         p++;                             /* skip log2(g_fac)     */
    342         p++;                             /* skip 20*log10(g_fac) */
    343 
    344         if (g_pitch <= gp_limit)
    345         {
    346             g_code = mult(g_code, gcode0, pOverflow);
    347             g2_pitch = mult(g_pitch, g_pitch, pOverflow);
    348             g2_code = mult(g_code, g_code, pOverflow);
    349             g_pit_cod = mult(g_code, g_pitch, pOverflow);
    350 
    351             L_tmp = Mpy_32_16(coeff[0], coeff_lo[0], g2_pitch, pOverflow);
    352             L_tmp2 = Mpy_32_16(coeff[1], coeff_lo[1], g_pitch, pOverflow);
    353             L_tmp = L_add(L_tmp, L_tmp2, pOverflow);
    354 
    355             L_tmp2 = Mpy_32_16(coeff[2], coeff_lo[2], g2_code, pOverflow);
    356             L_tmp = L_add(L_tmp, L_tmp2, pOverflow);
    357 
    358             L_tmp2 =  Mpy_32_16(coeff[3], coeff_lo[3], g_code, pOverflow);
    359             L_tmp = L_add(L_tmp, L_tmp2, pOverflow);
    360 
    361             L_tmp2 = Mpy_32_16(coeff[4], coeff_lo[4], g_pit_cod, pOverflow);
    362             L_tmp = L_add(L_tmp, L_tmp2, pOverflow);
    363 
    364             /* store table index if MSE for this index is lower
    365                than the minimum MSE seen so far */
    366             if (L_tmp < dist_min)
    367             {
    368                 dist_min = L_tmp;
    369                 index = i;
    370             }
    371         }
    372     }
    373 
    374     /*------------------------------------------------------------------*
    375      *  read quantized gains and new values for MA predictor memories   *
    376      *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~   *
    377      *------------------------------------------------------------------*/
    378 
    379     /* Read the quantized gains */
    380     p = &table_gain[shl(index, 2, pOverflow)];
    381     *gain_pit = *p++;
    382     g_code = *p++;
    383     *qua_ener_MR122 = *p++;
    384     *qua_ener = *p;
    385 
    386     /*------------------------------------------------------------------*
    387      *  calculate final fixed codebook gain:                            *
    388      *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                            *
    389      *                                                                  *
    390      *   gc = gc0 * g                                                   *
    391      *------------------------------------------------------------------*/
    392 
    393     L_tmp = L_mult(g_code, gcode0, pOverflow);
    394     temp  = sub(10, exp_gcode0, pOverflow);
    395     L_tmp = L_shr(L_tmp, temp, pOverflow);
    396 
    397     *gain_cod = extract_h(L_tmp);
    398 
    399     return index;
    400 }
    401