2 /******************************************************************
4 iLBC Speech Coder ANSI-C Source Code
12 ******************************************************************/
17 #include "iLBC_define.h"
18 #include "iCBSearch.h"
19 #include "gainquant.h"
22 #include "constants.h"
24 /*----------------------------------------------------------------*
25 * Search routine for codebook encoding and gain quantization.
26 *---------------------------------------------------------------*/
29 int *index, /* (o) Codebook indices */
30 int *gain_index,/* (o) Gain quantization indices */
31 float *intarget,/* (i) Target vector for encoding */
32 float *mem, /* (i) Buffer for codebook construction */
33 int lMem, /* (i) Length of buffer */
34 int lTarget, /* (i) Length of vector */
35 int nStages, /* (i) Number of codebook stages */
36 float *weightDenum, /* (i) weighting filter coefficients */
37 float *weightState, /* (i) weighting filter state */
38 int block /* (i) the subblock number */
40 int i, j, icount, stage, best_index, range, counter;
41 float max_measure, gain, measure, crossDot, ftmp;
42 float gains[CB_NSTAGES];
44 int base_index, sInd, eInd, base_size;
45 int sIndAug=0, eIndAug=0;
46 float buf[CB_MEML+SUBL+2*LPC_FILTERORDER];
47 float invenergy[CB_EXPAND*128], energy[CB_EXPAND*128];
48 float *pp, *ppi=0, *ppo=0, *ppe=0;
49 float cbvectors[CB_MEML];
50 float tene, cene, cvec[SUBL];
53 memset(cvec,0,SUBL*sizeof(float));
55 /* Determine size of codebook sections */
57 base_size=lMem-lTarget+1;
60 base_size=lMem-lTarget+1+lTarget/2;
63 /* setup buffer for weighting */
65 memcpy(buf,weightState,sizeof(float)*LPC_FILTERORDER);
66 memcpy(buf+LPC_FILTERORDER,mem,lMem*sizeof(float));
67 memcpy(buf+LPC_FILTERORDER+lMem,intarget,lTarget*sizeof(float));
71 AllPoleFilter(buf+LPC_FILTERORDER, weightDenum,
72 lMem+lTarget, LPC_FILTERORDER);
74 /* Construct the codebook and target needed */
76 memcpy(target, buf+LPC_FILTERORDER+lMem, lTarget*sizeof(float));
79 for (i=0;i<lTarget;i++) {
80 tene+=target[i]*target[i];
83 /* Prepare search over one more codebook section. This section
84 is created by filtering the original buffer with a filter. */
86 filteredCBvecs(cbvectors, buf+LPC_FILTERORDER, lMem);
88 /* The Main Loop over stages */
90 for (stage=0;stage<nStages; stage++) {
92 range = search_rangeTbl[block][stage];
94 /* initialize search measure */
96 max_measure = (float)-10000000.0;
100 /* Compute cross dot product between the target
104 pp=buf+LPC_FILTERORDER+lMem-lTarget;
105 for (j=0; j<lTarget; j++) {
106 crossDot += target[j]*(*pp++);
111 /* Calculate energy in the first block of
112 'lTarget' sampels. */
114 ppi = buf+LPC_FILTERORDER+lMem-lTarget-1;
115 ppo = buf+LPC_FILTERORDER+lMem-1;
118 pp=buf+LPC_FILTERORDER+lMem-lTarget;
119 for (j=0; j<lTarget; j++) {
120 // XXXXXX is this the coder's intent?
121 //*ppe+=(*pp)*(*pp++);
122 *ppe+=(pp[0])*(pp[1]);
126 invenergy[0] = (float) 1.0 / (*ppe + EPS);
128 invenergy[0] = (float) 0.0;
132 measure=(float)-10000000.0;
134 if (crossDot > 0.0) {
135 measure = crossDot*crossDot*invenergy[0];
139 measure = crossDot*crossDot*invenergy[0];
142 /* check if measure is better */
143 ftmp = crossDot*invenergy[0];
145 if ((measure>max_measure) && (fabs(ftmp)<CB_MAXGAIN)) {
147 max_measure = measure;
151 /* loop over lags 40+ in the first codebook section,
154 for (icount=1; icount<range; icount++) {
156 /* calculate measure */
159 pp = buf+LPC_FILTERORDER+lMem-lTarget-icount;
161 for (j=0;j<lTarget;j++) {
162 crossDot += target[j]*(*pp++);
166 *ppe++ = energy[icount-1] + (*ppi)*(*ppi) -
171 if(energy[icount]>0.0) {
173 (float)1.0/(energy[icount]+EPS);
175 invenergy[icount] = (float) 0.0;
178 measure=(float)-10000000.0;
180 if (crossDot > 0.0) {
181 measure = crossDot*crossDot*invenergy[icount];
185 measure = crossDot*crossDot*invenergy[icount];
188 /* check if measure is better */
189 ftmp = crossDot*invenergy[icount];
192 if ((measure>max_measure) && (fabs(ftmp)<CB_MAXGAIN)){
194 max_measure = measure;
199 /* Loop over lags 20-39 in the first codebook section,
201 * The vectors are interpolated.
206 /* Search for best possible lag and compute
207 the CB-vectors' energy. */
209 searchAugmentedCB(20, 39, stage, base_size-lTarget/2,
210 target, buf+LPC_FILTERORDER+lMem,
211 &max_measure, &best_index, &gain, energy, invenergy);
215 /* set search range for following codebook sections */
217 base_index=best_index;
219 /* unrestricted search */
221 if (CB_RESRANGE == -1) {
228 /* restriced search around best index from first
232 /* Initialize search indices */
235 sInd=base_index-CB_RESRANGE/2;
236 eInd=sInd+CB_RESRANGE;
246 } else if( base_index < (base_size-20) ) {
249 sInd -= (eInd-range);
252 } else { /* base_index >= (base_size-20) */
254 if(sInd < (base_size-20)) {
258 eIndAug = 19 + CB_RESRANGE;
265 sIndAug = 20 + sInd - (base_size-20);
268 eInd = CB_RESRANGE - (eIndAug-sIndAug+1);
272 } else { /* lTarget = 22 */
280 sInd -= (eInd - range);
286 /* search of higher codebook section */
288 /* index search range */
295 ppe = energy+base_size;
298 pp=cbvectors+lMem-lTarget;
299 for (j=0; j<lTarget; j++) {
300 // XXXXXX is this the coder's intent?
301 //*ppe+=(*pp)*(*pp++);
302 *ppe+=(pp[0])*(pp[1]);
305 ppi = cbvectors + lMem - 1 - lTarget;
306 ppo = cbvectors + lMem - 1;
308 for(j=0;j<(range-1);j++) {
309 *(ppe+1) = *ppe + (*ppi)*(*ppi) - (*ppo)*(*ppo);
316 /* loop over search range */
318 for (icount=sInd; icount<eInd; icount++) {
320 /* calculate measure */
323 pp=cbvectors + lMem - (counter++) - lTarget;
325 for (j=0;j<lTarget;j++) {
326 crossDot += target[j]*(*pp++);
329 if(energy[icount]>0.0) {
330 invenergy[icount] = (float) 1.0/(energy[icount]+EPS);
332 invenergy[icount] = (float) 0.0;
337 measure=(float)-10000000.0;
339 if (crossDot > 0.0) {
340 measure = crossDot*crossDot*
345 measure = crossDot*crossDot*invenergy[icount];
348 /* check if measure is better */
349 ftmp = crossDot*invenergy[icount];
351 if ((measure>max_measure) && (fabs(ftmp)<CB_MAXGAIN)){
353 max_measure = measure;
358 /* Search the augmented CB inside the limited range. */
360 if ((lTarget==SUBL)&&(sIndAug!=0)) {
362 searchAugmentedCB(sIndAug, eIndAug, stage,
363 2*base_size-20, target, cbvectors+lMem,
364 &max_measure, &best_index, &gain, energy, invenergy);
368 /* record best index */
370 index[stage] = best_index;
372 /* gain quantization */
380 if (gain>CB_MAXGAIN) {
381 gain = (float)CB_MAXGAIN;
383 gain = gainquant(gain, 1.0, 32, &gain_index[stage]);
387 gain = gainquant(gain, (float)fabs(gains[stage-1]),
388 16, &gain_index[stage]);
390 gain = gainquant(gain, (float)fabs(gains[stage-1]),
391 8, &gain_index[stage]);
395 /* Extract the best (according to measure) codebook vector */
397 if(lTarget==(STATE_LEN-STATE_SHORT_LEN)) {
399 if(index[stage]<base_size) {
400 pp=buf+LPC_FILTERORDER+lMem-lTarget-index[stage];
402 pp=cbvectors+lMem-lTarget-
403 index[stage]+base_size;
407 if (index[stage]<base_size) {
408 if (index[stage]<(base_size-20)) {
409 pp=buf+LPC_FILTERORDER+lMem-lTarget-index[stage];
411 createAugmentedVec(index[stage]-base_size+40,
412 buf+LPC_FILTERORDER+lMem,aug_vec);
416 int filterno, lag_val;
418 filterno=index[stage]/base_size;
419 lag_val=index[stage]-filterno*base_size;
422 if (lag_val<(base_size-20)) {
423 pp=cbvectors+filterno*lMem-lTarget-
424 index[stage]+filterno*base_size;
427 index[stage]-(filterno+1)*base_size+40,
428 cbvectors+filterno*lMem,aug_vec);
434 /* Subtract the best codebook vector, according
435 to measure, from the target vector */
437 for(j=0;j<lTarget;j++){
438 cvec[j] += gain*(*pp);
439 target[j] -= gain*(*pp++);
442 /* record quantized gain */
446 }/* end of Main Loop. for (stage=0;... */
448 /* Gain adjustment for energy matching */
450 for (i=0;i<lTarget;i++) {
451 cene+=cvec[i]*cvec[i];
455 for (i=gain_index[0];i<32;i++) {
456 ftmp=cene*gain_sq5Tbl[i]*gain_sq5Tbl[i];
458 if ((ftmp<(tene*gains[0]*gains[0])) &&
459 (gain_sq5Tbl[j]<(2.0*gains[0]))) {