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/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 = ®ressor[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