1b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/*
2b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
3b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *
4b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  Use of this source code is governed by a BSD-style license
5b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  that can be found in the LICENSE file in the root of the source
6b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  tree. An additional intellectual property rights grant can be found
7b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  in the file PATENTS.  All contributing project authors may
8b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
9b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */
10b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
11b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/******************************************************************
12b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
13b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org iLBC Speech Coder ANSI-C Source Code
14b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
15b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WebRtcIlbcfix_XcorrCoef.c
16b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
17b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org******************************************************************/
18b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
19b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "defines.h"
20b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
21b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/*----------------------------------------------------------------*
22b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * cross correlation which finds the optimal lag for the
23b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * crossCorr*crossCorr/(energy) criteria
24b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *---------------------------------------------------------------*/
25b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
26b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint WebRtcIlbcfix_XcorrCoef(
27fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    int16_t *target,  /* (i) first array */
28fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    int16_t *regressor, /* (i) second array */
29fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    int16_t subl,  /* (i) dimension arrays */
30fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    int16_t searchLen, /* (i) the search lenght */
31fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    int16_t offset,  /* (i) samples offset between arrays */
32fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    int16_t step   /* (i) +1 or -1 */
33b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            ){
34b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int k;
35fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t maxlag;
36fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t pos;
37fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t max;
38fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t crossCorrScale, Energyscale;
39fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t crossCorrSqMod, crossCorrSqMod_Max;
40fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t crossCorr, Energy;
41fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t crossCorrmod, EnergyMod, EnergyMod_Max;
42fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t *tp, *rp;
43fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t *rp_beg, *rp_end;
44fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t totscale, totscale_max;
45fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t scalediff;
46fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t newCrit, maxCrit;
47b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int shifts;
48b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
49b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Initializations, to make sure that the first one is selected */
50b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  crossCorrSqMod_Max=0;
51b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EnergyMod_Max=WEBRTC_SPL_WORD16_MAX;
52b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  totscale_max=-500;
53b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  maxlag=0;
54b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  pos=0;
55b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
56b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Find scale value and start position */
57b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (step==1) {
58fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    max=WebRtcSpl_MaxAbsValueW16(regressor, (int16_t)(subl+searchLen-1));
59b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    rp_beg = regressor;
60b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    rp_end = &regressor[subl];
61b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  } else { /* step==-1 */
62fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    max=WebRtcSpl_MaxAbsValueW16(&regressor[-searchLen], (int16_t)(subl+searchLen-1));
63b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    rp_beg = &regressor[-1];
64b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    rp_end = &regressor[subl-1];
65b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
66b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
67fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  /* Introduce a scale factor on the Energy in int32_t in
68b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     order to make sure that the calculation does not
69b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     overflow */
70b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
71b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (max>5000) {
72b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    shifts=2;
73b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  } else {
74b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    shifts=0;
75b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
76b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
77b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Calculate the first energy, then do a +/- to get the other energies */
78b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  Energy=WebRtcSpl_DotProductWithScale(regressor, regressor, subl, shifts);
79b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
80b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k=0;k<searchLen;k++) {
81b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    tp = target;
82b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    rp = &regressor[pos];
83b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
84b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    crossCorr=WebRtcSpl_DotProductWithScale(tp, rp, subl, shifts);
85b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
86b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if ((Energy>0)&&(crossCorr>0)) {
87b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
88b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      /* Put cross correlation and energy on 16 bit word */
89fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org      crossCorrScale=(int16_t)WebRtcSpl_NormW32(crossCorr)-16;
90fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org      crossCorrmod=(int16_t)WEBRTC_SPL_SHIFT_W32(crossCorr, crossCorrScale);
91fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org      Energyscale=(int16_t)WebRtcSpl_NormW32(Energy)-16;
92fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org      EnergyMod=(int16_t)WEBRTC_SPL_SHIFT_W32(Energy, Energyscale);
93b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
94fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org      /* Square cross correlation and store upper int16_t */
95fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org      crossCorrSqMod=(int16_t)WEBRTC_SPL_MUL_16_16_RSFT(crossCorrmod, crossCorrmod, 16);
96b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
97b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      /* Calculate the total number of (dynamic) right shifts that have
98b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org         been performed on (crossCorr*crossCorr)/energy
99b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      */
100b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      totscale=Energyscale-(crossCorrScale<<1);
101b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
102b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      /* Calculate the shift difference in order to be able to compare the two
103b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org         (crossCorr*crossCorr)/energy in the same domain
104b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      */
105b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      scalediff=totscale-totscale_max;
106b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      scalediff=WEBRTC_SPL_MIN(scalediff,31);
107b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      scalediff=WEBRTC_SPL_MAX(scalediff,-31);
108b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
109b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      /* Compute the cross multiplication between the old best criteria
110b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org         and the new one to be able to compare them without using a
111b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org         division */
112b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
113b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      if (scalediff<0) {
114fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org        newCrit = ((int32_t)crossCorrSqMod*EnergyMod_Max)>>(-scalediff);
115fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org        maxCrit = ((int32_t)crossCorrSqMod_Max*EnergyMod);
116b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      } else {
117fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org        newCrit = ((int32_t)crossCorrSqMod*EnergyMod_Max);
118fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org        maxCrit = ((int32_t)crossCorrSqMod_Max*EnergyMod)>>scalediff;
119b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      }
120b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
121b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      /* Store the new lag value if the new criteria is larger
122b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org         than previous largest criteria */
123b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
124b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      if (newCrit > maxCrit) {
125b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        crossCorrSqMod_Max = crossCorrSqMod;
126b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        EnergyMod_Max = EnergyMod;
127b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        totscale_max = totscale;
128b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        maxlag = k;
129b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      }
130b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
131b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    pos+=step;
132b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
133b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Do a +/- to get the next energy */
134b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    Energy += step*(WEBRTC_SPL_RSHIFT_W32(
135fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org        ((int32_t)(*rp_end)*(*rp_end)) - ((int32_t)(*rp_beg)*(*rp_beg)),
136b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        shifts));
137b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    rp_beg+=step;
138b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    rp_end+=step;
139b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
140b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
141b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return(maxlag+offset);
142b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
143