Asterisk - The Open Source Telephony Project GIT-master-f36a736
iCBSearch.c
Go to the documentation of this file.
1
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
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;
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
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++, pp++) {
130 *ppe+=(*pp)*(*pp);
131 }
132
133 if (*ppe>0.0) {
134 invenergy[0] = (float) 1.0 / (*ppe + EPS);
135 } else {
136 invenergy[0] = (float) 0.0;
137
138
139
140
141
142 }
143 ppe++;
144
145 measure=(float)-10000000.0;
146
147 if (crossDot > 0.0) {
148 measure = crossDot*crossDot*invenergy[0];
149 }
150 }
151 else {
152 measure = crossDot*crossDot*invenergy[0];
153 }
154
155 /* check if measure is better */
156 ftmp = crossDot*invenergy[0];
157
158 if ((measure>max_measure) && (fabs(ftmp)<CB_MAXGAIN)) {
159 best_index = 0;
160 max_measure = measure;
161 gain = ftmp;
162 }
163
164 /* loop over the main first codebook section,
165 full search */
166
167 for (icount=1; icount<range; icount++) {
168
169 /* calculate measure */
170
171 crossDot=0.0;
172 pp = buf+LPC_FILTERORDER+lMem-lTarget-icount;
173
174 for (j=0; j<lTarget; j++) {
175 crossDot += target[j]*(*pp++);
176 }
177
178 if (stage==0) {
179 *ppe++ = energy[icount-1] + (*ppi)*(*ppi) -
180 (*ppo)*(*ppo);
181 ppo--;
182 ppi--;
183
184 if (energy[icount]>0.0) {
185 invenergy[icount] =
186 (float)1.0/(energy[icount]+EPS);
187 } else {
188 invenergy[icount] = (float) 0.0;
189 }
190
191
192
193
194
195 measure=(float)-10000000.0;
196
197 if (crossDot > 0.0) {
198 measure = crossDot*crossDot*invenergy[icount];
199 }
200 }
201 else {
202 measure = crossDot*crossDot*invenergy[icount];
203 }
204
205 /* check if measure is better */
206 ftmp = crossDot*invenergy[icount];
207
208 if ((measure>max_measure) && (fabs(ftmp)<CB_MAXGAIN)) {
209 best_index = icount;
210 max_measure = measure;
211 gain = ftmp;
212 }
213 }
214
215 /* Loop over augmented part in the first codebook
216 * section, full search.
217 * The vectors are interpolated.
218 */
219
220 if (lTarget==SUBL) {
221
222 /* Search for best possible cb vector and
223 compute the CB-vectors' energy. */
224 searchAugmentedCB(20, 39, stage, base_size-lTarget/2,
225 target, buf+LPC_FILTERORDER+lMem,
226 &max_measure, &best_index, &gain, energy,
227 invenergy);
228 }
229
230 /* set search range for following codebook sections */
231
232 base_index=best_index;
233
234 /* unrestricted search */
235
236 if (CB_RESRANGE == -1) {
237 sInd=0;
238 eInd=range-1;
239 sIndAug=20;
240 eIndAug=39;
241 }
242
243
244
245
246
247
248 /* restricted search around best index from first
249 codebook section */
250
251 else {
252 /* Initialize search indices */
253 sIndAug=0;
254 eIndAug=0;
255 sInd=base_index-CB_RESRANGE/2;
256 eInd=sInd+CB_RESRANGE;
257
258 if (lTarget==SUBL) {
259
260 if (sInd<0) {
261
262 sIndAug = 40 + sInd;
263 eIndAug = 39;
264 sInd=0;
265
266 } else if ( base_index < (base_size-20) ) {
267
268 if (eInd > range) {
269 sInd -= (eInd-range);
270 eInd = range;
271 }
272 } else { /* base_index >= (base_size-20) */
273
274 if (sInd < (base_size-20)) {
275 sIndAug = 20;
276 sInd = 0;
277 eInd = 0;
278 eIndAug = 19 + CB_RESRANGE;
279
280 if(eIndAug > 39) {
281 eInd = eIndAug-39;
282 eIndAug = 39;
283 }
284 } else {
285 sIndAug = 20 + sInd - (base_size-20);
286 eIndAug = 39;
287 sInd = 0;
288 eInd = CB_RESRANGE - (eIndAug-sIndAug+1);
289 }
290 }
291
292 } else { /* lTarget = 22 or 23 */
293
294 if (sInd < 0) {
295 eInd -= sInd;
296
297
298
299
300
301 sInd = 0;
302 }
303
304 if(eInd > range) {
305 sInd -= (eInd - range);
306 eInd = range;
307 }
308 }
309 }
310
311 /* search of higher codebook section */
312
313 /* index search range */
314 counter = sInd;
315 sInd += base_size;
316 eInd += base_size;
317
318
319 if (stage==0) {
320 ppe = energy+base_size;
321 *ppe=0.0;
322
323 pp=cbvectors+lMem-lTarget;
324 for (j=0; j<lTarget; j++, pp++) {
325 *ppe+=(*pp)*(*pp);
326 }
327
328 ppi = cbvectors + lMem - 1 - lTarget;
329 ppo = cbvectors + lMem - 1;
330
331 for (j=0; j<(range-1); j++) {
332 *(ppe+1) = *ppe + (*ppi)*(*ppi) - (*ppo)*(*ppo);
333 ppo--;
334 ppi--;
335 ppe++;
336 }
337 }
338
339 /* loop over search range */
340
341 for (icount=sInd; icount<eInd; icount++) {
342
343 /* calculate measure */
344
345 crossDot=0.0;
346 pp=cbvectors + lMem - (counter++) - lTarget;
347
348 for (j=0;j<lTarget;j++) {
349
350
351
352
353
354 crossDot += target[j]*(*pp++);
355 }
356
357 if (energy[icount]>0.0) {
358 invenergy[icount] =(float)1.0/(energy[icount]+EPS);
359 } else {
360 invenergy[icount] =(float)0.0;
361 }
362
363 if (stage==0) {
364
365 measure=(float)-10000000.0;
366
367 if (crossDot > 0.0) {
368 measure = crossDot*crossDot*
369 invenergy[icount];
370 }
371 }
372 else {
373 measure = crossDot*crossDot*invenergy[icount];
374 }
375
376 /* check if measure is better */
377 ftmp = crossDot*invenergy[icount];
378
379 if ((measure>max_measure) && (fabs(ftmp)<CB_MAXGAIN)) {
380 best_index = icount;
381 max_measure = measure;
382 gain = ftmp;
383 }
384 }
385
386 /* Search the augmented CB inside the limited range. */
387
388 if ((lTarget==SUBL)&&(sIndAug!=0)) {
389 searchAugmentedCB(sIndAug, eIndAug, stage,
390 2*base_size-20, target, cbvectors+lMem,
391 &max_measure, &best_index, &gain, energy,
392 invenergy);
393 }
394
395 /* record best index */
396
397 index[stage] = best_index;
398
399 /* gain quantization */
400
401 if (stage==0){
402
403
404
405
406
407
408 if (gain<0.0){
409 gain = 0.0;
410 }
411
412 if (gain>CB_MAXGAIN) {
413 gain = (float)CB_MAXGAIN;
414 }
415 gain = gainquant(gain, 1.0, 32, &gain_index[stage]);
416 }
417 else {
418 if (stage==1) {
419 gain = gainquant(gain, (float)fabs(gains[stage-1]),
420 16, &gain_index[stage]);
421 } else {
422 gain = gainquant(gain, (float)fabs(gains[stage-1]),
423 8, &gain_index[stage]);
424 }
425 }
426
427 /* Extract the best (according to measure)
428 codebook vector */
429
430 if (lTarget==(STATE_LEN-iLBCenc_inst->state_short_len)) {
431
432 if (index[stage]<base_size) {
433 pp=buf+LPC_FILTERORDER+lMem-lTarget-index[stage];
434 } else {
435 pp=cbvectors+lMem-lTarget-
436 index[stage]+base_size;
437 }
438 } else {
439
440 if (index[stage]<base_size) {
441 if (index[stage]<(base_size-20)) {
442 pp=buf+LPC_FILTERORDER+lMem-
443 lTarget-index[stage];
444 } else {
445 createAugmentedVec(index[stage]-base_size+40,
446 buf+LPC_FILTERORDER+lMem,aug_vec);
447 pp=aug_vec;
448 }
449 } else {
450 int filterno, position;
451
452 filterno=index[stage]/base_size;
453 position=index[stage]-filterno*base_size;
454
455
456
457
458
459
460
461 if (position<(base_size-20)) {
462 pp=cbvectors+filterno*lMem-lTarget-
463 index[stage]+filterno*base_size;
464 } else {
466 index[stage]-(filterno+1)*base_size+40,
467 cbvectors+filterno*lMem,aug_vec);
468 pp=aug_vec;
469 }
470 }
471 }
472
473 /* Subtract the best codebook vector, according
474 to measure, from the target vector */
475
476 for (j=0;j<lTarget;j++) {
477 cvec[j] += gain*(*pp);
478 target[j] -= gain*(*pp++);
479 }
480
481 /* record quantized gain */
482
483 gains[stage]=gain;
484
485 }/* end of Main Loop. for (stage=0;... */
486
487 /* Gain adjustment for energy matching */
488 cene=0.0;
489 for (i=0; i<lTarget; i++) {
490 cene+=cvec[i]*cvec[i];
491 }
492 j=gain_index[0];
493
494 for (i=gain_index[0]; i<32; i++) {
495 ftmp=cene*gain_sq5Tbl[i]*gain_sq5Tbl[i];
496
497 if ((ftmp<(tene*gains[0]*gains[0])) &&
498 (gain_sq5Tbl[j]<(2.0*gains[0]))) {
499 j=i;
500 }
501 }
502 gain_index[0]=j;
503 }
float gain_sq5Tbl[32]
Definition: constants.c:168
int search_rangeTbl[5][CB_NSTAGES]
Definition: constants.c:135
void createAugmentedVec(int index, float *buffer, float *cbVec)
Definition: createCB.c:190
void searchAugmentedCB(int low, int high, int stage, int startIndex, float *target, float *buffer, float *max_measure, int *best_index, float *gain, float *energy, float *invenergy)
Definition: createCB.c:71
void filteredCBvecs(float *cbvectors, float *mem, int lMem)
Definition: createCB.c:29
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
void AllPoleFilter(float *InOut, float *Coef, int lengthInOut, int orderCoef)
Definition: filter.c:19
float gainquant(float in, float maxIn, int cblen, int *index)
Definition: gainquant.c:27
void iCBSearch(iLBC_Enc_Inst_t *iLBCenc_inst, int *index, int *gain_index, float *intarget, float *mem, int lMem, int lTarget, int nStages, float *weightDenum, float *weightState, int block)
Definition: iCBSearch.c:26
#define CB_EXPAND
Definition: iLBC_define.h:57
#define STATE_LEN
Definition: iLBC_define.h:34
#define CB_NSTAGES
Definition: iLBC_define.h:56
#define CB_MAXGAIN
Definition: iLBC_define.h:62
#define CB_MEML
Definition: iLBC_define.h:58
#define SUBL
Definition: iLBC_define.h:33
#define EPS
Definition: iLBC_define.h:106
#define LPC_FILTERORDER
Definition: iLBC_define.h:40
#define CB_RESRANGE
Definition: iLBC_define.h:61