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