1 
2 /******************************************************************
3 
4     iLBC Speech Coder ANSI-C Source Code
5 
6     doCPLC.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 <stdio.h>
16 
17 #include "iLBC_define.h"
18 #include "doCPLC.h"
19 
20 /*----------------------------------------------------------------*
21  *  Compute cross correlation and pitch gain for pitch prediction
22  *  of last subframe at given lag.
23  *---------------------------------------------------------------*/
24 
compCorr(float * cc,float * gc,float * pm,float * buffer,int lag,int bLen,int sRange)25 static void compCorr(
26     float *cc,      /* (o) cross correlation coefficient */
27     float *gc,      /* (o) gain */
28     float *pm,
29     float *buffer,  /* (i) signal buffer */
30     int lag,    /* (i) pitch lag */
31     int bLen,       /* (i) length of buffer */
32     int sRange      /* (i) correlation search length */
33 ){
34 
35 
36     int i;
37     float ftmp1, ftmp2, ftmp3;
38 
39     /* Guard against getting outside buffer */
40     if ((bLen-sRange-lag)<0) {
41         sRange=bLen-lag;
42     }
43 
44     ftmp1 = 0.0;
45     ftmp2 = 0.0;
46     ftmp3 = 0.0;
47     for (i=0; i<sRange; i++) {
48         ftmp1 += buffer[bLen-sRange+i] *
49             buffer[bLen-sRange+i-lag];
50         ftmp2 += buffer[bLen-sRange+i-lag] *
51                 buffer[bLen-sRange+i-lag];
52         ftmp3 += buffer[bLen-sRange+i] *
53                 buffer[bLen-sRange+i];
54     }
55 
56     if (ftmp2 > 0.0) {
57         *cc = ftmp1*ftmp1/ftmp2;
58         *gc = (float)fabs(ftmp1/ftmp2);
59         *pm=(float)fabs(ftmp1)/
60             ((float)sqrt(ftmp2)*(float)sqrt(ftmp3));
61     }
62     else {
63         *cc = 0.0;
64         *gc = 0.0;
65         *pm=0.0;
66     }
67 }
68 
69 /*----------------------------------------------------------------*
70  *  Packet loss concealment routine. Conceals a residual signal
71  *  and LP parameters. If no packet loss, update state.
72  *---------------------------------------------------------------*/
73 
doThePLC(float * PLCresidual,float * PLClpc,int PLI,float * decresidual,float * lpc,int inlag,iLBC_Dec_Inst_t * iLBCdec_inst)74 void doThePLC(
75     float *PLCresidual, /* (o) concealed residual */
76     float *PLClpc,      /* (o) concealed LP parameters */
77     int PLI,        /* (i) packet loss indicator
78                                0 - no PL, 1 = PL */
79     float *decresidual, /* (i) decoded residual */
80     float *lpc,         /* (i) decoded LPC (only used for no PL) */
81     int inlag,          /* (i) pitch lag */
82     iLBC_Dec_Inst_t *iLBCdec_inst
83                         /* (i/o) decoder instance */
84 ){
85     int lag=20, randlag;
86     float gain, maxcc;
87     float use_gain;
88     float gain_comp, maxcc_comp, per, max_per;
89     int i, pick, use_lag;
90 
91 
92     float ftmp, randvec[BLOCKL_MAX], pitchfact, energy;
93 
94     /* Packet Loss */
95 
96     if (PLI == 1) {
97 
98         iLBCdec_inst->consPLICount += 1;
99 
100         /* if previous frame not lost,
101            determine pitch pred. gain */
102 
103         if (iLBCdec_inst->prevPLI != 1) {
104 
105             /* Search around the previous lag to find the
106                best pitch period */
107 
108             lag=inlag-3;
109             compCorr(&maxcc, &gain, &max_per,
110                 iLBCdec_inst->prevResidual,
111                 lag, iLBCdec_inst->blockl, 60);
112             for (i=inlag-2;i<=inlag+3;i++) {
113                 compCorr(&maxcc_comp, &gain_comp, &per,
114                     iLBCdec_inst->prevResidual,
115                     i, iLBCdec_inst->blockl, 60);
116 
117                 if (maxcc_comp>maxcc) {
118                     maxcc=maxcc_comp;
119                     gain=gain_comp;
120                     lag=i;
121                     max_per=per;
122                 }
123             }
124 
125         }
126 
127         /* previous frame lost, use recorded lag and periodicity */
128 
129         else {
130             lag=iLBCdec_inst->prevLag;
131             max_per=iLBCdec_inst->per;
132         }
133 
134         /* downscaling */
135 
136         use_gain=1.0;
137         if (iLBCdec_inst->consPLICount*iLBCdec_inst->blockl>320)
138             use_gain=(float)0.9;
139         else if (iLBCdec_inst->consPLICount*
140                         iLBCdec_inst->blockl>2*320)
141             use_gain=(float)0.7;
142         else if (iLBCdec_inst->consPLICount*
143                         iLBCdec_inst->blockl>3*320)
144             use_gain=(float)0.5;
145         else if (iLBCdec_inst->consPLICount*
146 
147 
148                         iLBCdec_inst->blockl>4*320)
149             use_gain=(float)0.0;
150 
151         /* mix noise and pitch repeatition */
152         ftmp=(float)sqrt(max_per);
153         if (ftmp>(float)0.7)
154             pitchfact=(float)1.0;
155         else if (ftmp>(float)0.4)
156             pitchfact=(ftmp-(float)0.4)/((float)0.7-(float)0.4);
157         else
158             pitchfact=0.0;
159 
160 
161         /* avoid repetition of same pitch cycle */
162         use_lag=lag;
163         if (lag<80) {
164             use_lag=2*lag;
165         }
166 
167         /* compute concealed residual */
168 
169         energy = 0.0;
170         for (i=0; i<iLBCdec_inst->blockl; i++) {
171 
172             /* noise component */
173 
174             iLBCdec_inst->seed=(iLBCdec_inst->seed*69069L+1) &
175                 (0x80000000L-1);
176             randlag = 50 + ((signed long) iLBCdec_inst->seed)%70;
177             pick = i - randlag;
178 
179             if (pick < 0) {
180                 randvec[i] =
181                     iLBCdec_inst->prevResidual[
182                                 iLBCdec_inst->blockl+pick];
183             } else {
184                 randvec[i] =  randvec[pick];
185             }
186 
187             /* pitch repeatition component */
188             pick = i - use_lag;
189 
190             if (pick < 0) {
191                 PLCresidual[i] =
192                     iLBCdec_inst->prevResidual[
193                                 iLBCdec_inst->blockl+pick];
194             } else {
195                 PLCresidual[i] = PLCresidual[pick];
196             }
197 
198             /* mix random and periodicity component */
199 
200             if (i<80)
201                 PLCresidual[i] = use_gain*(pitchfact *
202 
203 
204                             PLCresidual[i] +
205                             ((float)1.0 - pitchfact) * randvec[i]);
206             else if (i<160)
207                 PLCresidual[i] = (float)0.95*use_gain*(pitchfact *
208                             PLCresidual[i] +
209                             ((float)1.0 - pitchfact) * randvec[i]);
210             else
211                 PLCresidual[i] = (float)0.9*use_gain*(pitchfact *
212                             PLCresidual[i] +
213                             ((float)1.0 - pitchfact) * randvec[i]);
214 
215             energy += PLCresidual[i] * PLCresidual[i];
216         }
217 
218         /* less than 30 dB, use only noise */
219 
220         if (sqrt(energy/(float)iLBCdec_inst->blockl) < 30.0) {
221             gain=0.0;
222             for (i=0; i<iLBCdec_inst->blockl; i++) {
223                 PLCresidual[i] = randvec[i];
224             }
225         }
226 
227         /* use old LPC */
228 
229         memcpy(PLClpc,iLBCdec_inst->prevLpc,
230             (LPC_FILTERORDER+1)*sizeof(float));
231 
232     }
233 
234     /* no packet loss, copy input */
235 
236     else {
237         memcpy(PLCresidual, decresidual,
238             iLBCdec_inst->blockl*sizeof(float));
239         memcpy(PLClpc, lpc, (LPC_FILTERORDER+1)*sizeof(float));
240         iLBCdec_inst->consPLICount = 0;
241     }
242 
243     /* update state */
244 
245     if (PLI) {
246         iLBCdec_inst->prevLag = lag;
247         iLBCdec_inst->per=max_per;
248     }
249 
250     iLBCdec_inst->prevPLI = PLI;
251     memcpy(iLBCdec_inst->prevLpc, PLClpc,
252         (LPC_FILTERORDER+1)*sizeof(float));
253     memcpy(iLBCdec_inst->prevResidual, PLCresidual,
254         iLBCdec_inst->blockl*sizeof(float));
255 }
256 
257 
258 
259 
260