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 
WebRtcIlbcfix_XcorrCoef(int16_t * target,int16_t * regressor,size_t subl,size_t searchLen,size_t offset,int16_t step)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