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/autocorr.c
     35 
     36      Date: 05/15/2000
     37 
     38 ------------------------------------------------------------------------------
     39  REVISION HISTORY
     40 
     41  Description: Put into template...starting optimization.
     42 
     43  Description: Removed call to mult_r routine.
     44 
     45  Description: Modified Input/Output Definitions section to comply with the
     46           current template. Fixed tabs.
     47 
     48  Description: Updated Input/Output definitions by making them more
     49           descriptive.
     50 
     51  Description: Synchronized file with UMTS version 3.2.0. Updated coding
     52               template.
     53 
     54  Description: Made the following changes per comments from Phase 2/3 review:
     55               1. Added full pathname of file.
     56               2. Fixed typecasting issue with TI compiler.
     57               3. Modified FOR loops to count down.
     58               4. Added comment to the code.
     59 
     60  Description: Removed extern to global paramter (Flag Overflow) and replaced
     61  by passing in a pointer to Overflow.  Also, made several small changes to
     62  bring code more in line with PV Standards.
     63 
     64  Description:
     65             1. Added pointer to avoid adding offsets in every pass
     66             2. Break last loop in two nested loop to speed up processing
     67             3. Removed extra check for overflow by doing scaling right
     68                after overflow is detected.
     69             4. Eliminated calls to basic operations (like extract) not
     70                needed because of the nature of the number (all bounded)
     71 
     72  Description:
     73               1. Fixed for:
     74                 overflow check was looking for positive number before a left
     75                 shift. When numbers were big enough, positive numbers after
     76                 shifted became negative, causing a 1/0 division).
     77                 Fixed so now it checks for numbers lesser than 0x40000000
     78                 before the left shift
     79 
     80  Description:
     81               1.Modified check for saturation to match bit exact test.
     82                 Also, when saturation is reached, a faster loop is used
     83                 (with no energy accumulation) to speed up processing
     84 
     85 
     86  Description:
     87               1.Added pointer initialization to for loop when saturation
     88                 is found. This because some compiler ( like Vcpp in release
     89                 mode) when optimizing code, may remove pointer information
     90                 once the loop is broken.
     91 
     92  Description:  Added casting to eliminate warnings
     93 
     94  Description:  Replaced "int" and/or "char" with OSCL defined types.
     95 
     96  Description: Using inlines from fxp_arithmetic.h.
     97 
     98  Description: Replacing fxp_arithmetic.h with basic_op.h.
     99 
    100  Description:
    101 
    102 ----------------------------------------------------------------------------*/
    103 
    104 /*----------------------------------------------------------------------------
    105 ; INCLUDES
    106 ----------------------------------------------------------------------------*/
    107 #include "autocorr.h"
    108 #include "typedef.h"
    109 #include "basic_op.h"
    110 #include "oper_32b.h"
    111 #include "cnst.h"
    112 
    113 /*----------------------------------------------------------------------------
    114 ; MACROS
    115 ; Define module specific macros here
    116 ----------------------------------------------------------------------------*/
    117 
    118 
    119 /*----------------------------------------------------------------------------
    120 ; DEFINES
    121 ; Include all pre-processor statements here. Include conditional
    122 ; compile variables also.
    123 ----------------------------------------------------------------------------*/
    124 
    125 
    126 /*----------------------------------------------------------------------------
    127 ; LOCAL FUNCTION DEFINITIONS
    128 ; Function Prototype declaration
    129 ----------------------------------------------------------------------------*/
    130 
    131 /*----------------------------------------------------------------------------
    132 ; LOCAL STORE/BUFFER/POINTER DEFINITIONS
    133 ; Variable declaration - defined here and used outside this module
    134 ----------------------------------------------------------------------------*/
    135 
    136 /*----------------------------------------------------------------------------
    137 ; EXTERNAL FUNCTION REFERENCES
    138 ; Declare functions defined elsewhere and referenced in this module
    139 ----------------------------------------------------------------------------*/
    140 
    141 
    142 /*----------------------------------------------------------------------------
    143 ; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
    144 ; Declare variables used in this module but defined elsewhere
    145 ----------------------------------------------------------------------------*/
    146 
    147 /*
    148 ------------------------------------------------------------------------------
    149  FUNCTION NAME: Autocorr
    150 ----------------------------------------------------------------------------
    151  INPUT AND OUTPUT DEFINITIONS
    152 
    153  Inputs:
    154     x = buffer of input signals of type Word16
    155     m = LPC order of type Word16
    156     wind = buffer of window signals of type Word16
    157     r_h = buffer containing the high word of the autocorrelation values
    158           of type Word16
    159     r_l = buffer containing the low word of the autocorrelation values
    160           of type Word16
    161 
    162     pOverflow = pointer to variable of type Flag *, which indicates if
    163                 overflow occurs.
    164 
    165  Outputs:
    166     r_h buffer contains the high word of the new autocorrelation values
    167     r_l buffer contains the low word of the new autocorrelation values
    168     pOverflow -> 1 if overflow occurs.
    169 
    170  Returns:
    171     norm = normalized autocorrelation at lag zero of type Word16
    172 
    173  Global Variables Used:
    174     None
    175 
    176  Local Variables Needed:
    177     None
    178 
    179 ------------------------------------------------------------------------------
    180  FUNCTION DESCRIPTION
    181 
    182  This function windows the input signal with the provided window
    183  then calculates the autocorrelation values for lags of 0,1,...m,
    184  where m is the passed in LPC order.
    185 
    186 ------------------------------------------------------------------------------
    187  REQUIREMENTS
    188 
    189  None.
    190 
    191 ------------------------------------------------------------------------------
    192  REFERENCES
    193 
    194  autocorr.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
    195 
    196 ------------------------------------------------------------------------------
    197  PSEUDO-CODE
    198 
    199 Word16 Autocorr (
    200     Word16 x[],            // (i)    : Input signal (L_WINDOW)
    201     Word16 m,              // (i)    : LPC order
    202     Word16 r_h[],          // (o)    : Autocorrelations  (msb)
    203     Word16 r_l[],          // (o)    : Autocorrelations  (lsb)
    204     const Word16 wind[]    // (i)    : window for LPC analysis (L_WINDOW)
    205 )
    206 {
    207     Word16 i, j, norm;
    208     Word16 y[L_WINDOW];
    209     Word32 sum;
    210     Word16 overfl, overfl_shft;
    211 
    212     // Windowing of signal
    213 
    214     for (i = 0; i < L_WINDOW; i++)
    215     {
    216         y[i] = mult_r (x[i], wind[i]);
    217     }
    218 
    219     // Compute r[0] and test for overflow
    220 
    221     overfl_shft = 0;
    222 
    223     do
    224     {
    225         overfl = 0;
    226         sum = 0L;
    227 
    228         for (i = 0; i < L_WINDOW; i++)
    229         {
    230             sum = L_mac (sum, y[i], y[i]);
    231         }
    232 
    233         // If overflow divide y[] by 4
    234 
    235         if (L_sub (sum, MAX_32) == 0L)
    236         {
    237             overfl_shft = add (overfl_shft, 4);
    238             overfl = 1; // Set the overflow flag
    239 
    240             for (i = 0; i < L_WINDOW; i++)
    241             {
    242                 y[i] = shr (y[i], 2);
    243             }
    244         }
    245     }
    246     while (overfl != 0);
    247 
    248     sum = L_add (sum, 1L);             // Avoid the case of all zeros
    249 
    250     // Normalization of r[0]
    251 
    252     norm = norm_l (sum);
    253     sum = L_shl (sum, norm);
    254     L_Extract (sum, &r_h[0], &r_l[0]); // Put in DPF format (see oper_32b)
    255 
    256     // r[1] to r[m]
    257 
    258     for (i = 1; i <= m; i++)
    259     {
    260         sum = 0;
    261 
    262         for (j = 0; j < L_WINDOW - i; j++)
    263         {
    264             sum = L_mac (sum, y[j], y[j + i]);
    265         }
    266 
    267         sum = L_shl (sum, norm);
    268         L_Extract (sum, &r_h[i], &r_l[i]);
    269     }
    270 
    271     norm = sub (norm, overfl_shft);
    272 
    273     return norm;
    274 }
    275 
    276 
    277 ------------------------------------------------------------------------------
    278  RESOURCES USED [optional]
    279 
    280  When the code is written for a specific target processor the
    281  the resources used should be documented below.
    282 
    283  HEAP MEMORY USED: x bytes
    284 
    285  STACK MEMORY USED: x bytes
    286 
    287  CLOCK CYCLES: (cycle count equation for this function) + (variable
    288                 used to represent cycle count for each subroutine
    289                 called)
    290      where: (cycle count variable) = cycle count for [subroutine
    291                                      name]
    292 
    293 ------------------------------------------------------------------------------
    294  CAUTION [optional]
    295  [State any special notes, constraints or cautions for users of this function]
    296 
    297 ------------------------------------------------------------------------------
    298 */
    299 
    300 Word16 Autocorr(
    301     Word16 x[],            /* (i)    : Input signal (L_WINDOW)            */
    302     Word16 m,              /* (i)    : LPC order                          */
    303     Word16 r_h[],          /* (o)    : Autocorrelations  (msb)            */
    304     Word16 r_l[],          /* (o)    : Autocorrelations  (lsb)            */
    305     const Word16 wind[],   /* (i)    : window for LPC analysis (L_WINDOW) */
    306     Flag  *pOverflow       /* (o)    : indicates overflow                 */
    307 )
    308 {
    309     Word16 i;
    310     Word16 j;
    311     Word16 norm;
    312 
    313     Word16 y[L_WINDOW];
    314     Word32 sum;
    315     Word16 overfl_shft;
    316 
    317 
    318     /* Added for optimization  */
    319 
    320 
    321     Word16 temp;
    322     Word16 *p_x;
    323     Word16 *p_y;
    324     Word16 *p_y_1;
    325     Word16 *p_y_ref;
    326     Word16 *p_rh;
    327     Word16 *p_rl;
    328     const Word16 *p_wind;
    329     p_y = y;
    330     p_x = x;
    331     p_wind = wind;
    332     /*
    333      *  Windowing of the signal
    334      */
    335 
    336     OSCL_UNUSED_ARG(pOverflow);
    337 
    338     sum = 0L;
    339     j = 0;
    340 
    341     for (i = L_WINDOW; i != 0; i--)
    342     {
    343         temp = (amrnb_fxp_mac_16_by_16bb((Word32) * (p_x++), (Word32) * (p_wind++), 0x04000)) >> 15;
    344         *(p_y++) = temp;
    345 
    346         sum += ((Word32)temp * temp) << 1;
    347         if (sum < 0)
    348         {
    349             /*
    350              * if oveflow exist, then stop accumulation
    351              */
    352             j = 1;
    353             break;
    354         }
    355 
    356     }
    357     /*
    358      * if oveflow existed, complete  windowing operation
    359      * without computing energy
    360      */
    361 
    362     if (j)
    363     {
    364         p_y = &y[L_WINDOW-i];
    365         p_x = &x[L_WINDOW-i];
    366         p_wind = &wind[L_WINDOW-i];
    367 
    368         for (; i != 0; i--)
    369         {
    370             temp = (amrnb_fxp_mac_16_by_16bb((Word32) * (p_x++), (Word32) * (p_wind++), 0x04000)) >> 15;
    371             *(p_y++) = temp;
    372         }
    373     }
    374 
    375 
    376     /*
    377      *  Compute r[0] and test for overflow
    378      */
    379 
    380     overfl_shft = 0;
    381 
    382     /*
    383      * scale down by 1/4 only when needed
    384      */
    385     while (j == 1)
    386     {
    387         /* If overflow divide y[] by 4          */
    388         /* FYI: For better resolution, we could */
    389         /*      divide y[] by 2                 */
    390         overfl_shft += 4;
    391         p_y   = &y[0];
    392         sum = 0L;
    393 
    394         for (i = (L_WINDOW >> 1); i != 0 ; i--)
    395         {
    396             temp = *p_y >> 2;
    397             *(p_y++) = temp;
    398             sum += ((Word32)temp * temp) << 1;
    399             temp = *p_y >> 2;
    400             *(p_y++) = temp;
    401             sum += ((Word32)temp * temp) << 1;
    402         }
    403         if (sum > 0)
    404         {
    405             j = 0;
    406         }
    407 
    408     }
    409 
    410     sum += 1L;              /* Avoid the case of all zeros */
    411 
    412     /* Normalization of r[0] */
    413 
    414     norm = norm_l(sum);
    415 
    416     sum <<= norm;
    417 
    418     /* Put in DPF format (see oper_32b) */
    419     r_h[0] = (Word16)(sum >> 16);
    420     r_l[0] = (Word16)((sum >> 1) - ((Word32)(r_h[0]) << 15));
    421 
    422     /* r[1] to r[m] */
    423 
    424     p_y_ref = &y[L_WINDOW - 1 ];
    425     p_rh = &r_h[m];
    426     p_rl = &r_l[m];
    427 
    428     for (i = m; i > 0; i--)
    429     {
    430         sum  = 0;
    431 
    432         p_y   = &y[L_WINDOW - i - 1];
    433         p_y_1 = p_y_ref;
    434 
    435         for (j = (L_WINDOW - i - 1) >> 1; j != 0; j--)
    436         {
    437             sum = amrnb_fxp_mac_16_by_16bb((Word32) * (p_y--), (Word32) * (p_y_1--), sum);
    438             sum = amrnb_fxp_mac_16_by_16bb((Word32) * (p_y--), (Word32) * (p_y_1--), sum);
    439         }
    440 
    441         sum = amrnb_fxp_mac_16_by_16bb((Word32) * (p_y--), (Word32) * (p_y_1--), sum);
    442 
    443         if (((L_WINDOW - i - 1) & 1))
    444         {
    445             sum = amrnb_fxp_mac_16_by_16bb((Word32) * (p_y--), (Word32) * (p_y_1--), sum);
    446         }
    447 
    448         sum  <<= (norm + 1);
    449 
    450         *(p_rh)   = (Word16)(sum >> 16);
    451         *(p_rl--) = (Word16)((sum >> 1) - ((Word32) * (p_rh--) << 15));
    452 
    453     }
    454 
    455     norm -= overfl_shft;
    456 
    457     return (norm);
    458 
    459 } /* Autocorr */
    460