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