blob: dfbc50b75a9ac0a5fe2f8efbea4beedfb2201ec3 [file] [log] [blame]
Benny Prijonoc5859882006-07-31 15:25:14 +00001
2 /******************************************************************
3
4 iLBC Speech Coder ANSI-C Source Code
5
6 iCBSearch.c
7
8 Copyright (C) The Internet Society (2004).
9 All Rights Reserved.
10
11 ******************************************************************/
12
13 #include <math.h>
14 #include <string.h>
15
16 #include "iLBC_define.h"
17 #include "gainquant.h"
18 #include "createCB.h"
19 #include "filter.h"
20 #include "constants.h"
21
22 /*----------------------------------------------------------------*
23 * Search routine for codebook encoding and gain quantization.
24 *---------------------------------------------------------------*/
25
26 void iCBSearch(
27 iLBC_Enc_Inst_t *iLBCenc_inst,
28 /* (i) the encoder state structure */
29 int *index, /* (o) Codebook indices */
30 int *gain_index,/* (o) Gain quantization indices */
31
32
33
34
35
36 float *intarget,/* (i) Target vector for encoding */
37 float *mem, /* (i) Buffer for codebook construction */
38 int lMem, /* (i) Length of buffer */
39 int lTarget, /* (i) Length of vector */
40 int nStages, /* (i) Number of codebook stages */
41 float *weightDenum, /* (i) weighting filter coefficients */
42 float *weightState, /* (i) weighting filter state */
43 int block /* (i) the sub-block number */
44 ){
45 int i, j, icount, stage, best_index, range, counter;
46 float max_measure, gain, measure, crossDot, ftmp;
47 float gains[CB_NSTAGES];
48 float target[SUBL];
49 int base_index, sInd, eInd, base_size;
50 int sIndAug=0, eIndAug=0;
51 float buf[CB_MEML+SUBL+2*LPC_FILTERORDER];
52 float invenergy[CB_EXPAND*128], energy[CB_EXPAND*128];
53 float *pp, *ppi=0, *ppo=0, *ppe=0;
54 float cbvectors[CB_MEML];
55 float tene, cene, cvec[SUBL];
56 float aug_vec[SUBL];
57
58 memset(cvec,0,SUBL*sizeof(float));
59
60 /* Determine size of codebook sections */
61
62 base_size=lMem-lTarget+1;
63
64 if (lTarget==SUBL) {
65 base_size=lMem-lTarget+1+lTarget/2;
66 }
67
68 /* setup buffer for weighting */
69
70 memcpy(buf,weightState,sizeof(float)*LPC_FILTERORDER);
71 memcpy(buf+LPC_FILTERORDER,mem,lMem*sizeof(float));
72 memcpy(buf+LPC_FILTERORDER+lMem,intarget,lTarget*sizeof(float));
73
74 /* weighting */
75
76 AllPoleFilter(buf+LPC_FILTERORDER, weightDenum,
77 lMem+lTarget, LPC_FILTERORDER);
78
79 /* Construct the codebook and target needed */
80
81 memcpy(target, buf+LPC_FILTERORDER+lMem, lTarget*sizeof(float));
82
83 tene=0.0;
84
85
86
87
88
89 for (i=0; i<lTarget; i++) {
90 tene+=target[i]*target[i];
91 }
92
93 /* Prepare search over one more codebook section. This section
94 is created by filtering the original buffer with a filter. */
95
96 filteredCBvecs(cbvectors, buf+LPC_FILTERORDER, lMem);
97
98 /* The Main Loop over stages */
99
100 for (stage=0; stage<nStages; stage++) {
101
102 range = search_rangeTbl[block][stage];
103
104 /* initialize search measure */
105
106 max_measure = (float)-10000000.0;
107 gain = (float)0.0;
108 best_index = 0;
109
110 /* Compute cross dot product between the target
111 and the CB memory */
112
113 crossDot=0.0;
114 pp=buf+LPC_FILTERORDER+lMem-lTarget;
115 for (j=0; j<lTarget; j++) {
116 crossDot += target[j]*(*pp++);
117 }
118
119 if (stage==0) {
120
121 /* Calculate energy in the first block of
122 'lTarget' samples. */
123 ppe = energy;
124 ppi = buf+LPC_FILTERORDER+lMem-lTarget-1;
125 ppo = buf+LPC_FILTERORDER+lMem-1;
126
127 *ppe=0.0;
128 pp=buf+LPC_FILTERORDER+lMem-lTarget;
129 for (j=0; j<lTarget; j++) {
Benny Prijono594e4c52006-09-14 18:51:01 +0000130 *ppe+=(*pp)*(*pp);
131 ++pp;
Benny Prijonoc5859882006-07-31 15:25:14 +0000132 }
133
134 if (*ppe>0.0) {
135 invenergy[0] = (float) 1.0 / (*ppe + EPS);
136 } else {
137 invenergy[0] = (float) 0.0;
138
139
140
141
142
143 }
144 ppe++;
145
146 measure=(float)-10000000.0;
147
148 if (crossDot > 0.0) {
149 measure = crossDot*crossDot*invenergy[0];
150 }
151 }
152 else {
153 measure = crossDot*crossDot*invenergy[0];
154 }
155
156 /* check if measure is better */
157 ftmp = crossDot*invenergy[0];
158
159 if ((measure>max_measure) && (fabs(ftmp)<CB_MAXGAIN)) {
160 best_index = 0;
161 max_measure = measure;
162 gain = ftmp;
163 }
164
165 /* loop over the main first codebook section,
166 full search */
167
168 for (icount=1; icount<range; icount++) {
169
170 /* calculate measure */
171
172 crossDot=0.0;
173 pp = buf+LPC_FILTERORDER+lMem-lTarget-icount;
174
175 for (j=0; j<lTarget; j++) {
176 crossDot += target[j]*(*pp++);
177 }
178
179 if (stage==0) {
180 *ppe++ = energy[icount-1] + (*ppi)*(*ppi) -
181 (*ppo)*(*ppo);
182 ppo--;
183 ppi--;
184
185 if (energy[icount]>0.0) {
186 invenergy[icount] =
187 (float)1.0/(energy[icount]+EPS);
188 } else {
189 invenergy[icount] = (float) 0.0;
190 }
191
192
193
194
195
196 measure=(float)-10000000.0;
197
198 if (crossDot > 0.0) {
199 measure = crossDot*crossDot*invenergy[icount];
200 }
201 }
202 else {
203 measure = crossDot*crossDot*invenergy[icount];
204 }
205
206 /* check if measure is better */
207 ftmp = crossDot*invenergy[icount];
208
209 if ((measure>max_measure) && (fabs(ftmp)<CB_MAXGAIN)) {
210 best_index = icount;
211 max_measure = measure;
212 gain = ftmp;
213 }
214 }
215
216 /* Loop over augmented part in the first codebook
217 * section, full search.
218 * The vectors are interpolated.
219 */
220
221 if (lTarget==SUBL) {
222
223 /* Search for best possible cb vector and
224 compute the CB-vectors' energy. */
225 searchAugmentedCB(20, 39, stage, base_size-lTarget/2,
226 target, buf+LPC_FILTERORDER+lMem,
227 &max_measure, &best_index, &gain, energy,
228 invenergy);
229 }
230
231 /* set search range for following codebook sections */
232
233 base_index=best_index;
234
235 /* unrestricted search */
236
237 if (CB_RESRANGE == -1) {
238 sInd=0;
239 eInd=range-1;
240 sIndAug=20;
241 eIndAug=39;
242 }
243
244
245
246
247
248
249 /* restricted search around best index from first
250 codebook section */
251
252 else {
253 /* Initialize search indices */
254 sIndAug=0;
255 eIndAug=0;
256 sInd=base_index-CB_RESRANGE/2;
257 eInd=sInd+CB_RESRANGE;
258
259 if (lTarget==SUBL) {
260
261 if (sInd<0) {
262
263 sIndAug = 40 + sInd;
264 eIndAug = 39;
265 sInd=0;
266
267 } else if ( base_index < (base_size-20) ) {
268
269 if (eInd > range) {
270 sInd -= (eInd-range);
271 eInd = range;
272 }
273 } else { /* base_index >= (base_size-20) */
274
275 if (sInd < (base_size-20)) {
276 sIndAug = 20;
277 sInd = 0;
278 eInd = 0;
279 eIndAug = 19 + CB_RESRANGE;
280
281 if(eIndAug > 39) {
282 eInd = eIndAug-39;
283 eIndAug = 39;
284 }
285 } else {
286 sIndAug = 20 + sInd - (base_size-20);
287 eIndAug = 39;
288 sInd = 0;
289 eInd = CB_RESRANGE - (eIndAug-sIndAug+1);
290 }
291 }
292
293 } else { /* lTarget = 22 or 23 */
294
295 if (sInd < 0) {
296 eInd -= sInd;
297
298
299
300
301
302 sInd = 0;
303 }
304
305 if(eInd > range) {
306 sInd -= (eInd - range);
307 eInd = range;
308 }
309 }
310 }
311
312 /* search of higher codebook section */
313
314 /* index search range */
315 counter = sInd;
316 sInd += base_size;
317 eInd += base_size;
318
319
320 if (stage==0) {
321 ppe = energy+base_size;
322 *ppe=0.0;
323
324 pp=cbvectors+lMem-lTarget;
325 for (j=0; j<lTarget; j++) {
Benny Prijono594e4c52006-09-14 18:51:01 +0000326 *ppe+=(*pp)*(*pp);
327 ++pp;
Benny Prijonoc5859882006-07-31 15:25:14 +0000328 }
329
330 ppi = cbvectors + lMem - 1 - lTarget;
331 ppo = cbvectors + lMem - 1;
332
333 for (j=0; j<(range-1); j++) {
334 *(ppe+1) = *ppe + (*ppi)*(*ppi) - (*ppo)*(*ppo);
335 ppo--;
336 ppi--;
337 ppe++;
338 }
339 }
340
341 /* loop over search range */
342
343 for (icount=sInd; icount<eInd; icount++) {
344
345 /* calculate measure */
346
347 crossDot=0.0;
348 pp=cbvectors + lMem - (counter++) - lTarget;
349
350 for (j=0;j<lTarget;j++) {
351
352
353
354
355
356 crossDot += target[j]*(*pp++);
357 }
358
359 if (energy[icount]>0.0) {
360 invenergy[icount] =(float)1.0/(energy[icount]+EPS);
361 } else {
362 invenergy[icount] =(float)0.0;
363 }
364
365 if (stage==0) {
366
367 measure=(float)-10000000.0;
368
369 if (crossDot > 0.0) {
370 measure = crossDot*crossDot*
371 invenergy[icount];
372 }
373 }
374 else {
375 measure = crossDot*crossDot*invenergy[icount];
376 }
377
378 /* check if measure is better */
379 ftmp = crossDot*invenergy[icount];
380
381 if ((measure>max_measure) && (fabs(ftmp)<CB_MAXGAIN)) {
382 best_index = icount;
383 max_measure = measure;
384 gain = ftmp;
385 }
386 }
387
388 /* Search the augmented CB inside the limited range. */
389
390 if ((lTarget==SUBL)&&(sIndAug!=0)) {
391 searchAugmentedCB(sIndAug, eIndAug, stage,
392 2*base_size-20, target, cbvectors+lMem,
393 &max_measure, &best_index, &gain, energy,
394 invenergy);
395 }
396
397 /* record best index */
398
399 index[stage] = best_index;
400
401 /* gain quantization */
402
403 if (stage==0){
404
405
406
407
408
409
410 if (gain<0.0){
411 gain = 0.0;
412 }
413
414 if (gain>CB_MAXGAIN) {
415 gain = (float)CB_MAXGAIN;
416 }
417 gain = gainquant(gain, 1.0, 32, &gain_index[stage]);
418 }
419 else {
420 if (stage==1) {
421 gain = gainquant(gain, (float)fabs(gains[stage-1]),
422 16, &gain_index[stage]);
423 } else {
424 gain = gainquant(gain, (float)fabs(gains[stage-1]),
425 8, &gain_index[stage]);
426 }
427 }
428
429 /* Extract the best (according to measure)
430 codebook vector */
431
432 if (lTarget==(STATE_LEN-iLBCenc_inst->state_short_len)) {
433
434 if (index[stage]<base_size) {
435 pp=buf+LPC_FILTERORDER+lMem-lTarget-index[stage];
436 } else {
437 pp=cbvectors+lMem-lTarget-
438 index[stage]+base_size;
439 }
440 } else {
441
442 if (index[stage]<base_size) {
443 if (index[stage]<(base_size-20)) {
444 pp=buf+LPC_FILTERORDER+lMem-
445 lTarget-index[stage];
446 } else {
447 createAugmentedVec(index[stage]-base_size+40,
448 buf+LPC_FILTERORDER+lMem,aug_vec);
449 pp=aug_vec;
450 }
451 } else {
452 int filterno, position;
453
454 filterno=index[stage]/base_size;
455 position=index[stage]-filterno*base_size;
456
457
458
459
460
461
462
463 if (position<(base_size-20)) {
464 pp=cbvectors+filterno*lMem-lTarget-
465 index[stage]+filterno*base_size;
466 } else {
467 createAugmentedVec(
468 index[stage]-(filterno+1)*base_size+40,
469 cbvectors+filterno*lMem,aug_vec);
470 pp=aug_vec;
471 }
472 }
473 }
474
475 /* Subtract the best codebook vector, according
476 to measure, from the target vector */
477
478 for (j=0;j<lTarget;j++) {
479 cvec[j] += gain*(*pp);
480 target[j] -= gain*(*pp++);
481 }
482
483 /* record quantized gain */
484
485 gains[stage]=gain;
486
487 }/* end of Main Loop. for (stage=0;... */
488
489 /* Gain adjustment for energy matching */
490 cene=0.0;
491 for (i=0; i<lTarget; i++) {
492 cene+=cvec[i]*cvec[i];
493 }
494 j=gain_index[0];
495
496 for (i=gain_index[0]; i<32; i++) {
497 ftmp=cene*gain_sq5Tbl[i]*gain_sq5Tbl[i];
498
499 if ((ftmp<(tene*gains[0]*gains[0])) &&
500 (gain_sq5Tbl[j]<(2.0*gains[0]))) {
501 j=i;
502 }
503 }
504 gain_index[0]=j;
505 }
506
507
508
509
510
511
512
513
514