1 /* 2 * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 /****************************************************************** 12 13 iLBC Speech Coder ANSI-C Source Code 14 15 WebRtcIlbcfix_DoThePlc.c 16 17 ******************************************************************/ 18 19 #include "defines.h" 20 #include "constants.h" 21 #include "comp_corr.h" 22 #include "bw_expand.h" 23 24 /*----------------------------------------------------------------* 25 * Packet loss concealment routine. Conceals a residual signal 26 * and LP parameters. If no packet loss, update state. 27 *---------------------------------------------------------------*/ 28 29 void WebRtcIlbcfix_DoThePlc( 30 int16_t *PLCresidual, /* (o) concealed residual */ 31 int16_t *PLClpc, /* (o) concealed LP parameters */ 32 int16_t PLI, /* (i) packet loss indicator 33 0 - no PL, 1 = PL */ 34 int16_t *decresidual, /* (i) decoded residual */ 35 int16_t *lpc, /* (i) decoded LPC (only used for no PL) */ 36 int16_t inlag, /* (i) pitch lag */ 37 iLBC_Dec_Inst_t *iLBCdec_inst 38 /* (i/o) decoder instance */ 39 ){ 40 int16_t i, pick; 41 int32_t cross, ener, cross_comp, ener_comp = 0; 42 int32_t measure, maxMeasure, energy; 43 int16_t max, crossSquareMax, crossSquare; 44 int16_t j, lag, tmp1, tmp2, randlag; 45 int16_t shift1, shift2, shift3, shiftMax; 46 int16_t scale3; 47 int16_t corrLen; 48 int32_t tmpW32, tmp2W32; 49 int16_t use_gain; 50 int16_t tot_gain; 51 int16_t max_perSquare; 52 int16_t scale1, scale2; 53 int16_t totscale; 54 int32_t nom; 55 int16_t denom; 56 int16_t pitchfact; 57 int16_t use_lag; 58 int ind; 59 int16_t randvec[BLOCKL_MAX]; 60 61 /* Packet Loss */ 62 if (PLI == 1) { 63 64 (*iLBCdec_inst).consPLICount += 1; 65 66 /* if previous frame not lost, 67 determine pitch pred. gain */ 68 69 if (iLBCdec_inst->prevPLI != 1) { 70 71 /* Maximum 60 samples are correlated, preserve as high accuracy 72 as possible without getting overflow */ 73 max = WebRtcSpl_MaxAbsValueW16((*iLBCdec_inst).prevResidual, (int16_t)iLBCdec_inst->blockl); 74 scale3 = (WebRtcSpl_GetSizeInBits(max)<<1) - 25; 75 if (scale3 < 0) { 76 scale3 = 0; 77 } 78 79 /* Store scale for use when interpolating between the 80 * concealment and the received packet */ 81 iLBCdec_inst->prevScale = scale3; 82 83 /* Search around the previous lag +/-3 to find the 84 best pitch period */ 85 lag = inlag - 3; 86 87 /* Guard against getting outside the frame */ 88 corrLen = WEBRTC_SPL_MIN(60, iLBCdec_inst->blockl-(inlag+3)); 89 90 WebRtcIlbcfix_CompCorr( &cross, &ener, 91 iLBCdec_inst->prevResidual, lag, iLBCdec_inst->blockl, corrLen, scale3); 92 93 /* Normalize and store cross^2 and the number of shifts */ 94 shiftMax = WebRtcSpl_GetSizeInBits(WEBRTC_SPL_ABS_W32(cross))-15; 95 crossSquareMax = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(WEBRTC_SPL_SHIFT_W32(cross, -shiftMax), 96 WEBRTC_SPL_SHIFT_W32(cross, -shiftMax), 15); 97 98 for (j=inlag-2;j<=inlag+3;j++) { 99 WebRtcIlbcfix_CompCorr( &cross_comp, &ener_comp, 100 iLBCdec_inst->prevResidual, j, iLBCdec_inst->blockl, corrLen, scale3); 101 102 /* Use the criteria (corr*corr)/energy to compare if 103 this lag is better or not. To avoid the division, 104 do a cross multiplication */ 105 shift1 = WebRtcSpl_GetSizeInBits(WEBRTC_SPL_ABS_W32(cross_comp))-15; 106 crossSquare = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(WEBRTC_SPL_SHIFT_W32(cross_comp, -shift1), 107 WEBRTC_SPL_SHIFT_W32(cross_comp, -shift1), 15); 108 109 shift2 = WebRtcSpl_GetSizeInBits(ener)-15; 110 measure = WEBRTC_SPL_MUL_16_16(WEBRTC_SPL_SHIFT_W32(ener, -shift2), 111 crossSquare); 112 113 shift3 = WebRtcSpl_GetSizeInBits(ener_comp)-15; 114 maxMeasure = WEBRTC_SPL_MUL_16_16(WEBRTC_SPL_SHIFT_W32(ener_comp, -shift3), 115 crossSquareMax); 116 117 /* Calculate shift value, so that the two measures can 118 be put in the same Q domain */ 119 if(((shiftMax<<1)+shift3) > ((shift1<<1)+shift2)) { 120 tmp1 = WEBRTC_SPL_MIN(31, (shiftMax<<1)+shift3-(shift1<<1)-shift2); 121 tmp2 = 0; 122 } else { 123 tmp1 = 0; 124 tmp2 = WEBRTC_SPL_MIN(31, (shift1<<1)+shift2-(shiftMax<<1)-shift3); 125 } 126 127 if ((measure>>tmp1) > (maxMeasure>>tmp2)) { 128 /* New lag is better => record lag, measure and domain */ 129 lag = j; 130 crossSquareMax = crossSquare; 131 cross = cross_comp; 132 shiftMax = shift1; 133 ener = ener_comp; 134 } 135 } 136 137 /* Calculate the periodicity for the lag with the maximum correlation. 138 139 Definition of the periodicity: 140 abs(corr(vec1, vec2))/(sqrt(energy(vec1))*sqrt(energy(vec2))) 141 142 Work in the Square domain to simplify the calculations 143 max_perSquare is less than 1 (in Q15) 144 */ 145 tmp2W32=WebRtcSpl_DotProductWithScale(&iLBCdec_inst->prevResidual[iLBCdec_inst->blockl-corrLen], 146 &iLBCdec_inst->prevResidual[iLBCdec_inst->blockl-corrLen], 147 corrLen, scale3); 148 149 if ((tmp2W32>0)&&(ener_comp>0)) { 150 /* norm energies to int16_t, compute the product of the energies and 151 use the upper int16_t as the denominator */ 152 153 scale1=(int16_t)WebRtcSpl_NormW32(tmp2W32)-16; 154 tmp1=(int16_t)WEBRTC_SPL_SHIFT_W32(tmp2W32, scale1); 155 156 scale2=(int16_t)WebRtcSpl_NormW32(ener)-16; 157 tmp2=(int16_t)WEBRTC_SPL_SHIFT_W32(ener, scale2); 158 denom=(int16_t)WEBRTC_SPL_MUL_16_16_RSFT(tmp1, tmp2, 16); /* denom in Q(scale1+scale2-16) */ 159 160 /* Square the cross correlation and norm it such that max_perSquare 161 will be in Q15 after the division */ 162 163 totscale = scale1+scale2-1; 164 tmp1 = (int16_t)WEBRTC_SPL_SHIFT_W32(cross, (totscale>>1)); 165 tmp2 = (int16_t)WEBRTC_SPL_SHIFT_W32(cross, totscale-(totscale>>1)); 166 167 nom = WEBRTC_SPL_MUL_16_16(tmp1, tmp2); 168 max_perSquare = (int16_t)WebRtcSpl_DivW32W16(nom, denom); 169 170 } else { 171 max_perSquare = 0; 172 } 173 } 174 175 /* previous frame lost, use recorded lag and gain */ 176 177 else { 178 lag = iLBCdec_inst->prevLag; 179 max_perSquare = iLBCdec_inst->perSquare; 180 } 181 182 /* Attenuate signal and scale down pitch pred gain if 183 several frames lost consecutively */ 184 185 use_gain = 32767; /* 1.0 in Q15 */ 186 187 if (iLBCdec_inst->consPLICount*iLBCdec_inst->blockl>320) { 188 use_gain = 29491; /* 0.9 in Q15 */ 189 } else if (iLBCdec_inst->consPLICount*iLBCdec_inst->blockl>640) { 190 use_gain = 22938; /* 0.7 in Q15 */ 191 } else if (iLBCdec_inst->consPLICount*iLBCdec_inst->blockl>960) { 192 use_gain = 16384; /* 0.5 in Q15 */ 193 } else if (iLBCdec_inst->consPLICount*iLBCdec_inst->blockl>1280) { 194 use_gain = 0; /* 0.0 in Q15 */ 195 } 196 197 /* Compute mixing factor of picth repeatition and noise: 198 for max_per>0.7 set periodicity to 1.0 199 0.4<max_per<0.7 set periodicity to (maxper-0.4)/0.7-0.4) 200 max_per<0.4 set periodicity to 0.0 201 */ 202 203 if (max_perSquare>7868) { /* periodicity > 0.7 (0.7^4=0.2401 in Q15) */ 204 pitchfact = 32767; 205 } else if (max_perSquare>839) { /* 0.4 < periodicity < 0.7 (0.4^4=0.0256 in Q15) */ 206 /* find best index and interpolate from that */ 207 ind = 5; 208 while ((max_perSquare<WebRtcIlbcfix_kPlcPerSqr[ind])&&(ind>0)) { 209 ind--; 210 } 211 /* pitch fact is approximated by first order */ 212 tmpW32 = (int32_t)WebRtcIlbcfix_kPlcPitchFact[ind] + 213 WEBRTC_SPL_MUL_16_16_RSFT(WebRtcIlbcfix_kPlcPfSlope[ind], (max_perSquare-WebRtcIlbcfix_kPlcPerSqr[ind]), 11); 214 215 pitchfact = (int16_t)WEBRTC_SPL_MIN(tmpW32, 32767); /* guard against overflow */ 216 217 } else { /* periodicity < 0.4 */ 218 pitchfact = 0; 219 } 220 221 /* avoid repetition of same pitch cycle (buzzyness) */ 222 use_lag = lag; 223 if (lag<80) { 224 use_lag = 2*lag; 225 } 226 227 /* compute concealed residual */ 228 energy = 0; 229 230 for (i=0; i<iLBCdec_inst->blockl; i++) { 231 232 /* noise component - 52 < randlagFIX < 117 */ 233 iLBCdec_inst->seed = (int16_t)(WEBRTC_SPL_MUL_16_16(iLBCdec_inst->seed, 31821)+(int32_t)13849); 234 randlag = 53 + (int16_t)(iLBCdec_inst->seed & 63); 235 236 pick = i - randlag; 237 238 if (pick < 0) { 239 randvec[i] = iLBCdec_inst->prevResidual[iLBCdec_inst->blockl+pick]; 240 } else { 241 randvec[i] = iLBCdec_inst->prevResidual[pick]; 242 } 243 244 /* pitch repeatition component */ 245 pick = i - use_lag; 246 247 if (pick < 0) { 248 PLCresidual[i] = iLBCdec_inst->prevResidual[iLBCdec_inst->blockl+pick]; 249 } else { 250 PLCresidual[i] = PLCresidual[pick]; 251 } 252 253 /* Attinuate total gain for each 10 ms */ 254 if (i<80) { 255 tot_gain=use_gain; 256 } else if (i<160) { 257 tot_gain=(int16_t)WEBRTC_SPL_MUL_16_16_RSFT(31130, use_gain, 15); /* 0.95*use_gain */ 258 } else { 259 tot_gain=(int16_t)WEBRTC_SPL_MUL_16_16_RSFT(29491, use_gain, 15); /* 0.9*use_gain */ 260 } 261 262 263 /* mix noise and pitch repeatition */ 264 265 PLCresidual[i] = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(tot_gain, 266 (int16_t)WEBRTC_SPL_RSHIFT_W32( (WEBRTC_SPL_MUL_16_16(pitchfact, PLCresidual[i]) + 267 WEBRTC_SPL_MUL_16_16((32767-pitchfact), randvec[i]) + 16384), 268 15), 269 15); 270 271 /* Shifting down the result one step extra to ensure that no overflow 272 will occur */ 273 energy += WEBRTC_SPL_MUL_16_16_RSFT(PLCresidual[i], 274 PLCresidual[i], (iLBCdec_inst->prevScale+1)); 275 276 } 277 278 /* less than 30 dB, use only noise */ 279 if (energy < (WEBRTC_SPL_SHIFT_W32(((int32_t)iLBCdec_inst->blockl*900),-(iLBCdec_inst->prevScale+1)))) { 280 energy = 0; 281 for (i=0; i<iLBCdec_inst->blockl; i++) { 282 PLCresidual[i] = randvec[i]; 283 } 284 } 285 286 /* use the old LPC */ 287 WEBRTC_SPL_MEMCPY_W16(PLClpc, (*iLBCdec_inst).prevLpc, LPC_FILTERORDER+1); 288 289 /* Update state in case there are multiple frame losses */ 290 iLBCdec_inst->prevLag = lag; 291 iLBCdec_inst->perSquare = max_perSquare; 292 } 293 294 /* no packet loss, copy input */ 295 296 else { 297 WEBRTC_SPL_MEMCPY_W16(PLCresidual, decresidual, iLBCdec_inst->blockl); 298 WEBRTC_SPL_MEMCPY_W16(PLClpc, lpc, (LPC_FILTERORDER+1)); 299 iLBCdec_inst->consPLICount = 0; 300 } 301 302 /* update state */ 303 iLBCdec_inst->prevPLI = PLI; 304 WEBRTC_SPL_MEMCPY_W16(iLBCdec_inst->prevLpc, PLClpc, (LPC_FILTERORDER+1)); 305 WEBRTC_SPL_MEMCPY_W16(iLBCdec_inst->prevResidual, PLCresidual, iLBCdec_inst->blockl); 306 307 return; 308 } 309