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