2 /******************************************************************
4 iLBC Speech Coder ANSI-C Source Code
12 ******************************************************************/
17 #include "iLBC_define.h"
18 #include "gainquant.h"
24 #include "constants.h"
26 /*----------------------------------------------------------------*
27 * Search routine for codebook encoding and gain quantization.
28 *---------------------------------------------------------------*/
31 iLBC_Enc_Inst_t
*iLBCenc_inst
,
32 /* (i) the encoder state structure */
33 int *index
, /* (o) Codebook indices */
34 int *gain_index
,/* (o) Gain quantization indices */
35 float *intarget
,/* (i) Target vector for encoding */
36 float *mem
, /* (i) Buffer for codebook construction */
37 int lMem
, /* (i) Length of buffer */
38 int lTarget
, /* (i) Length of vector */
39 int nStages
, /* (i) Number of codebook stages */
40 float *weightDenum
, /* (i) weighting filter coefficients */
41 float *weightState
, /* (i) weighting filter state */
42 int block
/* (i) the subblock number */
44 int i
, j
, icount
, stage
, best_index
, range
, counter
;
45 float max_measure
, gain
, measure
, crossDot
, ftmp
;
46 float gains
[CB_NSTAGES
];
48 int base_index
, sInd
, eInd
, base_size
;
49 int sIndAug
=0, eIndAug
=0;
50 float buf
[CB_MEML
+SUBL
+2*LPC_FILTERORDER
];
51 float invenergy
[CB_EXPAND
*128], energy
[CB_EXPAND
*128];
52 float *pp
, *ppi
=0, *ppo
=0, *ppe
=0;
53 float cbvectors
[CB_MEML
];
54 float tene
, cene
, cvec
[SUBL
];
57 memset(cvec
,0,SUBL
*sizeof(float));
59 /* Determine size of codebook sections */
61 base_size
=lMem
-lTarget
+1;
64 base_size
=lMem
-lTarget
+1+lTarget
/2;
67 /* setup buffer for weighting */
69 memcpy(buf
,weightState
,sizeof(float)*LPC_FILTERORDER
);
70 memcpy(buf
+LPC_FILTERORDER
,mem
,lMem
*sizeof(float));
71 memcpy(buf
+LPC_FILTERORDER
+lMem
,intarget
,lTarget
*sizeof(float));
75 AllPoleFilter(buf
+LPC_FILTERORDER
, weightDenum
,
76 lMem
+lTarget
, LPC_FILTERORDER
);
81 /* Construct the codebook and target needed */
83 memcpy(target
, buf
+LPC_FILTERORDER
+lMem
, lTarget
*sizeof(float));
86 for (i
=0; i
<lTarget
; i
++) {
87 tene
+=target
[i
]*target
[i
];
90 /* Prepare search over one more codebook section. This section
91 is created by filtering the original buffer with a filter. */
93 filteredCBvecs(cbvectors
, buf
+LPC_FILTERORDER
, lMem
);
95 /* The Main Loop over stages */
97 for (stage
=0; stage
<nStages
; stage
++) {
99 range
= search_rangeTbl
[block
][stage
];
101 /* initialize search measure */
103 max_measure
= (float)-10000000.0;
107 /* Compute cross dot product between the target
111 pp
=buf
+LPC_FILTERORDER
+lMem
-lTarget
;
112 for (j
=0; j
<lTarget
; j
++) {
113 crossDot
+= target
[j
]*(*pp
++);
118 /* Calculate energy in the first block of
119 'lTarget' sampels. */
121 ppi
= buf
+LPC_FILTERORDER
+lMem
-lTarget
-1;
122 ppo
= buf
+LPC_FILTERORDER
+lMem
-1;
125 pp
=buf
+LPC_FILTERORDER
+lMem
-lTarget
;
126 for (j
=0; j
<lTarget
; j
++) {
131 invenergy
[0] = (float) 1.0 / (*ppe
+ EPS
);
136 invenergy
[0] = (float) 0.0;
140 measure
=(float)-10000000.0;
142 if (crossDot
> 0.0) {
143 measure
= crossDot
*crossDot
*invenergy
[0];
147 measure
= crossDot
*crossDot
*invenergy
[0];
150 /* check if measure is better */
151 ftmp
= crossDot
*invenergy
[0];
153 if ((measure
>max_measure
) && (fabs(ftmp
)<CB_MAXGAIN
)) {
155 max_measure
= measure
;
159 /* loop over lags 40+ in the first codebook section,
162 for (icount
=1; icount
<range
; icount
++) {
164 /* calculate measure */
167 pp
= buf
+LPC_FILTERORDER
+lMem
-lTarget
-icount
;
169 for (j
=0; j
<lTarget
; j
++) {
170 crossDot
+= target
[j
]*(*pp
++);
174 *ppe
++ = energy
[icount
-1] + (*ppi
)*(*ppi
) -
179 if (energy
[icount
]>0.0) {
181 (float)1.0/(energy
[icount
]+EPS
);
183 invenergy
[icount
] = (float) 0.0;
186 measure
=(float)-10000000.0;
188 if (crossDot
> 0.0) {
192 measure
= crossDot
*crossDot
*invenergy
[icount
];
196 measure
= crossDot
*crossDot
*invenergy
[icount
];
199 /* check if measure is better */
200 ftmp
= crossDot
*invenergy
[icount
];
203 if ((measure
>max_measure
) && (fabs(ftmp
)<CB_MAXGAIN
)){
205 max_measure
= measure
;
210 /* Loop over lags 20-39 in the first codebook section,
212 * The vectors are interpolated.
217 /* Search for best possible lag and compute
218 the CB-vectors' energy. */
220 searchAugmentedCB(20, 39, stage
, base_size
-lTarget
/2,
221 target
, buf
+LPC_FILTERORDER
+lMem
,
222 &max_measure
, &best_index
, &gain
, energy
, invenergy
);
226 /* set search range for following codebook sections */
228 base_index
=best_index
;
230 /* unrestricted search */
232 if (CB_RESRANGE
== -1) {
239 /* restriced search around best index from first
243 /* Initialize search indices */
249 sInd
=base_index
-CB_RESRANGE
/2;
250 eInd
=sInd
+CB_RESRANGE
;
260 } else if ( base_index
< (base_size
-20) ) {
263 sInd
-= (eInd
-range
);
266 } else { /* base_index >= (base_size-20) */
268 if (sInd
< (base_size
-20)) {
272 eIndAug
= 19 + CB_RESRANGE
;
279 sIndAug
= 20 + sInd
- (base_size
-20);
282 eInd
= CB_RESRANGE
- (eIndAug
-sIndAug
+1);
286 } else { /* lTarget = 22 or 23 */
294 sInd
-= (eInd
- range
);
300 /* search of higher codebook section */
305 /* index search range */
312 ppe
= energy
+base_size
;
315 pp
=cbvectors
+lMem
-lTarget
;
316 for (j
=0; j
<lTarget
; j
++) {
320 ppi
= cbvectors
+ lMem
- 1 - lTarget
;
321 ppo
= cbvectors
+ lMem
- 1;
323 for (j
=0; j
<(range
-1); j
++) {
324 *(ppe
+1) = *ppe
+ (*ppi
)*(*ppi
) - (*ppo
)*(*ppo
);
331 /* loop over search range */
333 for (icount
=sInd
; icount
<eInd
; icount
++) {
335 /* calculate measure */
338 pp
=cbvectors
+ lMem
- (counter
++) - lTarget
;
340 for (j
=0;j
<lTarget
;j
++) {
341 crossDot
+= target
[j
]*(*pp
++);
344 if (energy
[icount
]>0.0) {
345 invenergy
[icount
] = (float) 1.0/(energy
[icount
]+EPS
);
347 invenergy
[icount
] = (float) 0.0;
352 measure
=(float)-10000000.0;
354 if (crossDot
> 0.0) {
355 measure
= crossDot
*crossDot
*
363 measure
= crossDot
*crossDot
*invenergy
[icount
];
366 /* check if measure is better */
367 ftmp
= crossDot
*invenergy
[icount
];
369 if ((measure
>max_measure
) && (fabs(ftmp
)<CB_MAXGAIN
)){
371 max_measure
= measure
;
376 /* Search the augmented CB inside the limited range. */
378 if ((lTarget
==SUBL
)&&(sIndAug
!=0)) {
380 searchAugmentedCB(sIndAug
, eIndAug
, stage
,
381 2*base_size
-20, target
, cbvectors
+lMem
,
382 &max_measure
, &best_index
, &gain
, energy
, invenergy
);
386 /* record best index */
388 index
[stage
] = best_index
;
390 /* gain quantization */
398 if (gain
>CB_MAXGAIN
) {
399 gain
= (float)CB_MAXGAIN
;
401 gain
= gainquant(gain
, 1.0, 32, &gain_index
[stage
]);
405 gain
= gainquant(gain
, (float)fabs(gains
[stage
-1]),
406 16, &gain_index
[stage
]);
408 gain
= gainquant(gain
, (float)fabs(gains
[stage
-1]),
409 8, &gain_index
[stage
]);
416 /* Extract the best (according to measure) codebook vector */
418 if (lTarget
==(STATE_LEN
-iLBCenc_inst
->state_short_len
)) {
420 if (index
[stage
]<base_size
) {
421 pp
=buf
+LPC_FILTERORDER
+lMem
-lTarget
-index
[stage
];
423 pp
=cbvectors
+lMem
-lTarget
-
424 index
[stage
]+base_size
;
428 if (index
[stage
]<base_size
) {
429 if (index
[stage
]<(base_size
-20)) {
430 pp
=buf
+LPC_FILTERORDER
+lMem
-lTarget
-index
[stage
];
432 createAugmentedVec(index
[stage
]-base_size
+40,
433 buf
+LPC_FILTERORDER
+lMem
,aug_vec
);
437 int filterno
, lag_val
;
439 filterno
=index
[stage
]/base_size
;
440 lag_val
=index
[stage
]-filterno
*base_size
;
443 if (lag_val
<(base_size
-20)) {
444 pp
=cbvectors
+filterno
*lMem
-lTarget
-
445 index
[stage
]+filterno
*base_size
;
448 index
[stage
]-(filterno
+1)*base_size
+40,
449 cbvectors
+filterno
*lMem
,aug_vec
);
455 /* Subtract the best codebook vector, according
456 to measure, from the target vector */
458 for (j
=0;j
<lTarget
;j
++) {
459 cvec
[j
] += gain
*(*pp
);
460 target
[j
] -= gain
*(*pp
++);
463 /* record quantized gain */
467 }/* end of Main Loop. for (stage=0;... */
472 /* Gain adjustment for energy matching */
474 for (i
=0; i
<lTarget
; i
++) {
475 cene
+=cvec
[i
]*cvec
[i
];
479 for (i
=gain_index
[0]; i
<32; i
++) {
480 ftmp
=cene
*gain_sq5Tbl
[i
]*gain_sq5Tbl
[i
];
482 if ((ftmp
<(tene
*gains
[0]*gains
[0])) &&
483 (gain_sq5Tbl
[j
]<(2.0*gains
[0]))) {