Coverage Report

Created: 2026-03-12 06:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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