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