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