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