xref: /aosp_15_r20/external/webrtc/modules/audio_coding/codecs/ilbc/xcorr_coef.c (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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 "modules/audio_coding/codecs/ilbc/xcorr_coef.h"
20 
21 #include "modules/audio_coding/codecs/ilbc/defines.h"
22 
23 /*----------------------------------------------------------------*
24  * cross correlation which finds the optimal lag for the
25  * crossCorr*crossCorr/(energy) criteria
26  *---------------------------------------------------------------*/
27 
WebRtcIlbcfix_XcorrCoef(int16_t * target,int16_t * regressor,size_t subl,size_t searchLen,size_t offset,int16_t step)28 size_t WebRtcIlbcfix_XcorrCoef(
29     int16_t *target,  /* (i) first array */
30     int16_t *regressor, /* (i) second array */
31     size_t subl,  /* (i) dimension arrays */
32     size_t searchLen, /* (i) the search lenght */
33     size_t offset,  /* (i) samples offset between arrays */
34     int16_t step   /* (i) +1 or -1 */
35                             ){
36   size_t k;
37   size_t maxlag;
38   int16_t pos;
39   int16_t max;
40   int16_t crossCorrScale, Energyscale;
41   int16_t crossCorrSqMod, crossCorrSqMod_Max;
42   int32_t crossCorr, Energy;
43   int16_t crossCorrmod, EnergyMod, EnergyMod_Max;
44   int16_t *tp, *rp;
45   int16_t *rp_beg, *rp_end;
46   int16_t totscale, totscale_max;
47   int16_t scalediff;
48   int32_t newCrit, maxCrit;
49   int shifts;
50 
51   /* Initializations, to make sure that the first one is selected */
52   crossCorrSqMod_Max=0;
53   EnergyMod_Max=WEBRTC_SPL_WORD16_MAX;
54   totscale_max=-500;
55   maxlag=0;
56   pos=0;
57 
58   /* Find scale value and start position */
59   if (step==1) {
60     max=WebRtcSpl_MaxAbsValueW16(regressor, subl + searchLen - 1);
61     rp_beg = regressor;
62     rp_end = regressor + subl;
63   } else { /* step==-1 */
64     max = WebRtcSpl_MaxAbsValueW16(regressor - searchLen, subl + searchLen - 1);
65     rp_beg = regressor - 1;
66     rp_end = regressor + subl - 1;
67   }
68 
69   /* Introduce a scale factor on the Energy in int32_t in
70      order to make sure that the calculation does not
71      overflow */
72 
73   if (max>5000) {
74     shifts=2;
75   } else {
76     shifts=0;
77   }
78 
79   /* Calculate the first energy, then do a +/- to get the other energies */
80   Energy=WebRtcSpl_DotProductWithScale(regressor, regressor, subl, shifts);
81 
82   for (k=0;k<searchLen;k++) {
83     tp = target;
84     rp = &regressor[pos];
85 
86     crossCorr=WebRtcSpl_DotProductWithScale(tp, rp, subl, shifts);
87 
88     if ((Energy>0)&&(crossCorr>0)) {
89 
90       /* Put cross correlation and energy on 16 bit word */
91       crossCorrScale=(int16_t)WebRtcSpl_NormW32(crossCorr)-16;
92       crossCorrmod=(int16_t)WEBRTC_SPL_SHIFT_W32(crossCorr, crossCorrScale);
93       Energyscale=(int16_t)WebRtcSpl_NormW32(Energy)-16;
94       EnergyMod=(int16_t)WEBRTC_SPL_SHIFT_W32(Energy, Energyscale);
95 
96       /* Square cross correlation and store upper int16_t */
97       crossCorrSqMod = (int16_t)((crossCorrmod * crossCorrmod) >> 16);
98 
99       /* Calculate the total number of (dynamic) right shifts that have
100          been performed on (crossCorr*crossCorr)/energy
101       */
102       totscale=Energyscale-(crossCorrScale<<1);
103 
104       /* Calculate the shift difference in order to be able to compare the two
105          (crossCorr*crossCorr)/energy in the same domain
106       */
107       scalediff=totscale-totscale_max;
108       scalediff=WEBRTC_SPL_MIN(scalediff,31);
109       scalediff=WEBRTC_SPL_MAX(scalediff,-31);
110 
111       /* Compute the cross multiplication between the old best criteria
112          and the new one to be able to compare them without using a
113          division */
114 
115       if (scalediff<0) {
116         newCrit = ((int32_t)crossCorrSqMod*EnergyMod_Max)>>(-scalediff);
117         maxCrit = ((int32_t)crossCorrSqMod_Max*EnergyMod);
118       } else {
119         newCrit = ((int32_t)crossCorrSqMod*EnergyMod_Max);
120         maxCrit = ((int32_t)crossCorrSqMod_Max*EnergyMod)>>scalediff;
121       }
122 
123       /* Store the new lag value if the new criteria is larger
124          than previous largest criteria */
125 
126       if (newCrit > maxCrit) {
127         crossCorrSqMod_Max = crossCorrSqMod;
128         EnergyMod_Max = EnergyMod;
129         totscale_max = totscale;
130         maxlag = k;
131       }
132     }
133     pos+=step;
134 
135     /* Do a +/- to get the next energy */
136     Energy += step * ((*rp_end * *rp_end - *rp_beg * *rp_beg) >> shifts);
137     rp_beg+=step;
138     rp_end+=step;
139   }
140 
141   return(maxlag+offset);
142 }
143