Home | History | Annotate | Download | only in ilbc
      1 /*
      2  *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 /******************************************************************
     12 
     13  iLBC Speech Coder ANSI-C Source Code
     14 
     15  WebRtcIlbcfix_XcorrCoef.c
     16 
     17 ******************************************************************/
     18 
     19 #include "defines.h"
     20 
     21 /*----------------------------------------------------------------*
     22  * cross correlation which finds the optimal lag for the
     23  * crossCorr*crossCorr/(energy) criteria
     24  *---------------------------------------------------------------*/
     25 
     26 size_t WebRtcIlbcfix_XcorrCoef(
     27     int16_t *target,  /* (i) first array */
     28     int16_t *regressor, /* (i) second array */
     29     size_t subl,  /* (i) dimension arrays */
     30     size_t searchLen, /* (i) the search lenght */
     31     size_t offset,  /* (i) samples offset between arrays */
     32     int16_t step   /* (i) +1 or -1 */
     33                             ){
     34   size_t k;
     35   size_t maxlag;
     36   int16_t pos;
     37   int16_t max;
     38   int16_t crossCorrScale, Energyscale;
     39   int16_t crossCorrSqMod, crossCorrSqMod_Max;
     40   int32_t crossCorr, Energy;
     41   int16_t crossCorrmod, EnergyMod, EnergyMod_Max;
     42   int16_t *tp, *rp;
     43   int16_t *rp_beg, *rp_end;
     44   int16_t totscale, totscale_max;
     45   int16_t scalediff;
     46   int32_t newCrit, maxCrit;
     47   int shifts;
     48 
     49   /* Initializations, to make sure that the first one is selected */
     50   crossCorrSqMod_Max=0;
     51   EnergyMod_Max=WEBRTC_SPL_WORD16_MAX;
     52   totscale_max=-500;
     53   maxlag=0;
     54   pos=0;
     55 
     56   /* Find scale value and start position */
     57   if (step==1) {
     58     max=WebRtcSpl_MaxAbsValueW16(regressor, subl + searchLen - 1);
     59     rp_beg = regressor;
     60     rp_end = regressor + subl;
     61   } else { /* step==-1 */
     62     max = WebRtcSpl_MaxAbsValueW16(regressor - searchLen, subl + searchLen - 1);
     63     rp_beg = regressor - 1;
     64     rp_end = regressor + subl - 1;
     65   }
     66 
     67   /* Introduce a scale factor on the Energy in int32_t in
     68      order to make sure that the calculation does not
     69      overflow */
     70 
     71   if (max>5000) {
     72     shifts=2;
     73   } else {
     74     shifts=0;
     75   }
     76 
     77   /* Calculate the first energy, then do a +/- to get the other energies */
     78   Energy=WebRtcSpl_DotProductWithScale(regressor, regressor, subl, shifts);
     79 
     80   for (k=0;k<searchLen;k++) {
     81     tp = target;
     82     rp = &regressor[pos];
     83 
     84     crossCorr=WebRtcSpl_DotProductWithScale(tp, rp, subl, shifts);
     85 
     86     if ((Energy>0)&&(crossCorr>0)) {
     87 
     88       /* Put cross correlation and energy on 16 bit word */
     89       crossCorrScale=(int16_t)WebRtcSpl_NormW32(crossCorr)-16;
     90       crossCorrmod=(int16_t)WEBRTC_SPL_SHIFT_W32(crossCorr, crossCorrScale);
     91       Energyscale=(int16_t)WebRtcSpl_NormW32(Energy)-16;
     92       EnergyMod=(int16_t)WEBRTC_SPL_SHIFT_W32(Energy, Energyscale);
     93 
     94       /* Square cross correlation and store upper int16_t */
     95       crossCorrSqMod = (int16_t)((crossCorrmod * crossCorrmod) >> 16);
     96 
     97       /* Calculate the total number of (dynamic) right shifts that have
     98          been performed on (crossCorr*crossCorr)/energy
     99       */
    100       totscale=Energyscale-(crossCorrScale<<1);
    101 
    102       /* Calculate the shift difference in order to be able to compare the two
    103          (crossCorr*crossCorr)/energy in the same domain
    104       */
    105       scalediff=totscale-totscale_max;
    106       scalediff=WEBRTC_SPL_MIN(scalediff,31);
    107       scalediff=WEBRTC_SPL_MAX(scalediff,-31);
    108 
    109       /* Compute the cross multiplication between the old best criteria
    110          and the new one to be able to compare them without using a
    111          division */
    112 
    113       if (scalediff<0) {
    114         newCrit = ((int32_t)crossCorrSqMod*EnergyMod_Max)>>(-scalediff);
    115         maxCrit = ((int32_t)crossCorrSqMod_Max*EnergyMod);
    116       } else {
    117         newCrit = ((int32_t)crossCorrSqMod*EnergyMod_Max);
    118         maxCrit = ((int32_t)crossCorrSqMod_Max*EnergyMod)>>scalediff;
    119       }
    120 
    121       /* Store the new lag value if the new criteria is larger
    122          than previous largest criteria */
    123 
    124       if (newCrit > maxCrit) {
    125         crossCorrSqMod_Max = crossCorrSqMod;
    126         EnergyMod_Max = EnergyMod;
    127         totscale_max = totscale;
    128         maxlag = k;
    129       }
    130     }
    131     pos+=step;
    132 
    133     /* Do a +/- to get the next energy */
    134     Energy += step * ((*rp_end * *rp_end - *rp_beg * *rp_beg) >> shifts);
    135     rp_beg+=step;
    136     rp_end+=step;
    137   }
    138 
    139   return(maxlag+offset);
    140 }
    141