void WebRtcIlbcfix_CbSearch( IlbcEncoder *iLBCenc_inst, /* (i) the encoder state structure */ int16_t *index, /* (o) Codebook indices */ int16_t *gain_index, /* (o) Gain quantization indices */ int16_t *intarget, /* (i) Target vector for encoding */ int16_t *decResidual,/* (i) Decoded residual for codebook construction */ int16_t lMem, /* (i) Length of buffer */ int16_t lTarget, /* (i) Length of vector */ int16_t *weightDenum,/* (i) weighting filter coefficients in Q12 */ int16_t block /* (i) the subblock number */ ) { int16_t i, j, stage, range; int16_t *pp, scale, tmp; int16_t bits, temp1, temp2; int16_t base_size; int32_t codedEner, targetEner; int16_t gains[CB_NSTAGES+1]; int16_t *cb_vecPtr; int16_t indexOffset, sInd, eInd; int32_t CritMax=0; int16_t shTotMax=WEBRTC_SPL_WORD16_MIN; int16_t bestIndex=0; int16_t bestGain=0; int16_t indexNew, CritNewSh; int32_t CritNew; int32_t *cDotPtr; int16_t noOfZeros; int16_t *gainPtr; int32_t t32, tmpW32; int16_t *WebRtcIlbcfix_kGainSq5_ptr; /* Stack based */ int16_t CBbuf[CB_MEML+LPC_FILTERORDER+CB_HALFFILTERLEN]; int32_t cDot[128]; int32_t Crit[128]; int16_t targetVec[SUBL+LPC_FILTERORDER]; int16_t cbvectors[CB_MEML + 1]; /* Adding one extra position for Coverity warnings. */ int16_t codedVec[SUBL]; int16_t interpSamples[20*4]; int16_t interpSamplesFilt[20*4]; int16_t energyW16[CB_EXPAND*128]; int16_t energyShifts[CB_EXPAND*128]; int16_t *inverseEnergy=energyW16; /* Reuse memory */ int16_t *inverseEnergyShifts=energyShifts; /* Reuse memory */ int16_t *buf = &CBbuf[LPC_FILTERORDER]; int16_t *target = &targetVec[LPC_FILTERORDER]; int16_t *aug_vec = (int16_t*)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, (int16_t)lMem); temp2 = WebRtcSpl_MaxAbsValueW16(target, (int16_t)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, (int16_t)(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, (int16_t)(indexNew+indexOffset), cDot[indexNew+indexOffset], inverseEnergy[indexNew+indexOffset], inverseEnergyShifts[indexNew+indexOffset], &CritMax, &shTotMax, &bestIndex, &bestGain); sInd=bestIndex-(int16_t)(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, (int16_t)(sInd+20), (int16_t)(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, (int16_t)(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, (int16_t)(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, (int16_t)(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, (int16_t)(indexNew+indexOffset), cDot[indexNew], inverseEnergy[indexNew+indexOffset], inverseEnergyShifts[indexNew+indexOffset], &CritMax, &shTotMax, &bestIndex, &bestGain); index[stage] = bestIndex; bestGain = WebRtcIlbcfix_GainQuant(bestGain, (int16_t)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((int16_t)(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((int16_t)(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, (int16_t)(-bestGain), (int32_t)8192, (int16_t)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 = (int16_t)WebRtcSpl_NormW32(codedEner); temp2 = (int16_t)WebRtcSpl_NormW32(targetEner); if(temp1 < temp2) { bits = 16 - temp1; } else { bits = 16 - temp2; } tmp = (int16_t) 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 = ((int32_t)(gains[1]-1))<<1; /* Pointer to the table that contains gain_sq5TblFIX * gain_sq5TblFIX in Q14 */ gainPtr=(int16_t*)WebRtcIlbcfix_kGainSq5Sq+gain_index[0]; temp1 = (int16_t)WEBRTC_SPL_SHIFT_W32(codedEner, -bits); WebRtcIlbcfix_kGainSq5_ptr = (int16_t*)&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 = (int16_t*)&WebRtcIlbcfix_kGainSq5[i]; } } gainPtr++; } gain_index[0]=j; return; }
void WebRtcIlbcfix_Refiner( WebRtc_Word16 *updStartPos, /* (o) updated start point (Q-2) */ WebRtc_Word16 *idata, /* (i) original data buffer */ WebRtc_Word16 idatal, /* (i) dimension of idata */ WebRtc_Word16 centerStartPos, /* (i) beginning center segment */ WebRtc_Word16 estSegPos, /* (i) estimated beginning other segment (Q-2) */ WebRtc_Word16 *surround, /* (i/o) The contribution from this sequence summed with earlier contributions */ WebRtc_Word16 gain /* (i) Gain to use for this sequence */ ){ WebRtc_Word16 estSegPosRounded,searchSegStartPos,searchSegEndPos,corrdim; WebRtc_Word16 tloc,tloc2,i,st,en,fraction; WebRtc_Word32 maxtemp, scalefact; WebRtc_Word16 *filtStatePtr, *polyPtr; /* Stack based */ WebRtc_Word16 filt[7]; WebRtc_Word32 corrVecUps[ENH_CORRDIM*ENH_UPS0]; WebRtc_Word32 corrVecTemp[ENH_CORRDIM]; WebRtc_Word16 vect[ENH_VECTL]; WebRtc_Word16 corrVec[ENH_CORRDIM]; /* defining array bounds */ estSegPosRounded=WEBRTC_SPL_RSHIFT_W16((estSegPos - 2),2); searchSegStartPos=estSegPosRounded-ENH_SLOP; if (searchSegStartPos<0) { searchSegStartPos=0; } searchSegEndPos=estSegPosRounded+ENH_SLOP; if(searchSegEndPos+ENH_BLOCKL >= idatal) { searchSegEndPos=idatal-ENH_BLOCKL-1; } corrdim=searchSegEndPos-searchSegStartPos+1; /* compute upsampled correlation and find location of max */ WebRtcIlbcfix_MyCorr(corrVecTemp,idata+searchSegStartPos, (WebRtc_Word16)(corrdim+ENH_BLOCKL-1),idata+centerStartPos,ENH_BLOCKL); /* Calculate the rescaling factor for the correlation in order to put the correlation in a WebRtc_Word16 vector instead */ maxtemp=WebRtcSpl_MaxAbsValueW32(corrVecTemp, (WebRtc_Word16)corrdim); scalefact=WebRtcSpl_GetSizeInBits(maxtemp)-15; if (scalefact>0) { for (i=0;i<corrdim;i++) { corrVec[i]=(WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(corrVecTemp[i], scalefact); } } else { for (i=0;i<corrdim;i++) { corrVec[i]=(WebRtc_Word16)corrVecTemp[i]; } } /* In order to guarantee that all values are initialized */ for (i=corrdim;i<ENH_CORRDIM;i++) { corrVec[i]=0; } /* Upsample the correlation */ WebRtcIlbcfix_EnhUpsample(corrVecUps,corrVec); /* Find maximum */ tloc=WebRtcSpl_MaxIndexW32(corrVecUps, (WebRtc_Word16) (ENH_UPS0*corrdim)); /* make vector can be upsampled without ever running outside bounds */ *updStartPos = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16(searchSegStartPos,4) + tloc + 4; tloc2 = WEBRTC_SPL_RSHIFT_W16((tloc+3), 2); st=searchSegStartPos+tloc2-ENH_FL0; /* initialize the vector to be filtered, stuff with zeros when data is outside idata buffer */ if(st<0){ WebRtcSpl_MemSetW16(vect, 0, (WebRtc_Word16)(-st)); WEBRTC_SPL_MEMCPY_W16(&vect[-st], idata, (ENH_VECTL+st)); } else{ en=st+ENH_VECTL; if(en>idatal){ WEBRTC_SPL_MEMCPY_W16(vect, &idata[st], (ENH_VECTL-(en-idatal))); WebRtcSpl_MemSetW16(&vect[ENH_VECTL-(en-idatal)], 0, (WebRtc_Word16)(en-idatal)); } else { WEBRTC_SPL_MEMCPY_W16(vect, &idata[st], ENH_VECTL); } } /* Calculate which of the 4 fractions to use */ fraction=(WebRtc_Word16)WEBRTC_SPL_MUL_16_16(tloc2,ENH_UPS0)-tloc; /* compute the segment (this is actually a convolution) */ filtStatePtr = filt + 6; polyPtr = (WebRtc_Word16*)WebRtcIlbcfix_kEnhPolyPhaser[fraction]; for (i=0;i<7;i++) { *filtStatePtr-- = *polyPtr++; } WebRtcSpl_FilterMAFastQ12( &vect[6], vect, filt, ENH_FLO_MULT2_PLUS1, ENH_BLOCKL); /* Add the contribution from this vector (scaled with gain) to the total surround vector */ WebRtcSpl_AddAffineVectorToVector( surround, vect, gain, (WebRtc_Word32)32768, 16, ENH_BLOCKL); return; }