git-svn-id: http://webrtc.googlecode.com/svn/trunk@4 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
396
modules/audio_coding/codecs/iLBC/main/source/cb_search.c
Normal file
396
modules/audio_coding/codecs/iLBC/main/source/cb_search.c
Normal file
@@ -0,0 +1,396 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
Reference in New Issue
Block a user