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