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
26int WebRtcIlbcfix_XcorrCoef(
27    int16_t *target,  /* (i) first array */
28    int16_t *regressor, /* (i) second array */
29    int16_t subl,  /* (i) dimension arrays */
30    int16_t searchLen, /* (i) the search lenght */
31    int16_t offset,  /* (i) samples offset between arrays */
32    int16_t step   /* (i) +1 or -1 */
33                            ){
34  int k;
35  int16_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, (int16_t)(subl+searchLen-1));
59    rp_beg = regressor;
60    rp_end = &regressor[subl];
61  } else { /* step==-1 */
62    max=WebRtcSpl_MaxAbsValueW16(&regressor[-searchLen], (int16_t)(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)WEBRTC_SPL_MUL_16_16_RSFT(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*(WEBRTC_SPL_RSHIFT_W32(
135        ((int32_t)(*rp_end)*(*rp_end)) - ((int32_t)(*rp_beg)*(*rp_beg)),
136        shifts));
137    rp_beg+=step;
138    rp_end+=step;
139  }
140
141  return(maxlag+offset);
142}
143