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_CbSearchCore.c
16
17******************************************************************/
18
19#include "defines.h"
20#include "constants.h"
21
22void WebRtcIlbcfix_CbSearchCore(
23    int32_t *cDot,    /* (i) Cross Correlation */
24    int16_t range,    /* (i) Search range */
25    int16_t stage,    /* (i) Stage of this search */
26    int16_t *inverseEnergy,  /* (i) Inversed energy */
27    int16_t *inverseEnergyShift, /* (i) Shifts of inversed energy
28                                           with the offset 2*16-29 */
29    int32_t *Crit,    /* (o) The criteria */
30    int16_t *bestIndex,   /* (o) Index that corresponds to
31                                                   maximum criteria (in this
32                                                   vector) */
33    int32_t *bestCrit,   /* (o) Value of critera for the
34                                                   chosen index */
35    int16_t *bestCritSh)   /* (o) The domain of the chosen
36                                                   criteria */
37{
38  int32_t maxW32, tmp32;
39  int16_t max, sh, tmp16;
40  int i;
41  int32_t *cDotPtr;
42  int16_t cDotSqW16;
43  int16_t *inverseEnergyPtr;
44  int32_t *critPtr;
45  int16_t *inverseEnergyShiftPtr;
46
47  /* Don't allow negative values for stage 0 */
48  if (stage==0) {
49    cDotPtr=cDot;
50    for (i=0;i<range;i++) {
51      *cDotPtr=WEBRTC_SPL_MAX(0, (*cDotPtr));
52      cDotPtr++;
53    }
54  }
55
56  /* Normalize cDot to int16_t, calculate the square of cDot and store the upper int16_t */
57  maxW32 = WebRtcSpl_MaxAbsValueW32(cDot, range);
58
59  sh = (int16_t)WebRtcSpl_NormW32(maxW32);
60  cDotPtr = cDot;
61  inverseEnergyPtr = inverseEnergy;
62  critPtr = Crit;
63  inverseEnergyShiftPtr=inverseEnergyShift;
64  max=WEBRTC_SPL_WORD16_MIN;
65
66  for (i=0;i<range;i++) {
67    /* Calculate cDot*cDot and put the result in a int16_t */
68    tmp32 = WEBRTC_SPL_LSHIFT_W32(*cDotPtr,sh);
69    tmp16 = (int16_t)WEBRTC_SPL_RSHIFT_W32(tmp32,16);
70    cDotSqW16 = (int16_t)(((int32_t)(tmp16)*(tmp16))>>16);
71
72    /* Calculate the criteria (cDot*cDot/energy) */
73    *critPtr=WEBRTC_SPL_MUL_16_16(cDotSqW16, (*inverseEnergyPtr));
74
75    /* Extract the maximum shift value under the constraint
76       that the criteria is not zero */
77    if ((*critPtr)!=0) {
78      max = WEBRTC_SPL_MAX((*inverseEnergyShiftPtr), max);
79    }
80
81    inverseEnergyPtr++;
82    inverseEnergyShiftPtr++;
83    critPtr++;
84    cDotPtr++;
85  }
86
87  /* If no max shifts still at initialization value, set shift to zero */
88  if (max==WEBRTC_SPL_WORD16_MIN) {
89    max = 0;
90  }
91
92  /* Modify the criterias, so that all of them use the same Q domain */
93  critPtr=Crit;
94  inverseEnergyShiftPtr=inverseEnergyShift;
95  for (i=0;i<range;i++) {
96    /* Guarantee that the shift value is less than 16
97       in order to simplify for DSP's (and guard against >31) */
98    tmp16 = WEBRTC_SPL_MIN(16, max-(*inverseEnergyShiftPtr));
99
100    (*critPtr)=WEBRTC_SPL_SHIFT_W32((*critPtr),-tmp16);
101    critPtr++;
102    inverseEnergyShiftPtr++;
103  }
104
105  /* Find the index of the best value */
106  *bestIndex = WebRtcSpl_MaxIndexW32(Crit, range);
107  *bestCrit = Crit[*bestIndex];
108
109  /* Calculate total shifts of this criteria */
110  *bestCritSh = 32 - 2*sh + max;
111
112  return;
113}
114