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/g_pitch.c
     35 
     36      Date: 06/12/2000
     37 
     38 ------------------------------------------------------------------------------
     39  REVISION HISTORY
     40 
     41  Description:  Placed into template and began to optimize.
     42 
     43  Description: Synchronized file with UMTS version 3.2.0. Updated coding
     44               template. Removed unnecessary include files.
     45 
     46  Description: Replaced basic_op.h and oper_32b.h with the header files of the
     47               math functions used in the file. Fixed typecasting issue with
     48               TI compiler.
     49 
     50  Description: Passing in pointer to overflow flag for EPOC compatibility. .
     51 
     52  Description:
     53               1. Eliminated unused include files.
     54               2. Replaced array addressing by pointers
     55               3. Eliminated math operations that unnecessary checked for
     56                  saturation, in some cases this by shifting before adding and
     57                  in other cases by evaluating the operands
     58               4. Unrolled loops to speed up processing
     59 
     60  Description:  Replaced OSCL mem type functions and eliminated include
     61                files that now are chosen by OSCL definitions
     62 
     63  Description:  Replaced "int" and/or "char" with OSCL defined types.
     64 
     65  Description: Changed round function name to pv_round to avoid conflict with
     66               round function in C standard library.
     67 
     68  Description: Using inlines from fxp_arithmetic.h .
     69 
     70  Description: Replacing fxp_arithmetic.h with basic_op.h.
     71 
     72  Description:
     73 
     74 ------------------------------------------------------------------------------
     75 */
     76 
     77 /*----------------------------------------------------------------------------
     78 ; INCLUDES
     79 ----------------------------------------------------------------------------*/
     80 #include "g_pitch.h"
     81 #include "mode.h"
     82 #include "cnst.h"
     83 #include "basic_op.h"
     84 
     85 /*----------------------------------------------------------------------------
     86 ; MACROS
     87 ; Define module specific macros here
     88 ----------------------------------------------------------------------------*/
     89 
     90 
     91 /*----------------------------------------------------------------------------
     92 ; DEFINES
     93 ; Include all pre-processor statements here. Include conditional
     94 ; compile variables also.
     95 ----------------------------------------------------------------------------*/
     96 
     97 /*----------------------------------------------------------------------------
     98 ; LOCAL FUNCTION DEFINITIONS
     99 ; Function Prototype declaration
    100 ----------------------------------------------------------------------------*/
    101 
    102 /*----------------------------------------------------------------------------
    103 ; LOCAL STORE/BUFFER/POINTER DEFINITIONS
    104 ; Variable declaration - defined here and used outside this module
    105 ----------------------------------------------------------------------------*/
    106 
    107 
    108 /*
    109 ------------------------------------------------------------------------------
    110  FUNCTION NAME: G_pitch
    111 ------------------------------------------------------------------------------
    112  INPUT AND OUTPUT DEFINITIONS
    113 
    114  Inputs:
    115     mode = AMR mode (enum Mode)
    116     xn = pointer to pitch target buffer (Word16)
    117     y1 = pointer to filtered adaptive codebook buffer (Word16)
    118     g_coeff  = pointer to buffer of correlations needed for gain quantization
    119                (Word16)
    120     L_subfr = length of subframe (Word16)
    121     pOverflow = pointer to overflow flag (Flag)
    122 
    123  Outputs:
    124     g_coeff contains the mantissa and exponent of the two dot products.
    125     pOverflow -> 1 if an overflow occurs
    126 
    127  Returns:
    128     gain =  ratio of dot products.(Word16)
    129 
    130  Global Variables Used:
    131     None.
    132 
    133  Local Variables Needed:
    134     None.
    135 
    136 ------------------------------------------------------------------------------
    137  FUNCTION DESCRIPTION
    138 
    139  This function computes the pitch (adaptive codebook) gain. The adaptive
    140  codebook gain is given by
    141 
    142     g = <x[], y[]> / <y[], y[]>
    143 
    144     where:  x[] is the target vector
    145             y[] is the filtered adaptive codevector
    146             <> denotes dot product.
    147 
    148  The gain is limited to the range [0,1.2] (=0..19661 Q14)
    149 
    150 ------------------------------------------------------------------------------
    151  REQUIREMENTS
    152 
    153  None.
    154 
    155 ------------------------------------------------------------------------------
    156  REFERENCES
    157 
    158  g_pitch.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
    159 
    160 ------------------------------------------------------------------------------
    161  PSEUDO-CODE
    162 
    163 Word16 G_pitch     (    // o : Gain of pitch lag saturated to 1.2
    164     enum Mode mode,     // i : AMR mode
    165     Word16 xn[],        // i : Pitch target.
    166     Word16 y1[],        // i : Filtered adaptive codebook.
    167     Word16 g_coeff[],   // i : Correlations need for gain quantization
    168     Word16 L_subfr      // i : Length of subframe.
    169 )
    170 {
    171     Word16 i;
    172     Word16 xy, yy, exp_xy, exp_yy, gain;
    173     Word32 s;
    174 
    175     Word16 scaled_y1[L_SUBFR];   // Usually dynamic allocation of (L_subfr)
    176 
    177     // divide "y1[]" by 4 to avoid overflow
    178 
    179 // The reference ETSI code uses a global overflow Flag. However in the actual
    180 // implementation a pointer to the overflow flag is passed into the function.
    181 
    182     for (i = 0; i < L_subfr; i++)
    183     {
    184         scaled_y1[i] = shr (y1[i], 2);
    185     }
    186 
    187     // Compute scalar product <y1[],y1[]>
    188 
    189     // Q12 scaling / MR122
    190     Overflow = 0;
    191     s = 1L; // Avoid case of all zeros
    192     for (i = 0; i < L_subfr; i++)
    193     {
    194         s = L_mac (s, y1[i], y1[i]);
    195     }
    196     if (Overflow == 0)       // Test for overflow
    197     {
    198         exp_yy = norm_l (s);
    199         yy = pv_round (L_shl (s, exp_yy));
    200     }
    201     else
    202     {
    203         s = 1L; // Avoid case of all zeros
    204         for (i = 0; i < L_subfr; i++)
    205         {
    206             s = L_mac (s, scaled_y1[i], scaled_y1[i]);
    207         }
    208         exp_yy = norm_l (s);
    209         yy = pv_round (L_shl (s, exp_yy));
    210         exp_yy = sub (exp_yy, 4);
    211     }
    212 
    213     // Compute scalar product <xn[],y1[]>
    214 
    215     Overflow = 0;
    216     s = 1L; // Avoid case of all zeros
    217 
    218     for (i = 0; i < L_subfr; i++)
    219     {
    220         s = L_mac(s, xn[i], y1[i]);
    221     }
    222     if (Overflow == 0)
    223     {
    224         exp_xy = norm_l (s);
    225         xy = pv_round (L_shl (s, exp_xy));
    226     }
    227     else
    228     {
    229         s = 1L; // Avoid case of all zeros
    230         for (i = 0; i < L_subfr; i++)
    231         {
    232             s = L_mac (s, xn[i], scaled_y1[i]);
    233         }
    234         exp_xy = norm_l (s);
    235         xy = pv_round (L_shl (s, exp_xy));
    236         exp_xy = sub (exp_xy, 2);
    237     }
    238 
    239     g_coeff[0] = yy;
    240     g_coeff[1] = sub (15, exp_yy);
    241     g_coeff[2] = xy;
    242     g_coeff[3] = sub (15, exp_xy);
    243 
    244     // If (xy < 4) gain = 0
    245 
    246     i = sub (xy, 4);
    247 
    248     if (i < 0)
    249         return ((Word16) 0);
    250 
    251     // compute gain = xy/yy
    252 
    253     xy = shr (xy, 1);                  // Be sure xy < yy
    254     gain = div_s (xy, yy);
    255 
    256     i = sub (exp_xy, exp_yy);      // Denormalization of division
    257     gain = shr (gain, i);
    258 
    259     // if(gain >1.2) gain = 1.2
    260 
    261     if (sub (gain, 19661) > 0)
    262     {
    263         gain = 19661;
    264     }
    265 
    266     if (sub(mode, MR122) == 0)
    267     {
    268        // clear 2 LSBits
    269        gain = gain & 0xfffC;
    270     }
    271 
    272     return (gain);
    273 }
    274 
    275 ------------------------------------------------------------------------------
    276  RESOURCES USED [optional]
    277 
    278  When the code is written for a specific target processor the
    279  the resources used should be documented below.
    280 
    281  HEAP MEMORY USED: x bytes
    282 
    283  STACK MEMORY USED: x bytes
    284 
    285  CLOCK CYCLES: (cycle count equation for this function) + (variable
    286                 used to represent cycle count for each subroutine
    287                 called)
    288      where: (cycle count variable) = cycle count for [subroutine
    289                                      name]
    290 
    291 ------------------------------------------------------------------------------
    292  CAUTION [optional]
    293  [State any special notes, constraints or cautions for users of this function]
    294 
    295 ------------------------------------------------------------------------------
    296 */
    297 
    298 Word16 G_pitch(         /* o : Gain of pitch lag saturated to 1.2       */
    299     enum Mode mode,     /* i : AMR mode                                 */
    300     Word16 xn[],        /* i : Pitch target.                            Q0  */
    301     Word16 y1[],        /* i : Filtered adaptive codebook.              Q12 */
    302     Word16 g_coeff[],   /* i : Correlations need for gain quantization  */
    303     Word16 L_subfr,     /* i : Length of subframe.                      */
    304     Flag   *pOverflow   /* i/o : Overflow flag                          */
    305 )
    306 {
    307 
    308     Word16 i;
    309     Word16 xy;
    310     Word16 yy;
    311     Word16 exp_xy;
    312     Word16 exp_yy;
    313     Word16 gain;
    314     Word16 tmp;
    315     Word32 s;
    316     Word32 s1;
    317     Word32 L_temp;                      /* Use this as an intermediate value */
    318     Word16 *p_xn = &xn[0];
    319     Word16 *p_y1 = &y1[0];
    320 
    321     /* Compute scalar product <y1[],y1[]> */
    322 
    323     /* Q12 scaling / MR122 */
    324     *pOverflow = 0;
    325     s = 0;
    326 
    327     for (i = L_subfr >> 2; i != 0; i--)
    328     {
    329         s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_y1), (Word32) * (p_y1), s);
    330         p_y1++;
    331         s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_y1), (Word32) * (p_y1), s);
    332         p_y1++;
    333         s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_y1), (Word32) * (p_y1), s);
    334         p_y1++;
    335         s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_y1), (Word32) * (p_y1), s);
    336         p_y1++;
    337     }
    338     if ((s >= 0) & (s < 0x40000000))
    339     {
    340         s <<= 1;
    341         s  += 1;            /* Avoid case of all zeros */
    342 
    343         exp_yy = norm_l(s);             /* Note 0<=exp_yy <= 31 */
    344         L_temp = s << exp_yy;
    345         yy = pv_round(L_temp, pOverflow);
    346     }
    347     else
    348     {
    349         s = 0;                      /* Avoid case of all zeros */
    350         p_y1 = &y1[0];
    351         for (i = (L_subfr >> 1); i != 0; i--)
    352         {
    353             tmp = *(p_y1++) >> 2;
    354             s = amrnb_fxp_mac_16_by_16bb((Word32) tmp, (Word32) tmp, s);
    355             tmp = *(p_y1++) >> 2;
    356             s = amrnb_fxp_mac_16_by_16bb((Word32) tmp, (Word32) tmp, s);
    357         }
    358 
    359         s <<= 1;
    360         s  += 1;            /* Avoid case of all zeros */
    361 
    362         exp_yy = norm_l(s);
    363         L_temp = s << exp_yy;
    364         yy = pv_round(L_temp, pOverflow);
    365         exp_yy = exp_yy - 4;
    366 
    367     }
    368 
    369     /* Compute scalar product <xn[],y1[]> */
    370 
    371     s = 0;
    372     p_y1 = &y1[0];
    373     *pOverflow = 0;
    374 
    375     for (i = L_subfr; i != 0; i--)
    376     {
    377         L_temp = ((Word32) * (p_xn++) * *(p_y1++));
    378         s1 = s;
    379         s = s1 + L_temp;
    380 
    381         if ((s1 ^ L_temp) > 0)
    382         {
    383             if ((s1 ^ s) < 0)
    384             {
    385                 *pOverflow = 1;
    386                 break;
    387             }
    388         }
    389     }
    390 
    391     if (!(*pOverflow))
    392     {
    393 
    394         s <<= 1;
    395         s  += 1;            /* Avoid case of all zeros */
    396 
    397         exp_xy = norm_l(s);             /* Note 0<=exp_yy <= 31 */
    398         L_temp = s << exp_xy;
    399         xy = pv_round(L_temp, pOverflow);
    400     }
    401     else
    402     {
    403         s = 0;  /* re-initialize calculations */
    404         p_y1 = &y1[0];
    405         p_xn = &xn[0];
    406         for (i = (L_subfr >> 2); i != 0; i--)
    407         {
    408             L_temp = (Word32)(*(p_y1++) >> 2);
    409             s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_xn++), L_temp, s);
    410             L_temp = (Word32)(*(p_y1++) >> 2);
    411             s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_xn++), L_temp, s);
    412             L_temp = (Word32)(*(p_y1++) >> 2);
    413             s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_xn++), L_temp, s);
    414             L_temp = (Word32)(*(p_y1++) >> 2);
    415             s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_xn++), L_temp, s);
    416         }
    417 
    418         s <<= 1;
    419         s  += 1;            /* Avoid case of all zeros */
    420 
    421         exp_xy = norm_l(s);
    422         L_temp = s << exp_xy;
    423         xy = pv_round(L_temp, pOverflow);
    424         exp_xy = exp_xy - 4;
    425 
    426     }
    427 
    428     g_coeff[0] = yy;
    429     g_coeff[1] = 15 - exp_yy;
    430     g_coeff[2] = xy;
    431     g_coeff[3] = 15 - exp_xy;
    432 
    433     /* If (xy < 4) gain = 0 */
    434     if (xy < 4)
    435     {
    436         return ((Word16) 0);
    437     }
    438 
    439     /* compute gain = xy/yy */
    440     /* Be sure xy < yy */
    441 
    442     xy = xy >> 1;
    443 
    444     gain = div_s(xy, yy);
    445 
    446     i = exp_xy - exp_yy;               /* Denormalization of division */
    447 
    448     gain = shr(gain, i, pOverflow);
    449 
    450 
    451     /* if(gain >1.2) gain = 1.2 */
    452     if (gain > 19661)
    453     {
    454         gain = 19661;
    455     }
    456 
    457     if (mode == MR122)
    458     {
    459         /* clear 2 LSBits */
    460         gain = gain & 0xfffC;
    461     }
    462 
    463     return(gain);
    464 
    465 }
    466