Mercurial > hg > audiostuff
comparison intercom/ilbc/iCBSearch.c @ 2:13be24d74cd2
import intercom-0.4.1
author | Peter Meerwald <pmeerw@cosy.sbg.ac.at> |
---|---|
date | Fri, 25 Jun 2010 09:57:52 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
1:9cadc470e3da | 2:13be24d74cd2 |
---|---|
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 } |