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_CbSearch.c 16 17******************************************************************/ 18 19#include "defines.h" 20#include "gain_quant.h" 21#include "filtered_cb_vecs.h" 22#include "constants.h" 23#include "cb_mem_energy.h" 24#include "interpolate_samples.h" 25#include "cb_mem_energy_augmentation.h" 26#include "cb_search_core.h" 27#include "energy_inverse.h" 28#include "augmented_cb_corr.h" 29#include "cb_update_best_index.h" 30#include "create_augmented_vec.h" 31 32/*----------------------------------------------------------------* 33 * Search routine for codebook encoding and gain quantization. 34 *----------------------------------------------------------------*/ 35 36void WebRtcIlbcfix_CbSearch( 37 IlbcEncoder *iLBCenc_inst, 38 /* (i) the encoder state structure */ 39 int16_t *index, /* (o) Codebook indices */ 40 int16_t *gain_index, /* (o) Gain quantization indices */ 41 int16_t *intarget, /* (i) Target vector for encoding */ 42 int16_t *decResidual,/* (i) Decoded residual for codebook construction */ 43 size_t lMem, /* (i) Length of buffer */ 44 size_t lTarget, /* (i) Length of vector */ 45 int16_t *weightDenum,/* (i) weighting filter coefficients in Q12 */ 46 size_t block /* (i) the subblock number */ 47 ) { 48 size_t i, range; 49 int16_t ii, j, stage; 50 int16_t *pp; 51 int16_t tmp; 52 int scale; 53 int16_t bits, temp1, temp2; 54 size_t base_size; 55 int32_t codedEner, targetEner; 56 int16_t gains[CB_NSTAGES+1]; 57 int16_t *cb_vecPtr; 58 size_t indexOffset, sInd, eInd; 59 int32_t CritMax=0; 60 int16_t shTotMax=WEBRTC_SPL_WORD16_MIN; 61 size_t bestIndex=0; 62 int16_t bestGain=0; 63 size_t indexNew; 64 int16_t CritNewSh; 65 int32_t CritNew; 66 int32_t *cDotPtr; 67 size_t noOfZeros; 68 int16_t *gainPtr; 69 int32_t t32, tmpW32; 70 int16_t *WebRtcIlbcfix_kGainSq5_ptr; 71 /* Stack based */ 72 int16_t CBbuf[CB_MEML+LPC_FILTERORDER+CB_HALFFILTERLEN]; 73 int32_t cDot[128]; 74 int32_t Crit[128]; 75 int16_t targetVec[SUBL+LPC_FILTERORDER]; 76 int16_t cbvectors[CB_MEML + 1]; /* Adding one extra position for 77 Coverity warnings. */ 78 int16_t codedVec[SUBL]; 79 int16_t interpSamples[20*4]; 80 int16_t interpSamplesFilt[20*4]; 81 int16_t energyW16[CB_EXPAND*128]; 82 int16_t energyShifts[CB_EXPAND*128]; 83 int16_t *inverseEnergy=energyW16; /* Reuse memory */ 84 int16_t *inverseEnergyShifts=energyShifts; /* Reuse memory */ 85 int16_t *buf = &CBbuf[LPC_FILTERORDER]; 86 int16_t *target = &targetVec[LPC_FILTERORDER]; 87 int16_t *aug_vec = (int16_t*)cDot; /* length [SUBL], reuse memory */ 88 89 /* Determine size of codebook sections */ 90 91 base_size=lMem-lTarget+1; 92 if (lTarget==SUBL) { 93 base_size=lMem-19; 94 } 95 96 /* weighting of the CB memory */ 97 noOfZeros=lMem-WebRtcIlbcfix_kFilterRange[block]; 98 WebRtcSpl_MemSetW16(&buf[-LPC_FILTERORDER], 0, noOfZeros+LPC_FILTERORDER); 99 WebRtcSpl_FilterARFastQ12( 100 decResidual+noOfZeros, buf+noOfZeros, 101 weightDenum, LPC_FILTERORDER+1, WebRtcIlbcfix_kFilterRange[block]); 102 103 /* weighting of the target vector */ 104 WEBRTC_SPL_MEMCPY_W16(&target[-LPC_FILTERORDER], buf+noOfZeros+WebRtcIlbcfix_kFilterRange[block]-LPC_FILTERORDER, LPC_FILTERORDER); 105 WebRtcSpl_FilterARFastQ12( 106 intarget, target, 107 weightDenum, LPC_FILTERORDER+1, lTarget); 108 109 /* Store target, towards the end codedVec is calculated as 110 the initial target minus the remaining target */ 111 WEBRTC_SPL_MEMCPY_W16(codedVec, target, lTarget); 112 113 /* Find the highest absolute value to calculate proper 114 vector scale factor (so that it uses 12 bits) */ 115 temp1 = WebRtcSpl_MaxAbsValueW16(buf, lMem); 116 temp2 = WebRtcSpl_MaxAbsValueW16(target, lTarget); 117 118 if ((temp1>0)&&(temp2>0)) { 119 temp1 = WEBRTC_SPL_MAX(temp1, temp2); 120 scale = WebRtcSpl_GetSizeInBits((uint32_t)(temp1 * temp1)); 121 } else { 122 /* temp1 or temp2 is negative (maximum was -32768) */ 123 scale = 30; 124 } 125 126 /* Scale to so that a mul-add 40 times does not overflow */ 127 scale = scale - 25; 128 scale = WEBRTC_SPL_MAX(0, scale); 129 130 /* Compute energy of the original target */ 131 targetEner = WebRtcSpl_DotProductWithScale(target, target, lTarget, scale); 132 133 /* Prepare search over one more codebook section. This section 134 is created by filtering the original buffer with a filter. */ 135 WebRtcIlbcfix_FilteredCbVecs(cbvectors, buf, lMem, WebRtcIlbcfix_kFilterRange[block]); 136 137 range = WebRtcIlbcfix_kSearchRange[block][0]; 138 139 if(lTarget == SUBL) { 140 /* Create the interpolated samples and store them for use in all stages */ 141 142 /* First section, non-filtered half of the cb */ 143 WebRtcIlbcfix_InterpolateSamples(interpSamples, buf, lMem); 144 145 /* Second section, filtered half of the cb */ 146 WebRtcIlbcfix_InterpolateSamples(interpSamplesFilt, cbvectors, lMem); 147 148 /* Compute the CB vectors' energies for the first cb section (non-filtered) */ 149 WebRtcIlbcfix_CbMemEnergyAugmentation(interpSamples, buf, 150 scale, 20, energyW16, energyShifts); 151 152 /* Compute the CB vectors' energies for the second cb section (filtered cb) */ 153 WebRtcIlbcfix_CbMemEnergyAugmentation(interpSamplesFilt, cbvectors, scale, 154 base_size + 20, energyW16, 155 energyShifts); 156 157 /* Compute the CB vectors' energies and store them in the vector 158 * energyW16. Also the corresponding shift values are stored. The 159 * energy values are used in all three stages. */ 160 WebRtcIlbcfix_CbMemEnergy(range, buf, cbvectors, lMem, 161 lTarget, energyW16+20, energyShifts+20, scale, base_size); 162 163 } else { 164 /* Compute the CB vectors' energies and store them in the vector 165 * energyW16. Also the corresponding shift values are stored. The 166 * energy values are used in all three stages. */ 167 WebRtcIlbcfix_CbMemEnergy(range, buf, cbvectors, lMem, 168 lTarget, energyW16, energyShifts, scale, base_size); 169 170 /* Set the energy positions 58-63 and 122-127 to zero 171 (otherwise they are uninitialized) */ 172 WebRtcSpl_MemSetW16(energyW16+range, 0, (base_size-range)); 173 WebRtcSpl_MemSetW16(energyW16+range+base_size, 0, (base_size-range)); 174 } 175 176 /* Calculate Inverse Energy (energyW16 is already normalized 177 and will contain the inverse energy in Q29 after this call */ 178 WebRtcIlbcfix_EnergyInverse(energyW16, base_size*CB_EXPAND); 179 180 /* The gain value computed in the previous stage is used 181 * as an upper limit to what the next stage gain value 182 * is allowed to be. In stage 0, 16384 (1.0 in Q14) is used as 183 * the upper limit. */ 184 gains[0] = 16384; 185 186 for (stage=0; stage<CB_NSTAGES; stage++) { 187 188 /* Set up memories */ 189 range = WebRtcIlbcfix_kSearchRange[block][stage]; 190 191 /* initialize search measures */ 192 CritMax=0; 193 shTotMax=-100; 194 bestIndex=0; 195 bestGain=0; 196 197 /* loop over lags 40+ in the first codebook section, full search */ 198 cb_vecPtr = buf+lMem-lTarget; 199 200 /* Calculate all the cross correlations (augmented part of CB) */ 201 if (lTarget==SUBL) { 202 WebRtcIlbcfix_AugmentedCbCorr(target, buf+lMem, 203 interpSamples, cDot, 204 20, 39, scale); 205 cDotPtr=&cDot[20]; 206 } else { 207 cDotPtr=cDot; 208 } 209 /* Calculate all the cross correlations (main part of CB) */ 210 WebRtcSpl_CrossCorrelation(cDotPtr, target, cb_vecPtr, lTarget, range, scale, -1); 211 212 /* Adjust the search range for the augmented vectors */ 213 if (lTarget==SUBL) { 214 range=WebRtcIlbcfix_kSearchRange[block][stage]+20; 215 } else { 216 range=WebRtcIlbcfix_kSearchRange[block][stage]; 217 } 218 219 indexOffset=0; 220 221 /* Search for best index in this part of the vector */ 222 WebRtcIlbcfix_CbSearchCore( 223 cDot, range, stage, inverseEnergy, 224 inverseEnergyShifts, Crit, 225 &indexNew, &CritNew, &CritNewSh); 226 227 /* Update the global best index and the corresponding gain */ 228 WebRtcIlbcfix_CbUpdateBestIndex( 229 CritNew, CritNewSh, indexNew+indexOffset, cDot[indexNew+indexOffset], 230 inverseEnergy[indexNew+indexOffset], inverseEnergyShifts[indexNew+indexOffset], 231 &CritMax, &shTotMax, &bestIndex, &bestGain); 232 233 sInd = ((CB_RESRANGE >> 1) > bestIndex) ? 234 0 : (bestIndex - (CB_RESRANGE >> 1)); 235 eInd=sInd+CB_RESRANGE; 236 if (eInd>=range) { 237 eInd=range-1; 238 sInd=eInd-CB_RESRANGE; 239 } 240 241 range = WebRtcIlbcfix_kSearchRange[block][stage]; 242 243 if (lTarget==SUBL) { 244 i=sInd; 245 if (sInd<20) { 246 WebRtcIlbcfix_AugmentedCbCorr(target, cbvectors + lMem, 247 interpSamplesFilt, cDot, sInd + 20, 248 WEBRTC_SPL_MIN(39, (eInd + 20)), scale); 249 i=20; 250 cDotPtr = &cDot[20 - sInd]; 251 } else { 252 cDotPtr = cDot; 253 } 254 255 cb_vecPtr = cbvectors+lMem-20-i; 256 257 /* Calculate the cross correlations (main part of the filtered CB) */ 258 WebRtcSpl_CrossCorrelation(cDotPtr, target, cb_vecPtr, lTarget, 259 eInd - i + 1, scale, -1); 260 261 } else { 262 cDotPtr = cDot; 263 cb_vecPtr = cbvectors+lMem-lTarget-sInd; 264 265 /* Calculate the cross correlations (main part of the filtered CB) */ 266 WebRtcSpl_CrossCorrelation(cDotPtr, target, cb_vecPtr, lTarget, 267 eInd - sInd + 1, scale, -1); 268 269 } 270 271 /* Adjust the search range for the augmented vectors */ 272 indexOffset=base_size+sInd; 273 274 /* Search for best index in this part of the vector */ 275 WebRtcIlbcfix_CbSearchCore( 276 cDot, eInd-sInd+1, stage, inverseEnergy+indexOffset, 277 inverseEnergyShifts+indexOffset, Crit, 278 &indexNew, &CritNew, &CritNewSh); 279 280 /* Update the global best index and the corresponding gain */ 281 WebRtcIlbcfix_CbUpdateBestIndex( 282 CritNew, CritNewSh, indexNew+indexOffset, cDot[indexNew], 283 inverseEnergy[indexNew+indexOffset], inverseEnergyShifts[indexNew+indexOffset], 284 &CritMax, &shTotMax, &bestIndex, &bestGain); 285 286 index[stage] = (int16_t)bestIndex; 287 288 289 bestGain = WebRtcIlbcfix_GainQuant(bestGain, 290 (int16_t)WEBRTC_SPL_ABS_W16(gains[stage]), stage, &gain_index[stage]); 291 292 /* Extract the best (according to measure) codebook vector 293 Also adjust the index, so that the augmented vectors are last. 294 Above these vectors were first... 295 */ 296 297 if(lTarget==(STATE_LEN-iLBCenc_inst->state_short_len)) { 298 299 if((size_t)index[stage]<base_size) { 300 pp=buf+lMem-lTarget-index[stage]; 301 } else { 302 pp=cbvectors+lMem-lTarget- 303 index[stage]+base_size; 304 } 305 306 } else { 307 308 if ((size_t)index[stage]<base_size) { 309 if (index[stage]>=20) { 310 /* Adjust index and extract vector */ 311 index[stage]-=20; 312 pp=buf+lMem-lTarget-index[stage]; 313 } else { 314 /* Adjust index and extract vector */ 315 index[stage]+=(int16_t)(base_size-20); 316 317 WebRtcIlbcfix_CreateAugmentedVec(index[stage]-base_size+40, 318 buf+lMem, aug_vec); 319 pp = aug_vec; 320 321 } 322 } else { 323 324 if ((index[stage] - base_size) >= 20) { 325 /* Adjust index and extract vector */ 326 index[stage]-=20; 327 pp=cbvectors+lMem-lTarget- 328 index[stage]+base_size; 329 } else { 330 /* Adjust index and extract vector */ 331 index[stage]+=(int16_t)(base_size-20); 332 WebRtcIlbcfix_CreateAugmentedVec(index[stage]-2*base_size+40, 333 cbvectors+lMem, aug_vec); 334 pp = aug_vec; 335 } 336 } 337 } 338 339 /* Subtract the best codebook vector, according 340 to measure, from the target vector */ 341 342 WebRtcSpl_AddAffineVectorToVector(target, pp, (int16_t)(-bestGain), 343 (int32_t)8192, (int16_t)14, lTarget); 344 345 /* record quantized gain */ 346 gains[stage+1] = bestGain; 347 348 } /* end of Main Loop. for (stage=0;... */ 349 350 /* Calculte the coded vector (original target - what's left) */ 351 for (i=0;i<lTarget;i++) { 352 codedVec[i]-=target[i]; 353 } 354 355 /* Gain adjustment for energy matching */ 356 codedEner = WebRtcSpl_DotProductWithScale(codedVec, codedVec, lTarget, scale); 357 358 j=gain_index[0]; 359 360 temp1 = (int16_t)WebRtcSpl_NormW32(codedEner); 361 temp2 = (int16_t)WebRtcSpl_NormW32(targetEner); 362 363 if(temp1 < temp2) { 364 bits = 16 - temp1; 365 } else { 366 bits = 16 - temp2; 367 } 368 369 tmp = (int16_t)((gains[1] * gains[1]) >> 14); 370 371 targetEner = (int16_t)WEBRTC_SPL_SHIFT_W32(targetEner, -bits) * tmp; 372 373 tmpW32 = ((int32_t)(gains[1]-1))<<1; 374 375 /* Pointer to the table that contains 376 gain_sq5TblFIX * gain_sq5TblFIX in Q14 */ 377 gainPtr=(int16_t*)WebRtcIlbcfix_kGainSq5Sq+gain_index[0]; 378 temp1 = (int16_t)WEBRTC_SPL_SHIFT_W32(codedEner, -bits); 379 380 WebRtcIlbcfix_kGainSq5_ptr = (int16_t*)&WebRtcIlbcfix_kGainSq5[j]; 381 382 /* targetEner and codedEner are in Q(-2*scale) */ 383 for (ii=gain_index[0];ii<32;ii++) { 384 385 /* Change the index if 386 (codedEnergy*gainTbl[i]*gainTbl[i])<(targetEn*gain[0]*gain[0]) AND 387 gainTbl[i] < 2*gain[0] 388 */ 389 390 t32 = temp1 * *gainPtr; 391 t32 = t32 - targetEner; 392 if (t32 < 0) { 393 if ((*WebRtcIlbcfix_kGainSq5_ptr) < tmpW32) { 394 j=ii; 395 WebRtcIlbcfix_kGainSq5_ptr = (int16_t*)&WebRtcIlbcfix_kGainSq5[ii]; 396 } 397 } 398 gainPtr++; 399 } 400 gain_index[0]=j; 401 402 return; 403} 404