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/cor_h.c
     35 
     36      Date: 06/12/2000
     37 
     38 ------------------------------------------------------------------------------
     39  REVISION HISTORY
     40 
     41  Description: Updated template used to PV coding template. First attempt at
     42           optimizing C code.
     43 
     44  Description: Used MAX_16 and MIN_16 when checking the result of Inv_sqrt.
     45           Synced up to the new template.
     46 
     47  Description: Added setting of Overflow flag in inlined code.
     48 
     49  Description: Took out cor_h_x function and put it in its own file. Sync'ed
     50           up with the single_func_template.c template. Delete version
     51           ID variable.
     52 
     53  Description: Synchronized file with UTMS version 3.2.0. Updated coding
     54               template. Removed unnecessary include files.
     55 
     56  Description: Fixed portion of the code that builds the rr[] matrix. There
     57               was an error in the original inlining of code that caused
     58               the code to be not bit-exact with UMTS version 3.2.0.
     59 
     60  Description: Added calls to L_add() and mult() in the code to handle overflow
     61               scenario. Moved cor_h.h after cnst.h in the Include section.
     62               Doing this allows the unit test to build using the cnst.h in the
     63               /test/include directory. Fixed initialization of the accumulator
     64               in the first calculation of the sum of squares.
     65 
     66  Description: Made the following changes per comments from Phase 2/3 review:
     67               1. Used #define value instead of hard-coded numbers in the code.
     68               2. Fixed typecasting issue with TI C compiler.
     69               3. Removed typecasting of 0x00008000L in the call to L_add.
     70 
     71  Description: Changed pOverflow from a global variable into a function
     72  parameter.
     73 
     74  Description:
     75             1. Added pointer to avoid adding offsets in every pass
     76             2. Eliminate variables defined as registers
     77             3. Removed extra check for overflow by doing scaling right
     78                after overflow is detected.
     79             4. Eliminated calls to basic operations (like extract) not
     80                needed because of the nature of the number (all bounded)
     81             5. Eliminated duplicate loop accessing same data
     82             6. Simplified matrix addressing by use of pointers
     83 
     84  Description:
     85               1. Eliminated unused include files.
     86               2. Access twice the number of points when delaing with matrices
     87                  and in the process only 3 pointers (instead of 4) are needed
     88               3. Replaced array addressing (array sign[]) by pointers
     89 
     90  Description: Changed round function name to pv_round to avoid conflict with
     91               round function in C standard library.
     92 
     93  Description: Using inlines from fxp_arithmetic.h .
     94 
     95  Description: Replacing fxp_arithmetic.h with basic_op.h.
     96 
     97  Description:
     98 
     99 ------------------------------------------------------------------------------
    100 */
    101 
    102 /*----------------------------------------------------------------------------
    103 ; INCLUDES
    104 ----------------------------------------------------------------------------*/
    105 #include "cnst.h"
    106 #include "cor_h.h"
    107 #include "basicop_malloc.h"
    108 #include "inv_sqrt.h"
    109 #include "basic_op.h"
    110 
    111 /*----------------------------------------------------------------------------
    112 ; MACROS
    113 ; Define module specific macros here
    114 ----------------------------------------------------------------------------*/
    115 
    116 /*----------------------------------------------------------------------------
    117 ; DEFINES
    118 ; Include all pre-processor statements here. Include conditional
    119 ; compile variables also.
    120 ----------------------------------------------------------------------------*/
    121 
    122 /*----------------------------------------------------------------------------
    123 ; LOCAL FUNCTION DEFINITIONS
    124 ; Function Prototype declaration
    125 ----------------------------------------------------------------------------*/
    126 
    127 /*----------------------------------------------------------------------------
    128 ; LOCAL STORE/BUFFER/POINTER DEFINITIONS
    129 ; Variable declaration - defined here and used outside this module
    130 ----------------------------------------------------------------------------*/
    131 
    132 /*
    133 ------------------------------------------------------------------------------
    134  FUNCTION NAME: cor_h
    135 ------------------------------------------------------------------------------
    136  INPUT AND OUTPUT DEFINITIONS
    137 
    138  Inputs:
    139     h = vector containing the impulse response of the weighted synthesis
    140         filter; vector contents are of type Word16; vector length is
    141         2 * L_SUBFR
    142     sign = vector containing the sign information for the correlation
    143            values; vector contents are of type Word16; vector length is
    144            L_CODE
    145     rr = autocorrelation matrix; matrix contents are of type Word16;
    146          matrix dimension is L_CODE by L_CODE
    147 
    148  Outputs:
    149     rr contents are the newly calculated autocorrelation values
    150 
    151  Returns:
    152     None
    153 
    154  Global Variables Used:
    155     None
    156 
    157  Local Variables Needed:
    158     None
    159 
    160 ------------------------------------------------------------------------------
    161  FUNCTION DESCRIPTION
    162 
    163  This function computes correlations of the impulse response (h) needed for
    164  the codebook search, and includes the sign information into the correlations.
    165 
    166  The correlations are given by:
    167     rr[i][j] = sum_{n=i}^{L-1} h[n-i] h[n-j];   i>=j; i,j=0,...,L-1
    168 
    169  The sign information is included by:
    170     rr[i][j] = rr[i][j]*sign[i]*sign[j]
    171 
    172 ------------------------------------------------------------------------------
    173  REQUIREMENTS
    174 
    175  None
    176 
    177 ------------------------------------------------------------------------------
    178  REFERENCES
    179 
    180  cor_h.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
    181 
    182 ------------------------------------------------------------------------------
    183  PSEUDO-CODE
    184 
    185 void cor_h (
    186     Word16 h[],         // (i) : impulse response of weighted synthesis
    187                                  filter
    188     Word16 sign[],      // (i) : sign of d[n]
    189     Word16 rr[][L_CODE] // (o) : matrix of autocorrelation
    190 )
    191 {
    192     Word16 i, j, k, dec, h2[L_CODE];
    193     Word32 s;
    194 
    195     // Scaling for maximum precision
    196 
    197     s = 2;
    198     for (i = 0; i < L_CODE; i++)
    199         s = L_mac (s, h[i], h[i]);
    200 
    201     j = sub (extract_h (s), 32767);
    202     if (j == 0)
    203     {
    204         for (i = 0; i < L_CODE; i++)
    205         {
    206             h2[i] = shr (h[i], 1);
    207         }
    208     }
    209     else
    210     {
    211         s = L_shr (s, 1);
    212         k = extract_h (L_shl (Inv_sqrt (s), 7));
    213         k = mult (k, 32440);                     // k = 0.99*k
    214 
    215         for (i = 0; i < L_CODE; i++)
    216         {
    217             h2[i] = pv_round (L_shl (L_mult (h[i], k), 9));
    218         }
    219     }
    220 
    221     // build matrix rr[]
    222     s = 0;
    223     i = L_CODE - 1;
    224     for (k = 0; k < L_CODE; k++, i--)
    225     {
    226         s = L_mac (s, h2[k], h2[k]);
    227         rr[i][i] = pv_round (s);
    228     }
    229 
    230     for (dec = 1; dec < L_CODE; dec++)
    231     {
    232         s = 0;
    233         j = L_CODE - 1;
    234         i = sub (j, dec);
    235         for (k = 0; k < (L_CODE - dec); k++, i--, j--)
    236         {
    237             s = L_mac (s, h2[k], h2[k + dec]);
    238             rr[j][i] = mult (pv_round (s), mult (sign[i], sign[j]));
    239             rr[i][j] = rr[j][i];
    240         }
    241     }
    242 }
    243 
    244 ---------------------------------------------------------------------------
    245  RESOURCES USED [optional]
    246 
    247  When the code is written for a specific target processor the
    248  the resources used should be documented below.
    249 
    250  HEAP MEMORY USED: x bytes
    251 
    252  STACK MEMORY USED: x bytes
    253 
    254  CLOCK CYCLES: (cycle count equation for this function) + (variable
    255                 used to represent cycle count for each subroutine
    256                 called)
    257      where: (cycle count variable) = cycle count for [subroutine
    258                                      name]
    259 
    260 ------------------------------------------------------------------------------
    261  CAUTION [optional]
    262  [State any special notes, constraints or cautions for users of this function]
    263 
    264 ------------------------------------------------------------------------------
    265 */
    266 
    267 void cor_h(
    268     Word16 h[],          /* (i) : impulse response of weighted synthesis
    269                                   filter                                  */
    270     Word16 sign[],       /* (i) : sign of d[n]                            */
    271     Word16 rr[][L_CODE], /* (o) : matrix of autocorrelation               */
    272     Flag  *pOverflow
    273 )
    274 {
    275     register Word16 i;
    276     register Word16 dec;
    277 
    278     Word16 h2[L_CODE];
    279     Word32 s;
    280     Word32 s2;
    281     Word16 tmp1;
    282     Word16 tmp2;
    283     Word16 tmp11;
    284     Word16 tmp22;
    285 
    286     Word16 *p_h;
    287     Word16 *p_h2;
    288     Word16 *rr1;
    289     Word16 *rr2;
    290     Word16 *rr3;
    291     Word16 *p_rr_ref1;
    292     Word16 *p_sign1;
    293     Word16 *p_sign2;
    294 
    295     /* Scaling for maximum precision */
    296 
    297     /* Initialize accumulator to 1 since left shift happens    */
    298     /* after the accumulation of the sum of squares (original  */
    299     /* code initialized s to 2)                                */
    300     s = 1;
    301     p_h = h;
    302 
    303     for (i = (L_CODE >> 1); i != 0 ; i--)
    304     {
    305         tmp1 = *(p_h++);
    306         s = amrnb_fxp_mac_16_by_16bb((Word32) tmp1, (Word32) tmp1, s);
    307         tmp1 = *(p_h++);
    308         s = amrnb_fxp_mac_16_by_16bb((Word32) tmp1, (Word32) tmp1, s);
    309 
    310     }
    311 
    312     s <<= 1;
    313 
    314     if (s & MIN_32)
    315     {
    316         p_h2 = h2;
    317         p_h  = h;
    318 
    319         for (i = (L_CODE >> 1); i != 0; i--)
    320         {
    321             *(p_h2++) =  *(p_h++)  >> 1;
    322             *(p_h2++) =  *(p_h++)  >> 1;
    323         }
    324     }
    325     else
    326     {
    327 
    328         s >>= 1;
    329 
    330         s = Inv_sqrt(s, pOverflow);
    331 
    332         if (s < (Word32) 0x00ffffffL)
    333         {
    334             /* k = 0.99*k */
    335             dec = (Word16)(((s >> 9) * 32440) >> 15);
    336         }
    337         else
    338         {
    339             dec = 32440;  /* 0.99 */
    340         }
    341 
    342         p_h  = h;
    343         p_h2 = h2;
    344 
    345         for (i = (L_CODE >> 1); i != 0; i--)
    346         {
    347             *(p_h2++) = (Word16)((amrnb_fxp_mac_16_by_16bb((Word32) * (p_h++), (Word32) dec, 0x020L)) >> 6);
    348             *(p_h2++) = (Word16)((amrnb_fxp_mac_16_by_16bb((Word32) * (p_h++), (Word32) dec, 0x020L)) >> 6);
    349         }
    350     }
    351     /* build matrix rr[] */
    352 
    353     s = 0;
    354 
    355     p_h2 = h2;
    356 
    357     rr1 = &rr[L_CODE-1][L_CODE-1];
    358 
    359     for (i = L_CODE >> 1; i != 0 ; i--)
    360     {
    361         tmp1   = *(p_h2++);
    362         s = amrnb_fxp_mac_16_by_16bb((Word32) tmp1, (Word32) tmp1, s);
    363         *rr1 = (Word16)((s + 0x00004000L) >> 15);
    364         rr1 -= (L_CODE + 1);
    365         tmp1   = *(p_h2++);
    366         s = amrnb_fxp_mac_16_by_16bb((Word32) tmp1, (Word32) tmp1, s);
    367         *rr1 = (Word16)((s + 0x00004000L) >> 15);
    368         rr1 -= (L_CODE + 1);
    369     }
    370 
    371 
    372     p_rr_ref1 = rr[L_CODE-1];
    373 
    374     for (dec = 1; dec < L_CODE; dec += 2)
    375     {
    376         rr1 = &p_rr_ref1[L_CODE-1-dec];
    377 
    378         rr2 = &rr[L_CODE-1-dec][L_CODE-1];
    379         rr3 = &rr[L_CODE-1-(dec+1)][L_CODE-1];
    380 
    381         s  = 0;
    382         s2 = 0;
    383 
    384         p_sign1 = &sign[L_CODE - 1];
    385         p_sign2 = &sign[L_CODE - 1 - dec];
    386 
    387         p_h2 = h2;
    388         p_h  = &h2[dec];
    389 
    390         for (i = (L_CODE - dec - 1); i != 0 ; i--)
    391         {
    392             s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_h2), (Word32) * (p_h++), s);
    393             s2 = amrnb_fxp_mac_16_by_16bb((Word32) * (p_h2++), (Word32) * (p_h), s2);
    394 
    395             tmp1  = (Word16)((s + 0x00004000L) >> 15);
    396             tmp11 = (Word16)((s2 + 0x00004000L) >> 15);
    397 
    398             tmp2  = ((Word32) * (p_sign1) * *(p_sign2--)) >> 15;
    399             tmp22 = ((Word32) * (p_sign1--) * *(p_sign2)) >> 15;
    400 
    401             *rr2 = ((Word32) tmp1 * tmp2) >> 15;
    402             *(rr1--) = *rr2;
    403             *rr1 = ((Word32) tmp11 * tmp22) >> 15;
    404             *rr3 = *rr1;
    405 
    406             rr1 -= (L_CODE);
    407             rr2 -= (L_CODE + 1);
    408             rr3 -= (L_CODE + 1);
    409 
    410         }
    411 
    412         s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_h2), (Word32) * (p_h), s);
    413 
    414         tmp1 = (Word16)((s + 0x00004000L) >> 15);
    415 
    416         tmp2 = ((Word32) * (p_sign1) * *(p_sign2)) >> 15;
    417         *rr1 = ((Word32) tmp1 * tmp2) >> 15;
    418 
    419         *rr2 = *rr1;
    420 
    421         rr1 -= (L_CODE + 1);
    422         rr2 -= (L_CODE + 1);
    423 
    424     }
    425 
    426     return;
    427 
    428 }
    429 
    430