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