
According to project structure discussed with Andrew. We want to flatten out the hierarchy and minimize the number of GYP files. No changes at all are being made in the source files; they are just moved. The only modified files are the GYP file and Android.mk Kevin: I updated relative paths in Android.mk so please verify it is correct, since I don't know how to build that. Review URL: http://webrtc-codereview.appspot.com/256006 git-svn-id: http://webrtc.googlecode.com/svn/trunk@894 4adac7df-926f-26a2-2b94-8c16560cd09d
397 lines
14 KiB
C
397 lines
14 KiB
C
/*
|
|
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license
|
|
* that can be found in the LICENSE file in the root of the source
|
|
* tree. An additional intellectual property rights grant can be found
|
|
* in the file PATENTS. All contributing project authors may
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
*/
|
|
|
|
/******************************************************************
|
|
|
|
iLBC Speech Coder ANSI-C Source Code
|
|
|
|
WebRtcIlbcfix_CbSearch.c
|
|
|
|
******************************************************************/
|
|
|
|
#include "defines.h"
|
|
#include "gain_quant.h"
|
|
#include "filtered_cb_vecs.h"
|
|
#include "constants.h"
|
|
#include "cb_mem_energy.h"
|
|
#include "interpolate_samples.h"
|
|
#include "cb_mem_energy_augmentation.h"
|
|
#include "cb_search_core.h"
|
|
#include "energy_inverse.h"
|
|
#include "augmented_cb_corr.h"
|
|
#include "cb_update_best_index.h"
|
|
#include "create_augmented_vec.h"
|
|
|
|
/*----------------------------------------------------------------*
|
|
* Search routine for codebook encoding and gain quantization.
|
|
*----------------------------------------------------------------*/
|
|
|
|
void WebRtcIlbcfix_CbSearch(
|
|
iLBC_Enc_Inst_t *iLBCenc_inst,
|
|
/* (i) the encoder state structure */
|
|
WebRtc_Word16 *index, /* (o) Codebook indices */
|
|
WebRtc_Word16 *gain_index, /* (o) Gain quantization indices */
|
|
WebRtc_Word16 *intarget, /* (i) Target vector for encoding */
|
|
WebRtc_Word16 *decResidual,/* (i) Decoded residual for codebook construction */
|
|
WebRtc_Word16 lMem, /* (i) Length of buffer */
|
|
WebRtc_Word16 lTarget, /* (i) Length of vector */
|
|
WebRtc_Word16 *weightDenum,/* (i) weighting filter coefficients in Q12 */
|
|
WebRtc_Word16 block /* (i) the subblock number */
|
|
) {
|
|
WebRtc_Word16 i, j, stage, range;
|
|
WebRtc_Word16 *pp, scale, tmp;
|
|
WebRtc_Word16 bits, temp1, temp2;
|
|
WebRtc_Word16 base_size;
|
|
WebRtc_Word32 codedEner, targetEner;
|
|
WebRtc_Word16 gains[CB_NSTAGES+1];
|
|
WebRtc_Word16 *cb_vecPtr;
|
|
WebRtc_Word16 indexOffset, sInd, eInd;
|
|
WebRtc_Word32 CritMax=0;
|
|
WebRtc_Word16 shTotMax=WEBRTC_SPL_WORD16_MIN;
|
|
WebRtc_Word16 bestIndex=0;
|
|
WebRtc_Word16 bestGain=0;
|
|
WebRtc_Word16 indexNew, CritNewSh;
|
|
WebRtc_Word32 CritNew;
|
|
WebRtc_Word32 *cDotPtr;
|
|
WebRtc_Word16 noOfZeros;
|
|
WebRtc_Word16 *gainPtr;
|
|
WebRtc_Word32 t32, tmpW32;
|
|
WebRtc_Word16 *WebRtcIlbcfix_kGainSq5_ptr;
|
|
/* Stack based */
|
|
WebRtc_Word16 CBbuf[CB_MEML+LPC_FILTERORDER+CB_HALFFILTERLEN];
|
|
WebRtc_Word32 cDot[128];
|
|
WebRtc_Word32 Crit[128];
|
|
WebRtc_Word16 targetVec[SUBL+LPC_FILTERORDER];
|
|
WebRtc_Word16 cbvectors[CB_MEML];
|
|
WebRtc_Word16 codedVec[SUBL];
|
|
WebRtc_Word16 interpSamples[20*4];
|
|
WebRtc_Word16 interpSamplesFilt[20*4];
|
|
WebRtc_Word16 energyW16[CB_EXPAND*128];
|
|
WebRtc_Word16 energyShifts[CB_EXPAND*128];
|
|
WebRtc_Word16 *inverseEnergy=energyW16; /* Reuse memory */
|
|
WebRtc_Word16 *inverseEnergyShifts=energyShifts; /* Reuse memory */
|
|
WebRtc_Word16 *buf = &CBbuf[LPC_FILTERORDER];
|
|
WebRtc_Word16 *target = &targetVec[LPC_FILTERORDER];
|
|
WebRtc_Word16 *aug_vec = (WebRtc_Word16*)cDot; /* length [SUBL], reuse memory */
|
|
|
|
/* Determine size of codebook sections */
|
|
|
|
base_size=lMem-lTarget+1;
|
|
if (lTarget==SUBL) {
|
|
base_size=lMem-19;
|
|
}
|
|
|
|
/* weighting of the CB memory */
|
|
noOfZeros=lMem-WebRtcIlbcfix_kFilterRange[block];
|
|
WebRtcSpl_MemSetW16(&buf[-LPC_FILTERORDER], 0, noOfZeros+LPC_FILTERORDER);
|
|
WebRtcSpl_FilterARFastQ12(
|
|
decResidual+noOfZeros, buf+noOfZeros,
|
|
weightDenum, LPC_FILTERORDER+1, WebRtcIlbcfix_kFilterRange[block]);
|
|
|
|
/* weighting of the target vector */
|
|
WEBRTC_SPL_MEMCPY_W16(&target[-LPC_FILTERORDER], buf+noOfZeros+WebRtcIlbcfix_kFilterRange[block]-LPC_FILTERORDER, LPC_FILTERORDER);
|
|
WebRtcSpl_FilterARFastQ12(
|
|
intarget, target,
|
|
weightDenum, LPC_FILTERORDER+1, lTarget);
|
|
|
|
/* Store target, towards the end codedVec is calculated as
|
|
the initial target minus the remaining target */
|
|
WEBRTC_SPL_MEMCPY_W16(codedVec, target, lTarget);
|
|
|
|
/* Find the highest absolute value to calculate proper
|
|
vector scale factor (so that it uses 12 bits) */
|
|
temp1 = WebRtcSpl_MaxAbsValueW16(buf, (WebRtc_Word16)lMem);
|
|
temp2 = WebRtcSpl_MaxAbsValueW16(target, (WebRtc_Word16)lTarget);
|
|
|
|
if ((temp1>0)&&(temp2>0)) {
|
|
temp1 = WEBRTC_SPL_MAX(temp1, temp2);
|
|
scale = WebRtcSpl_GetSizeInBits(WEBRTC_SPL_MUL_16_16(temp1, temp1));
|
|
} else {
|
|
/* temp1 or temp2 is negative (maximum was -32768) */
|
|
scale = 30;
|
|
}
|
|
|
|
/* Scale to so that a mul-add 40 times does not overflow */
|
|
scale = scale - 25;
|
|
scale = WEBRTC_SPL_MAX(0, scale);
|
|
|
|
/* Compute energy of the original target */
|
|
targetEner = WebRtcSpl_DotProductWithScale(target, target, lTarget, scale);
|
|
|
|
/* Prepare search over one more codebook section. This section
|
|
is created by filtering the original buffer with a filter. */
|
|
WebRtcIlbcfix_FilteredCbVecs(cbvectors, buf, lMem, WebRtcIlbcfix_kFilterRange[block]);
|
|
|
|
range = WebRtcIlbcfix_kSearchRange[block][0];
|
|
|
|
if(lTarget == SUBL) {
|
|
/* Create the interpolated samples and store them for use in all stages */
|
|
|
|
/* First section, non-filtered half of the cb */
|
|
WebRtcIlbcfix_InterpolateSamples(interpSamples, buf, lMem);
|
|
|
|
/* Second section, filtered half of the cb */
|
|
WebRtcIlbcfix_InterpolateSamples(interpSamplesFilt, cbvectors, lMem);
|
|
|
|
/* Compute the CB vectors' energies for the first cb section (non-filtered) */
|
|
WebRtcIlbcfix_CbMemEnergyAugmentation(interpSamples, buf,
|
|
scale, 20, energyW16, energyShifts);
|
|
|
|
/* Compute the CB vectors' energies for the second cb section (filtered cb) */
|
|
WebRtcIlbcfix_CbMemEnergyAugmentation(interpSamplesFilt, cbvectors,
|
|
scale, (WebRtc_Word16)(base_size+20), energyW16, energyShifts);
|
|
|
|
/* Compute the CB vectors' energies and store them in the vector
|
|
* energyW16. Also the corresponding shift values are stored. The
|
|
* energy values are used in all three stages. */
|
|
WebRtcIlbcfix_CbMemEnergy(range, buf, cbvectors, lMem,
|
|
lTarget, energyW16+20, energyShifts+20, scale, base_size);
|
|
|
|
} else {
|
|
/* Compute the CB vectors' energies and store them in the vector
|
|
* energyW16. Also the corresponding shift values are stored. The
|
|
* energy values are used in all three stages. */
|
|
WebRtcIlbcfix_CbMemEnergy(range, buf, cbvectors, lMem,
|
|
lTarget, energyW16, energyShifts, scale, base_size);
|
|
|
|
/* Set the energy positions 58-63 and 122-127 to zero
|
|
(otherwise they are uninitialized) */
|
|
WebRtcSpl_MemSetW16(energyW16+range, 0, (base_size-range));
|
|
WebRtcSpl_MemSetW16(energyW16+range+base_size, 0, (base_size-range));
|
|
}
|
|
|
|
/* Calculate Inverse Energy (energyW16 is already normalized
|
|
and will contain the inverse energy in Q29 after this call */
|
|
WebRtcIlbcfix_EnergyInverse(energyW16, base_size*CB_EXPAND);
|
|
|
|
/* The gain value computed in the previous stage is used
|
|
* as an upper limit to what the next stage gain value
|
|
* is allowed to be. In stage 0, 16384 (1.0 in Q14) is used as
|
|
* the upper limit. */
|
|
gains[0] = 16384;
|
|
|
|
for (stage=0; stage<CB_NSTAGES; stage++) {
|
|
|
|
/* Set up memories */
|
|
range = WebRtcIlbcfix_kSearchRange[block][stage];
|
|
|
|
/* initialize search measures */
|
|
CritMax=0;
|
|
shTotMax=-100;
|
|
bestIndex=0;
|
|
bestGain=0;
|
|
|
|
/* loop over lags 40+ in the first codebook section, full search */
|
|
cb_vecPtr = buf+lMem-lTarget;
|
|
|
|
/* Calculate all the cross correlations (augmented part of CB) */
|
|
if (lTarget==SUBL) {
|
|
WebRtcIlbcfix_AugmentedCbCorr(target, buf+lMem,
|
|
interpSamples, cDot,
|
|
20, 39, scale);
|
|
cDotPtr=&cDot[20];
|
|
} else {
|
|
cDotPtr=cDot;
|
|
}
|
|
/* Calculate all the cross correlations (main part of CB) */
|
|
WebRtcSpl_CrossCorrelation(cDotPtr, target, cb_vecPtr, lTarget, range, scale, -1);
|
|
|
|
/* Adjust the search range for the augmented vectors */
|
|
if (lTarget==SUBL) {
|
|
range=WebRtcIlbcfix_kSearchRange[block][stage]+20;
|
|
} else {
|
|
range=WebRtcIlbcfix_kSearchRange[block][stage];
|
|
}
|
|
|
|
indexOffset=0;
|
|
|
|
/* Search for best index in this part of the vector */
|
|
WebRtcIlbcfix_CbSearchCore(
|
|
cDot, range, stage, inverseEnergy,
|
|
inverseEnergyShifts, Crit,
|
|
&indexNew, &CritNew, &CritNewSh);
|
|
|
|
/* Update the global best index and the corresponding gain */
|
|
WebRtcIlbcfix_CbUpdateBestIndex(
|
|
CritNew, CritNewSh, (WebRtc_Word16)(indexNew+indexOffset), cDot[indexNew+indexOffset],
|
|
inverseEnergy[indexNew+indexOffset], inverseEnergyShifts[indexNew+indexOffset],
|
|
&CritMax, &shTotMax, &bestIndex, &bestGain);
|
|
|
|
sInd=bestIndex-(WebRtc_Word16)(CB_RESRANGE>>1);
|
|
eInd=sInd+CB_RESRANGE;
|
|
if (sInd<0) {
|
|
eInd-=sInd;
|
|
sInd=0;
|
|
}
|
|
if (eInd>=range) {
|
|
eInd=range-1;
|
|
sInd=eInd-CB_RESRANGE;
|
|
}
|
|
|
|
range = WebRtcIlbcfix_kSearchRange[block][stage];
|
|
|
|
if (lTarget==SUBL) {
|
|
i=sInd;
|
|
if (sInd<20) {
|
|
WebRtcIlbcfix_AugmentedCbCorr(target, cbvectors+lMem,
|
|
interpSamplesFilt, cDot,
|
|
(WebRtc_Word16)(sInd+20), (WebRtc_Word16)(WEBRTC_SPL_MIN(39, (eInd+20))), scale);
|
|
i=20;
|
|
}
|
|
|
|
cDotPtr=&cDot[WEBRTC_SPL_MAX(0,(20-sInd))];
|
|
cb_vecPtr = cbvectors+lMem-20-i;
|
|
|
|
/* Calculate the cross correlations (main part of the filtered CB) */
|
|
WebRtcSpl_CrossCorrelation(cDotPtr, target, cb_vecPtr, lTarget, (WebRtc_Word16)(eInd-i+1), scale, -1);
|
|
|
|
} else {
|
|
cDotPtr = cDot;
|
|
cb_vecPtr = cbvectors+lMem-lTarget-sInd;
|
|
|
|
/* Calculate the cross correlations (main part of the filtered CB) */
|
|
WebRtcSpl_CrossCorrelation(cDotPtr, target, cb_vecPtr, lTarget, (WebRtc_Word16)(eInd-sInd+1), scale, -1);
|
|
|
|
}
|
|
|
|
/* Adjust the search range for the augmented vectors */
|
|
indexOffset=base_size+sInd;
|
|
|
|
/* Search for best index in this part of the vector */
|
|
WebRtcIlbcfix_CbSearchCore(
|
|
cDot, (WebRtc_Word16)(eInd-sInd+1), stage, inverseEnergy+indexOffset,
|
|
inverseEnergyShifts+indexOffset, Crit,
|
|
&indexNew, &CritNew, &CritNewSh);
|
|
|
|
/* Update the global best index and the corresponding gain */
|
|
WebRtcIlbcfix_CbUpdateBestIndex(
|
|
CritNew, CritNewSh, (WebRtc_Word16)(indexNew+indexOffset), cDot[indexNew],
|
|
inverseEnergy[indexNew+indexOffset], inverseEnergyShifts[indexNew+indexOffset],
|
|
&CritMax, &shTotMax, &bestIndex, &bestGain);
|
|
|
|
index[stage] = bestIndex;
|
|
|
|
|
|
bestGain = WebRtcIlbcfix_GainQuant(bestGain,
|
|
(WebRtc_Word16)WEBRTC_SPL_ABS_W16(gains[stage]), stage, &gain_index[stage]);
|
|
|
|
/* Extract the best (according to measure) codebook vector
|
|
Also adjust the index, so that the augmented vectors are last.
|
|
Above these vectors were first...
|
|
*/
|
|
|
|
if(lTarget==(STATE_LEN-iLBCenc_inst->state_short_len)) {
|
|
|
|
if(index[stage]<base_size) {
|
|
pp=buf+lMem-lTarget-index[stage];
|
|
} else {
|
|
pp=cbvectors+lMem-lTarget-
|
|
index[stage]+base_size;
|
|
}
|
|
|
|
} else {
|
|
|
|
if (index[stage]<base_size) {
|
|
if (index[stage]>=20) {
|
|
/* Adjust index and extract vector */
|
|
index[stage]-=20;
|
|
pp=buf+lMem-lTarget-index[stage];
|
|
} else {
|
|
/* Adjust index and extract vector */
|
|
index[stage]+=(base_size-20);
|
|
|
|
WebRtcIlbcfix_CreateAugmentedVec((WebRtc_Word16)(index[stage]-base_size+40),
|
|
buf+lMem, aug_vec);
|
|
pp = aug_vec;
|
|
|
|
}
|
|
} else {
|
|
|
|
if ((index[stage] - base_size) >= 20) {
|
|
/* Adjust index and extract vector */
|
|
index[stage]-=20;
|
|
pp=cbvectors+lMem-lTarget-
|
|
index[stage]+base_size;
|
|
} else {
|
|
/* Adjust index and extract vector */
|
|
index[stage]+=(base_size-20);
|
|
WebRtcIlbcfix_CreateAugmentedVec((WebRtc_Word16)(index[stage]-2*base_size+40),
|
|
cbvectors+lMem, aug_vec);
|
|
pp = aug_vec;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Subtract the best codebook vector, according
|
|
to measure, from the target vector */
|
|
|
|
WebRtcSpl_AddAffineVectorToVector(target, pp, (WebRtc_Word16)(-bestGain), (WebRtc_Word32)8192, (WebRtc_Word16)14, (int)lTarget);
|
|
|
|
/* record quantized gain */
|
|
gains[stage+1] = bestGain;
|
|
|
|
} /* end of Main Loop. for (stage=0;... */
|
|
|
|
/* Calculte the coded vector (original target - what's left) */
|
|
for (i=0;i<lTarget;i++) {
|
|
codedVec[i]-=target[i];
|
|
}
|
|
|
|
/* Gain adjustment for energy matching */
|
|
codedEner = WebRtcSpl_DotProductWithScale(codedVec, codedVec, lTarget, scale);
|
|
|
|
j=gain_index[0];
|
|
|
|
temp1 = (WebRtc_Word16)WebRtcSpl_NormW32(codedEner);
|
|
temp2 = (WebRtc_Word16)WebRtcSpl_NormW32(targetEner);
|
|
|
|
if(temp1 < temp2) {
|
|
bits = 16 - temp1;
|
|
} else {
|
|
bits = 16 - temp2;
|
|
}
|
|
|
|
tmp = (WebRtc_Word16) WEBRTC_SPL_MUL_16_16_RSFT(gains[1],gains[1], 14);
|
|
|
|
targetEner = WEBRTC_SPL_MUL_16_16(
|
|
WEBRTC_SPL_SHIFT_W32(targetEner, -bits), tmp);
|
|
|
|
tmpW32 = ((WebRtc_Word32)(gains[1]-1))<<1;
|
|
|
|
/* Pointer to the table that contains
|
|
gain_sq5TblFIX * gain_sq5TblFIX in Q14 */
|
|
gainPtr=(WebRtc_Word16*)WebRtcIlbcfix_kGainSq5Sq+gain_index[0];
|
|
temp1 = (WebRtc_Word16)WEBRTC_SPL_SHIFT_W32(codedEner, -bits);
|
|
|
|
WebRtcIlbcfix_kGainSq5_ptr = (WebRtc_Word16*)&WebRtcIlbcfix_kGainSq5[j];
|
|
|
|
/* targetEner and codedEner are in Q(-2*scale) */
|
|
for (i=gain_index[0];i<32;i++) {
|
|
|
|
/* Change the index if
|
|
(codedEnergy*gainTbl[i]*gainTbl[i])<(targetEn*gain[0]*gain[0]) AND
|
|
gainTbl[i] < 2*gain[0]
|
|
*/
|
|
|
|
t32 = WEBRTC_SPL_MUL_16_16(temp1, (*gainPtr));
|
|
t32 = t32 - targetEner;
|
|
if (t32 < 0) {
|
|
if ((*WebRtcIlbcfix_kGainSq5_ptr) < tmpW32) {
|
|
j=i;
|
|
WebRtcIlbcfix_kGainSq5_ptr = (WebRtc_Word16*)&WebRtcIlbcfix_kGainSq5[i];
|
|
}
|
|
}
|
|
gainPtr++;
|
|
}
|
|
gain_index[0]=j;
|
|
|
|
return;
|
|
}
|