~ubuntu-branches/ubuntu/wily/sflphone/wily

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject-2.1.0/third_party/ilbc/enhancer.c

  • Committer: Package Import Robot
  • Author(s): Mark Purcell
  • Date: 2014-01-28 18:23:36 UTC
  • mfrom: (1.1.11)
  • mto: This revision was merged to the branch mainline in revision 24.
  • Revision ID: package-import@ubuntu.com-20140128182336-3xenud1kbnwmf3mz
* New upstream release 
  - Fixes "New Upstream Release" (Closes: #735846)
  - Fixes "Ringtone does not stop" (Closes: #727164)
  - Fixes "[sflphone-kde] crash on startup" (Closes: #718178)
  - Fixes "sflphone GUI crashes when call is hung up" (Closes: #736583)
* Build-Depends: ensure GnuTLS 2.6
  - libucommon-dev (>= 6.0.7-1.1), libccrtp-dev (>= 2.0.6-3)
  - Fixes "FTBFS Build-Depends libgnutls{26,28}-dev" (Closes: #722040)
* Fix "boost 1.49 is going away" unversioned Build-Depends: (Closes: #736746)
* Add Build-Depends: libsndfile-dev, nepomuk-core-dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
   /******************************************************************
 
3
 
 
4
       iLBC Speech Coder ANSI-C Source Code
 
5
 
 
6
       enhancer.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
   #include "iLBC_define.h"
 
16
   #include "constants.h"
 
17
   #include "filter.h"
 
18
 
 
19
   /*----------------------------------------------------------------*
 
20
    * Find index in array such that the array element with said
 
21
    * index is the element of said array closest to "value"
 
22
    * according to the squared-error criterion
 
23
    *---------------------------------------------------------------*/
 
24
 
 
25
   void NearestNeighbor(
 
26
 
 
27
 
 
28
 
 
29
 
 
30
 
 
31
       int   *index,   /* (o) index of array element closest
 
32
                              to value */
 
33
       float *array,   /* (i) data array */
 
34
       float value,/* (i) value */
 
35
       int arlength/* (i) dimension of data array */
 
36
   ){
 
37
       int i;
 
38
       float bestcrit,crit;
 
39
 
 
40
       crit=array[0]-value;
 
41
       bestcrit=crit*crit;
 
42
       *index=0;
 
43
       for (i=1; i<arlength; i++) {
 
44
           crit=array[i]-value;
 
45
           crit=crit*crit;
 
46
 
 
47
           if (crit<bestcrit) {
 
48
               bestcrit=crit;
 
49
               *index=i;
 
50
           }
 
51
       }
 
52
   }
 
53
 
 
54
   /*----------------------------------------------------------------*
 
55
    * compute cross correlation between sequences
 
56
    *---------------------------------------------------------------*/
 
57
 
 
58
   void mycorr1(
 
59
       float* corr,    /* (o) correlation of seq1 and seq2 */
 
60
       float* seq1,    /* (i) first sequence */
 
61
       int dim1,           /* (i) dimension first seq1 */
 
62
       const float *seq2,  /* (i) second sequence */
 
63
       int dim2        /* (i) dimension seq2 */
 
64
   ){
 
65
       int i,j;
 
66
 
 
67
       for (i=0; i<=dim1-dim2; i++) {
 
68
           corr[i]=0.0;
 
69
           for (j=0; j<dim2; j++) {
 
70
               corr[i] += seq1[i+j] * seq2[j];
 
71
           }
 
72
       }
 
73
   }
 
74
 
 
75
   /*----------------------------------------------------------------*
 
76
    * upsample finite array assuming zeros outside bounds
 
77
    *---------------------------------------------------------------*/
 
78
 
 
79
 
 
80
 
 
81
 
 
82
 
 
83
 
 
84
   void enh_upsample(
 
85
       float* useq1,   /* (o) upsampled output sequence */
 
86
       float* seq1,/* (i) unupsampled sequence */
 
87
       int dim1,       /* (i) dimension seq1 */
 
88
       int hfl         /* (i) polyphase filter length=2*hfl+1 */
 
89
   ){
 
90
       float *pu,*ps;
 
91
       int i,j,k,q,filterlength,hfl2;
 
92
       const float *polyp[ENH_UPS0]; /* pointers to
 
93
                                        polyphase columns */
 
94
       const float *pp;
 
95
 
 
96
       /* define pointers for filter */
 
97
 
 
98
       filterlength=2*hfl+1;
 
99
 
 
100
       if ( filterlength > dim1 ) {
 
101
           hfl2=(int) (dim1/2);
 
102
           for (j=0; j<ENH_UPS0; j++) {
 
103
               polyp[j]=polyphaserTbl+j*filterlength+hfl-hfl2;
 
104
           }
 
105
           hfl=hfl2;
 
106
           filterlength=2*hfl+1;
 
107
       }
 
108
       else {
 
109
           for (j=0; j<ENH_UPS0; j++) {
 
110
               polyp[j]=polyphaserTbl+j*filterlength;
 
111
           }
 
112
       }
 
113
 
 
114
       /* filtering: filter overhangs left side of sequence */
 
115
 
 
116
       pu=useq1;
 
117
       for (i=hfl; i<filterlength; i++) {
 
118
           for (j=0; j<ENH_UPS0; j++) {
 
119
               *pu=0.0;
 
120
               pp = polyp[j];
 
121
               ps = seq1+i;
 
122
               for (k=0; k<=i; k++) {
 
123
                   *pu += *ps-- * *pp++;
 
124
               }
 
125
               pu++;
 
126
           }
 
127
       }
 
128
 
 
129
       /* filtering: simple convolution=inner products */
 
130
 
 
131
       for (i=filterlength; i<dim1; i++) {
 
132
 
 
133
 
 
134
 
 
135
 
 
136
 
 
137
           for (j=0;j<ENH_UPS0; j++){
 
138
               *pu=0.0;
 
139
               pp = polyp[j];
 
140
               ps = seq1+i;
 
141
               for (k=0; k<filterlength; k++) {
 
142
                   *pu += *ps-- * *pp++;
 
143
               }
 
144
               pu++;
 
145
           }
 
146
       }
 
147
 
 
148
       /* filtering: filter overhangs right side of sequence */
 
149
 
 
150
       for (q=1; q<=hfl; q++) {
 
151
           for (j=0; j<ENH_UPS0; j++) {
 
152
               *pu=0.0;
 
153
               pp = polyp[j]+q;
 
154
               ps = seq1+dim1-1;
 
155
               for (k=0; k<filterlength-q; k++) {
 
156
                   *pu += *ps-- * *pp++;
 
157
               }
 
158
               pu++;
 
159
           }
 
160
       }
 
161
   }
 
162
 
 
163
 
 
164
   /*----------------------------------------------------------------*
 
165
    * find segment starting near idata+estSegPos that has highest
 
166
    * correlation with idata+centerStartPos through
 
167
    * idata+centerStartPos+ENH_BLOCKL-1 segment is found at a
 
168
    * resolution of ENH_UPSO times the original of the original
 
169
    * sampling rate
 
170
    *---------------------------------------------------------------*/
 
171
 
 
172
   void refiner(
 
173
       float *seg,         /* (o) segment array */
 
174
       float *updStartPos, /* (o) updated start point */
 
175
       float* idata,       /* (i) original data buffer */
 
176
       int idatal,         /* (i) dimension of idata */
 
177
       int centerStartPos, /* (i) beginning center segment */
 
178
       float estSegPos,/* (i) estimated beginning other segment */
 
179
       float period    /* (i) estimated pitch period */
 
180
   ){
 
181
       int estSegPosRounded,searchSegStartPos,searchSegEndPos,corrdim;
 
182
       int tloc,tloc2,i,st,en,fraction;
 
183
       float vect[ENH_VECTL],corrVec[ENH_CORRDIM],maxv;
 
184
       float corrVecUps[ENH_CORRDIM*ENH_UPS0];
 
185
 
 
186
       (void)period;
 
187
 
 
188
 
 
189
 
 
190
       /* defining array bounds */
 
191
 
 
192
       estSegPosRounded=(int)(estSegPos - 0.5);
 
193
 
 
194
       searchSegStartPos=estSegPosRounded-ENH_SLOP;
 
195
 
 
196
       if (searchSegStartPos<0) {
 
197
           searchSegStartPos=0;
 
198
       }
 
199
       searchSegEndPos=estSegPosRounded+ENH_SLOP;
 
200
 
 
201
       if (searchSegEndPos+ENH_BLOCKL >= idatal) {
 
202
           searchSegEndPos=idatal-ENH_BLOCKL-1;
 
203
       }
 
204
       corrdim=searchSegEndPos-searchSegStartPos+1;
 
205
 
 
206
       /* compute upsampled correlation (corr33) and find
 
207
          location of max */
 
208
 
 
209
       mycorr1(corrVec,idata+searchSegStartPos,
 
210
           corrdim+ENH_BLOCKL-1,idata+centerStartPos,ENH_BLOCKL);
 
211
       enh_upsample(corrVecUps,corrVec,corrdim,ENH_FL0);
 
212
       tloc=0; maxv=corrVecUps[0];
 
213
       for (i=1; i<ENH_UPS0*corrdim; i++) {
 
214
 
 
215
           if (corrVecUps[i]>maxv) {
 
216
               tloc=i;
 
217
               maxv=corrVecUps[i];
 
218
           }
 
219
       }
 
220
 
 
221
       /* make vector can be upsampled without ever running outside
 
222
          bounds */
 
223
 
 
224
       *updStartPos= (float)searchSegStartPos +
 
225
           (float)tloc/(float)ENH_UPS0+(float)1.0;
 
226
       tloc2=(int)(tloc/ENH_UPS0);
 
227
 
 
228
       if (tloc>tloc2*ENH_UPS0) {
 
229
           tloc2++;
 
230
       }
 
231
       st=searchSegStartPos+tloc2-ENH_FL0;
 
232
 
 
233
       if (st<0) {
 
234
           memset(vect,0,-st*sizeof(float));
 
235
           memcpy(&vect[-st],idata, (ENH_VECTL+st)*sizeof(float));
 
236
       }
 
237
       else {
 
238
 
 
239
 
 
240
 
 
241
 
 
242
 
 
243
           en=st+ENH_VECTL;
 
244
 
 
245
           if (en>idatal) {
 
246
               memcpy(vect, &idata[st],
 
247
                   (ENH_VECTL-(en-idatal))*sizeof(float));
 
248
               memset(&vect[ENH_VECTL-(en-idatal)], 0,
 
249
                   (en-idatal)*sizeof(float));
 
250
           }
 
251
           else {
 
252
               memcpy(vect, &idata[st], ENH_VECTL*sizeof(float));
 
253
           }
 
254
       }
 
255
       fraction=tloc2*ENH_UPS0-tloc;
 
256
 
 
257
       /* compute the segment (this is actually a convolution) */
 
258
 
 
259
       mycorr1(seg,vect,ENH_VECTL,polyphaserTbl+(2*ENH_FL0+1)*fraction,
 
260
           2*ENH_FL0+1);
 
261
   }
 
262
 
 
263
   /*----------------------------------------------------------------*
 
264
    * find the smoothed output data
 
265
    *---------------------------------------------------------------*/
 
266
 
 
267
   void smath(
 
268
       float *odata,   /* (o) smoothed output */
 
269
       float *sseq,/* (i) said second sequence of waveforms */
 
270
       int hl,         /* (i) 2*hl+1 is sseq dimension */
 
271
       float alpha0/* (i) max smoothing energy fraction */
 
272
   ){
 
273
       int i,k;
 
274
       float w00,w10,w11,A,B,C,*psseq,err,errs;
 
275
       float surround[BLOCKL_MAX]; /* shape contributed by other than
 
276
                                      current */
 
277
       float wt[2*ENH_HL+1];       /* waveform weighting to get
 
278
                                      surround shape */
 
279
       float denom;
 
280
 
 
281
       /* create shape of contribution from all waveforms except the
 
282
          current one */
 
283
 
 
284
       for (i=1; i<=2*hl+1; i++) {
 
285
           wt[i-1] = (float)0.5*(1 - (float)cos(2*PI*i/(2*hl+2)));
 
286
       }
 
287
       wt[hl]=0.0; /* for clarity, not used */
 
288
       for (i=0; i<ENH_BLOCKL; i++) {
 
289
           surround[i]=sseq[i]*wt[0];
 
290
       }
 
291
 
 
292
 
 
293
 
 
294
 
 
295
 
 
296
       for (k=1; k<hl; k++) {
 
297
           psseq=sseq+k*ENH_BLOCKL;
 
298
           for(i=0;i<ENH_BLOCKL; i++) {
 
299
               surround[i]+=psseq[i]*wt[k];
 
300
           }
 
301
       }
 
302
       for (k=hl+1; k<=2*hl; k++) {
 
303
           psseq=sseq+k*ENH_BLOCKL;
 
304
           for(i=0;i<ENH_BLOCKL; i++) {
 
305
               surround[i]+=psseq[i]*wt[k];
 
306
           }
 
307
       }
 
308
 
 
309
       /* compute some inner products */
 
310
 
 
311
       w00 = w10 = w11 = 0.0;
 
312
       psseq=sseq+hl*ENH_BLOCKL; /* current block  */
 
313
       for (i=0; i<ENH_BLOCKL;i++) {
 
314
           w00+=psseq[i]*psseq[i];
 
315
           w11+=surround[i]*surround[i];
 
316
           w10+=surround[i]*psseq[i];
 
317
       }
 
318
 
 
319
       if (fabs(w11) < 1.0) {
 
320
           w11=1.0;
 
321
       }
 
322
       C = (float)sqrt( w00/w11);
 
323
 
 
324
       /* first try enhancement without power-constraint */
 
325
 
 
326
       errs=0.0;
 
327
       psseq=sseq+hl*ENH_BLOCKL;
 
328
       for (i=0; i<ENH_BLOCKL; i++) {
 
329
           odata[i]=C*surround[i];
 
330
           err=psseq[i]-odata[i];
 
331
           errs+=err*err;
 
332
       }
 
333
 
 
334
       /* if constraint violated by first try, add constraint */
 
335
 
 
336
       if (errs > alpha0 * w00) {
 
337
           if ( w00 < 1) {
 
338
               w00=1;
 
339
           }
 
340
           denom = (w11*w00-w10*w10)/(w00*w00);
 
341
 
 
342
           if (denom > 0.0001) { /* eliminates numerical problems
 
343
                                    for if smooth */
 
344
 
 
345
 
 
346
 
 
347
 
 
348
 
 
349
               A = (float)sqrt( (alpha0- alpha0*alpha0/4)/denom);
 
350
               B = -alpha0/2 - A * w10/w00;
 
351
               B = B+1;
 
352
           }
 
353
           else { /* essentially no difference between cycles;
 
354
                     smoothing not needed */
 
355
               A= 0.0;
 
356
               B= 1.0;
 
357
           }
 
358
 
 
359
           /* create smoothed sequence */
 
360
 
 
361
           psseq=sseq+hl*ENH_BLOCKL;
 
362
           for (i=0; i<ENH_BLOCKL; i++) {
 
363
               odata[i]=A*surround[i]+B*psseq[i];
 
364
           }
 
365
       }
 
366
   }
 
367
 
 
368
   /*----------------------------------------------------------------*
 
369
    * get the pitch-synchronous sample sequence
 
370
    *---------------------------------------------------------------*/
 
371
 
 
372
   void getsseq(
 
373
       float *sseq,    /* (o) the pitch-synchronous sequence */
 
374
       float *idata,       /* (i) original data */
 
375
       int idatal,         /* (i) dimension of data */
 
376
       int centerStartPos, /* (i) where current block starts */
 
377
       float *period,      /* (i) rough-pitch-period array */
 
378
       float *plocs,       /* (i) where periods of period array
 
379
                                  are taken */
 
380
       int periodl,    /* (i) dimension period array */
 
381
       int hl              /* (i) 2*hl+1 is the number of sequences */
 
382
   ){
 
383
       int i,centerEndPos,q;
 
384
       float blockStartPos[2*ENH_HL+1];
 
385
       int lagBlock[2*ENH_HL+1];
 
386
       float plocs2[ENH_PLOCSL];
 
387
       float *psseq;
 
388
 
 
389
       centerEndPos=centerStartPos+ENH_BLOCKL-1;
 
390
 
 
391
       /* present */
 
392
 
 
393
       NearestNeighbor(lagBlock+hl,plocs,
 
394
           (float)0.5*(centerStartPos+centerEndPos),periodl);
 
395
 
 
396
       blockStartPos[hl]=(float)centerStartPos;
 
397
 
 
398
 
 
399
 
 
400
 
 
401
 
 
402
       psseq=sseq+ENH_BLOCKL*hl;
 
403
       memcpy(psseq, idata+centerStartPos, ENH_BLOCKL*sizeof(float));
 
404
 
 
405
       /* past */
 
406
 
 
407
       for (q=hl-1; q>=0; q--) {
 
408
           blockStartPos[q]=blockStartPos[q+1]-period[lagBlock[q+1]];
 
409
           NearestNeighbor(lagBlock+q,plocs,
 
410
               blockStartPos[q]+
 
411
               ENH_BLOCKL_HALF-period[lagBlock[q+1]], periodl);
 
412
 
 
413
 
 
414
           if (blockStartPos[q]-ENH_OVERHANG>=0) {
 
415
               refiner(sseq+q*ENH_BLOCKL, blockStartPos+q, idata,
 
416
                   idatal, centerStartPos, blockStartPos[q],
 
417
                   period[lagBlock[q+1]]);
 
418
           } else {
 
419
               psseq=sseq+q*ENH_BLOCKL;
 
420
               memset(psseq, 0, ENH_BLOCKL*sizeof(float));
 
421
           }
 
422
       }
 
423
 
 
424
       /* future */
 
425
 
 
426
       for (i=0; i<periodl; i++) {
 
427
           plocs2[i]=plocs[i]-period[i];
 
428
       }
 
429
       for (q=hl+1; q<=2*hl; q++) {
 
430
           NearestNeighbor(lagBlock+q,plocs2,
 
431
               blockStartPos[q-1]+ENH_BLOCKL_HALF,periodl);
 
432
 
 
433
           blockStartPos[q]=blockStartPos[q-1]+period[lagBlock[q]];
 
434
           if (blockStartPos[q]+ENH_BLOCKL+ENH_OVERHANG<idatal) {
 
435
               refiner(sseq+ENH_BLOCKL*q, blockStartPos+q, idata,
 
436
                   idatal, centerStartPos, blockStartPos[q],
 
437
                   period[lagBlock[q]]);
 
438
           }
 
439
           else {
 
440
               psseq=sseq+q*ENH_BLOCKL;
 
441
               memset(psseq, 0, ENH_BLOCKL*sizeof(float));
 
442
           }
 
443
       }
 
444
   }
 
445
 
 
446
   /*----------------------------------------------------------------*
 
447
    * perform enhancement on idata+centerStartPos through
 
448
    * idata+centerStartPos+ENH_BLOCKL-1
 
449
    *---------------------------------------------------------------*/
 
450
 
 
451
 
 
452
 
 
453
 
 
454
 
 
455
   void enhancer(
 
456
       float *odata,       /* (o) smoothed block, dimension blockl */
 
457
       float *idata,       /* (i) data buffer used for enhancing */
 
458
       int idatal,         /* (i) dimension idata */
 
459
       int centerStartPos, /* (i) first sample current block
 
460
                                  within idata */
 
461
       float alpha0,       /* (i) max correction-energy-fraction
 
462
                                 (in [0,1]) */
 
463
       float *period,      /* (i) pitch period array */
 
464
       float *plocs,       /* (i) locations where period array
 
465
                                  values valid */
 
466
       int periodl         /* (i) dimension of period and plocs */
 
467
   ){
 
468
       float sseq[(2*ENH_HL+1)*ENH_BLOCKL];
 
469
 
 
470
       /* get said second sequence of segments */
 
471
 
 
472
       getsseq(sseq,idata,idatal,centerStartPos,period,
 
473
           plocs,periodl,ENH_HL);
 
474
 
 
475
       /* compute the smoothed output from said second sequence */
 
476
 
 
477
       smath(odata,sseq,ENH_HL,alpha0);
 
478
 
 
479
   }
 
480
 
 
481
   /*----------------------------------------------------------------*
 
482
    * cross correlation
 
483
    *---------------------------------------------------------------*/
 
484
 
 
485
   float xCorrCoef(
 
486
       float *target,      /* (i) first array */
 
487
       float *regressor,   /* (i) second array */
 
488
       int subl        /* (i) dimension arrays */
 
489
   ){
 
490
       int i;
 
491
       float ftmp1, ftmp2;
 
492
 
 
493
       ftmp1 = 0.0;
 
494
       ftmp2 = 0.0;
 
495
       for (i=0; i<subl; i++) {
 
496
           ftmp1 += target[i]*regressor[i];
 
497
           ftmp2 += regressor[i]*regressor[i];
 
498
       }
 
499
 
 
500
       if (ftmp1 > 0.0) {
 
501
           return (float)(ftmp1*ftmp1/ftmp2);
 
502
       }
 
503
 
 
504
 
 
505
 
 
506
 
 
507
 
 
508
       else {
 
509
           return (float)0.0;
 
510
       }
 
511
   }
 
512
 
 
513
   /*----------------------------------------------------------------*
 
514
    * interface for enhancer
 
515
    *---------------------------------------------------------------*/
 
516
 
 
517
   int enhancerInterface(
 
518
       float *out,                     /* (o) enhanced signal */
 
519
       float *in,                      /* (i) unenhanced signal */
 
520
       iLBC_Dec_Inst_t *iLBCdec_inst   /* (i) buffers etc */
 
521
   ){
 
522
       float *enh_buf, *enh_period;
 
523
       int iblock, isample;
 
524
       int lag=0, ilag, i, ioffset;
 
525
       float cc, maxcc;
 
526
       float ftmp1, ftmp2;
 
527
       float *inPtr, *enh_bufPtr1, *enh_bufPtr2;
 
528
       float plc_pred[ENH_BLOCKL];
 
529
 
 
530
       float lpState[6], downsampled[(ENH_NBLOCKS*ENH_BLOCKL+120)/2];
 
531
       int inLen=ENH_NBLOCKS*ENH_BLOCKL+120;
 
532
       int start, plc_blockl, inlag;
 
533
 
 
534
       enh_buf=iLBCdec_inst->enh_buf;
 
535
       enh_period=iLBCdec_inst->enh_period;
 
536
 
 
537
       memmove(enh_buf, &enh_buf[iLBCdec_inst->blockl],
 
538
           (ENH_BUFL-iLBCdec_inst->blockl)*sizeof(float));
 
539
 
 
540
       memcpy(&enh_buf[ENH_BUFL-iLBCdec_inst->blockl], in,
 
541
           iLBCdec_inst->blockl*sizeof(float));
 
542
 
 
543
       if (iLBCdec_inst->mode==30)
 
544
           plc_blockl=ENH_BLOCKL;
 
545
       else
 
546
           plc_blockl=40;
 
547
 
 
548
       /* when 20 ms frame, move processing one block */
 
549
       ioffset=0;
 
550
       if (iLBCdec_inst->mode==20) ioffset=1;
 
551
 
 
552
       i=3-ioffset;
 
553
       memmove(enh_period, &enh_period[i],
 
554
           (ENH_NBLOCKS_TOT-i)*sizeof(float));
 
555
 
 
556
 
 
557
 
 
558
 
 
559
 
 
560
 
 
561
       /* Set state information to the 6 samples right before
 
562
          the samples to be downsampled. */
 
563
 
 
564
       memcpy(lpState,
 
565
           enh_buf+(ENH_NBLOCKS_EXTRA+ioffset)*ENH_BLOCKL-126,
 
566
           6*sizeof(float));
 
567
 
 
568
       /* Down sample a factor 2 to save computations */
 
569
 
 
570
       DownSample(enh_buf+(ENH_NBLOCKS_EXTRA+ioffset)*ENH_BLOCKL-120,
 
571
                   lpFilt_coefsTbl, inLen-ioffset*ENH_BLOCKL,
 
572
                   lpState, downsampled);
 
573
 
 
574
       /* Estimate the pitch in the down sampled domain. */
 
575
       for (iblock = 0; iblock<ENH_NBLOCKS-ioffset; iblock++) {
 
576
 
 
577
           lag = 10;
 
578
           maxcc = xCorrCoef(downsampled+60+iblock*
 
579
               ENH_BLOCKL_HALF, downsampled+60+iblock*
 
580
               ENH_BLOCKL_HALF-lag, ENH_BLOCKL_HALF);
 
581
           for (ilag=11; ilag<60; ilag++) {
 
582
               cc = xCorrCoef(downsampled+60+iblock*
 
583
                   ENH_BLOCKL_HALF, downsampled+60+iblock*
 
584
                   ENH_BLOCKL_HALF-ilag, ENH_BLOCKL_HALF);
 
585
 
 
586
               if (cc > maxcc) {
 
587
                   maxcc = cc;
 
588
                   lag = ilag;
 
589
               }
 
590
           }
 
591
 
 
592
           /* Store the estimated lag in the non-downsampled domain */
 
593
           enh_period[iblock+ENH_NBLOCKS_EXTRA+ioffset] = (float)lag*2;
 
594
 
 
595
 
 
596
       }
 
597
 
 
598
 
 
599
       /* PLC was performed on the previous packet */
 
600
       if (iLBCdec_inst->prev_enh_pl==1) {
 
601
 
 
602
           inlag=(int)enh_period[ENH_NBLOCKS_EXTRA+ioffset];
 
603
 
 
604
           lag = inlag-1;
 
605
           maxcc = xCorrCoef(in, in+lag, plc_blockl);
 
606
           for (ilag=inlag; ilag<=inlag+1; ilag++) {
 
607
               cc = xCorrCoef(in, in+ilag, plc_blockl);
 
608
 
 
609
 
 
610
 
 
611
 
 
612
 
 
613
 
 
614
               if (cc > maxcc) {
 
615
                   maxcc = cc;
 
616
                   lag = ilag;
 
617
               }
 
618
           }
 
619
 
 
620
           enh_period[ENH_NBLOCKS_EXTRA+ioffset-1]=(float)lag;
 
621
 
 
622
           /* compute new concealed residual for the old lookahead,
 
623
              mix the forward PLC with a backward PLC from
 
624
              the new frame */
 
625
 
 
626
           inPtr=&in[lag-1];
 
627
 
 
628
           enh_bufPtr1=&plc_pred[plc_blockl-1];
 
629
 
 
630
           if (lag>plc_blockl) {
 
631
               start=plc_blockl;
 
632
           } else {
 
633
               start=lag;
 
634
           }
 
635
 
 
636
           for (isample = start; isample>0; isample--) {
 
637
               *enh_bufPtr1-- = *inPtr--;
 
638
           }
 
639
 
 
640
           enh_bufPtr2=&enh_buf[ENH_BUFL-1-iLBCdec_inst->blockl];
 
641
           for (isample = (plc_blockl-1-lag); isample>=0; isample--) {
 
642
               *enh_bufPtr1-- = *enh_bufPtr2--;
 
643
           }
 
644
 
 
645
           /* limit energy change */
 
646
           ftmp2=0.0;
 
647
           ftmp1=0.0;
 
648
           for (i=0;i<plc_blockl;i++) {
 
649
               ftmp2+=enh_buf[ENH_BUFL-1-iLBCdec_inst->blockl-i]*
 
650
                   enh_buf[ENH_BUFL-1-iLBCdec_inst->blockl-i];
 
651
               ftmp1+=plc_pred[i]*plc_pred[i];
 
652
           }
 
653
           ftmp1=(float)sqrt(ftmp1/(float)plc_blockl);
 
654
           ftmp2=(float)sqrt(ftmp2/(float)plc_blockl);
 
655
           if (ftmp1>(float)2.0*ftmp2 && ftmp1>0.0) {
 
656
               for (i=0;i<plc_blockl-10;i++) {
 
657
                   plc_pred[i]*=(float)2.0*ftmp2/ftmp1;
 
658
               }
 
659
               for (i=plc_blockl-10;i<plc_blockl;i++) {
 
660
                   plc_pred[i]*=(float)(i-plc_blockl+10)*
 
661
                       ((float)1.0-(float)2.0*ftmp2/ftmp1)/(float)(10)+
 
662
 
 
663
 
 
664
 
 
665
 
 
666
 
 
667
                       (float)2.0*ftmp2/ftmp1;
 
668
               }
 
669
           }
 
670
 
 
671
           enh_bufPtr1=&enh_buf[ENH_BUFL-1-iLBCdec_inst->blockl];
 
672
           for (i=0; i<plc_blockl; i++) {
 
673
               ftmp1 = (float) (i+1) / (float) (plc_blockl+1);
 
674
               *enh_bufPtr1 *= ftmp1;
 
675
               *enh_bufPtr1 += ((float)1.0-ftmp1)*
 
676
                                   plc_pred[plc_blockl-1-i];
 
677
               enh_bufPtr1--;
 
678
           }
 
679
       }
 
680
 
 
681
       if (iLBCdec_inst->mode==20) {
 
682
           /* Enhancer with 40 samples delay */
 
683
           for (iblock = 0; iblock<2; iblock++) {
 
684
               enhancer(out+iblock*ENH_BLOCKL, enh_buf,
 
685
                   ENH_BUFL, (5+iblock)*ENH_BLOCKL+40,
 
686
                   ENH_ALPHA0, enh_period, enh_plocsTbl,
 
687
                       ENH_NBLOCKS_TOT);
 
688
           }
 
689
       } else if (iLBCdec_inst->mode==30) {
 
690
           /* Enhancer with 80 samples delay */
 
691
           for (iblock = 0; iblock<3; iblock++) {
 
692
               enhancer(out+iblock*ENH_BLOCKL, enh_buf,
 
693
                   ENH_BUFL, (4+iblock)*ENH_BLOCKL,
 
694
                   ENH_ALPHA0, enh_period, enh_plocsTbl,
 
695
                       ENH_NBLOCKS_TOT);
 
696
           }
 
697
       }
 
698
 
 
699
       return (lag*2);
 
700
   }
 
701