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