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