Utilise new MergeSym feature to no longer overwrite the source .DEF file when buildin...
[openh323.git] / src / iLBC / iCBSearch.c
blob2a6f0f3f17328d43b68f5e4f543b56656759061c
2 /******************************************************************
4 iLBC Speech Coder ANSI-C Source Code
6 iCBSearch.c
8 Copyright (c) 2001,
9 Global IP Sound AB.
10 All rights reserved.
12 ******************************************************************/
14 #include <math.h>
15 #include <string.h>
17 #include "iLBC_define.h"
18 #include "gainquant.h"
19 #include "createCB.h"
20 #include "filter.h"
24 #include "constants.h"
26 /*----------------------------------------------------------------*
27 * Search routine for codebook encoding and gain quantization.
28 *---------------------------------------------------------------*/
30 void iCBSearch(
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 */
43 ){
44 int i, j, icount, stage, best_index, range, counter;
45 float max_measure, gain, measure, crossDot, ftmp;
46 float gains[CB_NSTAGES];
47 float target[SUBL];
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];
55 float aug_vec[SUBL];
57 memset(cvec,0,SUBL*sizeof(float));
59 /* Determine size of codebook sections */
61 base_size=lMem-lTarget+1;
63 if (lTarget==SUBL) {
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));
73 /* weighting */
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));
85 tene=0.0;
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;
104 gain = (float)0.0;
105 best_index = 0;
107 /* Compute cross dot product between the target
108 and the CB memory */
110 crossDot=0.0;
111 pp=buf+LPC_FILTERORDER+lMem-lTarget;
112 for (j=0; j<lTarget; j++) {
113 crossDot += target[j]*(*pp++);
116 if (stage==0) {
118 /* Calculate energy in the first block of
119 'lTarget' sampels. */
120 ppe = energy;
121 ppi = buf+LPC_FILTERORDER+lMem-lTarget-1;
122 ppo = buf+LPC_FILTERORDER+lMem-1;
124 *ppe=0.0;
125 pp=buf+LPC_FILTERORDER+lMem-lTarget;
126 for (j=0; j<lTarget; j++) {
127 *ppe+=(*pp)*(*pp++);
130 if (*ppe>0.0) {
131 invenergy[0] = (float) 1.0 / (*ppe + EPS);
132 } else {
136 invenergy[0] = (float) 0.0;
138 ppe++;
140 measure=(float)-10000000.0;
142 if (crossDot > 0.0) {
143 measure = crossDot*crossDot*invenergy[0];
146 else {
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)) {
154 best_index = 0;
155 max_measure = measure;
156 gain = ftmp;
159 /* loop over lags 40+ in the first codebook section,
160 full search */
162 for (icount=1; icount<range; icount++) {
164 /* calculate measure */
166 crossDot=0.0;
167 pp = buf+LPC_FILTERORDER+lMem-lTarget-icount;
169 for (j=0; j<lTarget; j++) {
170 crossDot += target[j]*(*pp++);
173 if (stage==0) {
174 *ppe++ = energy[icount-1] + (*ppi)*(*ppi) -
175 (*ppo)*(*ppo);
176 ppo--;
177 ppi--;
179 if (energy[icount]>0.0) {
180 invenergy[icount] =
181 (float)1.0/(energy[icount]+EPS);
182 } else {
183 invenergy[icount] = (float) 0.0;
186 measure=(float)-10000000.0;
188 if (crossDot > 0.0) {
192 measure = crossDot*crossDot*invenergy[icount];
195 else {
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)){
204 best_index = icount;
205 max_measure = measure;
206 gain = ftmp;
210 /* Loop over lags 20-39 in the first codebook section,
211 * full search.
212 * The vectors are interpolated.
215 if (lTarget==SUBL) {
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) {
233 sInd=0;
234 eInd=range-1;
235 sIndAug=20;
236 eIndAug=39;
239 /* restriced search around best index from first
240 codebook section */
242 else {
243 /* Initialize search indices */
244 sIndAug=0;
248 eIndAug=0;
249 sInd=base_index-CB_RESRANGE/2;
250 eInd=sInd+CB_RESRANGE;
252 if (lTarget==SUBL) {
254 if (sInd<0) {
256 sIndAug = 40 + sInd;
257 eIndAug = 39;
258 sInd=0;
260 } else if ( base_index < (base_size-20) ) {
262 if (eInd > range) {
263 sInd -= (eInd-range);
264 eInd = range;
266 } else { /* base_index >= (base_size-20) */
268 if (sInd < (base_size-20)) {
269 sIndAug = 20;
270 sInd = 0;
271 eInd = 0;
272 eIndAug = 19 + CB_RESRANGE;
274 if(eIndAug > 39) {
275 eInd = eIndAug-39;
276 eIndAug = 39;
278 } else {
279 sIndAug = 20 + sInd - (base_size-20);
280 eIndAug = 39;
281 sInd = 0;
282 eInd = CB_RESRANGE - (eIndAug-sIndAug+1);
286 } else { /* lTarget = 22 or 23 */
288 if (sInd < 0) {
289 eInd -= sInd;
290 sInd = 0;
293 if(eInd > range) {
294 sInd -= (eInd - range);
295 eInd = range;
300 /* search of higher codebook section */
305 /* index search range */
306 counter = sInd;
307 sInd += base_size;
308 eInd += base_size;
311 if (stage==0) {
312 ppe = energy+base_size;
313 *ppe=0.0;
315 pp=cbvectors+lMem-lTarget;
316 for (j=0; j<lTarget; j++) {
317 *ppe+=(*pp)*(*pp++);
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);
325 ppo--;
326 ppi--;
327 ppe++;
331 /* loop over search range */
333 for (icount=sInd; icount<eInd; icount++) {
335 /* calculate measure */
337 crossDot=0.0;
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);
346 } else {
347 invenergy[icount] = (float) 0.0;
350 if (stage==0) {
352 measure=(float)-10000000.0;
354 if (crossDot > 0.0) {
355 measure = crossDot*crossDot*
356 invenergy[icount];
362 else {
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)){
370 best_index = icount;
371 max_measure = measure;
372 gain = ftmp;
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 */
392 if (stage==0){
394 if (gain<0.0){
395 gain = 0.0;
398 if (gain>CB_MAXGAIN) {
399 gain = (float)CB_MAXGAIN;
401 gain = gainquant(gain, 1.0, 32, &gain_index[stage]);
403 else {
404 if (stage==1) {
405 gain = gainquant(gain, (float)fabs(gains[stage-1]),
406 16, &gain_index[stage]);
407 } else {
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];
422 } else {
423 pp=cbvectors+lMem-lTarget-
424 index[stage]+base_size;
426 } else {
428 if (index[stage]<base_size) {
429 if (index[stage]<(base_size-20)) {
430 pp=buf+LPC_FILTERORDER+lMem-lTarget-index[stage];
431 } else {
432 createAugmentedVec(index[stage]-base_size+40,
433 buf+LPC_FILTERORDER+lMem,aug_vec);
434 pp=aug_vec;
436 } else {
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;
446 } else {
447 createAugmentedVec(
448 index[stage]-(filterno+1)*base_size+40,
449 cbvectors+filterno*lMem,aug_vec);
450 pp=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 */
465 gains[stage]=gain;
467 }/* end of Main Loop. for (stage=0;... */
472 /* Gain adjustment for energy matching */
473 cene=0.0;
474 for (i=0; i<lTarget; i++) {
475 cene+=cvec[i]*cvec[i];
477 j=gain_index[0];
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]))) {
484 j=i;
487 gain_index[0]=j;