📄 docplc.cxx
字号:
//A.14 doCPLC.c /****************************************************************** iLBC Speech Coder ANSI-C Source Code doCPLC.c Copyright (c) 2001, Global IP Sound AB. All rights reserved. ******************************************************************/ #include <math.h> #include <string.h> #include"iLBC_define.h" /*----------------------------------------------------------------* * Compute cross correlation and pitch gain for pitch prediction * of last subframe at given lag. *---------------------------------------------------------------*/ void compCorr( float *cc, /* (o) cross correlation coefficient */ float *gc, /* (o) gain */ float *buffer, /* (i) signal buffer */ int lag, /* (i) pitch lag */ int bLen, /* (i) length of buffer */ int sRange /* (i) correlation search length */ ){ int i; float ftmp1, ftmp2; ftmp1 = 0.0; ftmp2 = 0.0; for (i=0; i<sRange; i++) { ftmp1 += buffer[bLen-sRange+i] * buffer[bLen-sRange+i-lag]; ftmp2 += buffer[bLen-sRange+i-lag] * buffer[bLen-sRange+i-lag]; } if (ftmp2 > 0.0) { *cc = ftmp1*ftmp1/ftmp2; *gc = (float)fabs(ftmp1/ftmp2); } else { *cc = 0.0; *gc = 0.0; } } /*----------------------------------------------------------------* * Packet loss concealment routine. Conceals a residual signal * and LP parameters. If no packet loss, update state. *---------------------------------------------------------------*/ void doThePLC( float *PLCresidual, /* (o) concealed residual */ float *PLClpc, /* (o) concealed LP parameters */ int PLI, /* (i) packet loss indicator 0 - no PL, 1 = PL */ float *decresidual, /* (i) decoded residual */ float *lpc, /* (i) decoded LPC (only used for no PL) */ int inlag, /* (i) pitch lag */ iLBC_Dec_Inst_t *iLBCdec_inst /* (i/o) decoder instance */ ){ int lag=20, randlag; float gain, maxcc; float gain_comp, maxcc_comp; int i, pick, offset; float ftmp, ftmp1, randvec[BLOCKL_MAX], pitchfact; /* Packet Loss */ if (PLI == 1) { (*iLBCdec_inst).consPLICount += 1; /* if previous frame not lost, determine pitch pred. gain */ if ((*iLBCdec_inst).prevPLI != 1) { /* Search around the previous lag to find the best pitch period */ lag=inlag-3; compCorr(&maxcc, &gain, (*iLBCdec_inst).prevResidual, lag, BLOCKL, 60); for (i=inlag-2;i<=inlag+3;i++) { compCorr(&maxcc_comp, &gain_comp, (*iLBCdec_inst).prevResidual, i, BLOCKL, 60); if (maxcc_comp>maxcc) { maxcc=maxcc_comp; gain=gain_comp; lag=i; } } if (gain > 1.0) { gain = 1.0; } } /* previous frame lost, use recorded lag and gain */ else { lag=(*iLBCdec_inst).prevLag; gain=(*iLBCdec_inst).prevGain; } /* Attenuate signal and scale down pitch pred gain if several frames lost consecutively */ if ((*iLBCdec_inst).consPLICount > 1) { gain *= (float)0.9; } /* Compute mixing factor of picth repeatition and noise */ if (gain > PLC_XT_MIX) { pitchfact = PLC_YT_MIX; } else if (gain < PLC_XB_MIX) { pitchfact = PLC_YB_MIX; } else { pitchfact = PLC_YB_MIX + (gain - PLC_XB_MIX) * (PLC_YT_MIX-PLC_YB_MIX)/(PLC_XT_MIX-PLC_XB_MIX); } /* compute concealed residual */ (*iLBCdec_inst).energy = 0.0; for (i=0; i<BLOCKL; i++) { /* noise component */ (*iLBCdec_inst).seed=((*iLBCdec_inst).seed*69069L+1) & (0x80000000L-1); randlag = 50 + ((signed long) (*iLBCdec_inst).seed)%70; pick = i - randlag; if (pick < 0) { randvec[i] = gain * (*iLBCdec_inst).prevResidual[BLOCKL+pick]; } else { randvec[i] = gain * randvec[pick]; } /* pitch repeatition component */ pick = i - lag; if (pick < 0) { PLCresidual[i] = gain * (*iLBCdec_inst).prevResidual[BLOCKL+pick]; } else { PLCresidual[i] = gain * PLCresidual[pick]; } /* mix noise and pitch repeatition */ PLCresidual[i] = (pitchfact * PLCresidual[i] + ((float)1.0 - pitchfact) * randvec[i]); (*iLBCdec_inst).energy += PLCresidual[i] * PLCresidual[i]; } /* less than 30 dB, use only noise */ if (sqrt((*iLBCdec_inst).energy/(float)BLOCKL) < 30.0) { (*iLBCdec_inst).energy = 0.0; gain=0.0; for (i=0; i<BLOCKL; i++) { PLCresidual[i] = randvec[i]; (*iLBCdec_inst).energy += PLCresidual[i] * PLCresidual[i]; } } /* conceal LPC by bandwidth expansion of old LPC */ ftmp=PLC_BWEXPAND; PLClpc[0]=(float)1.0; for (i=1; i<LPC_FILTERORDER+1; i++) { PLClpc[i] = ftmp * (*iLBCdec_inst).prevLpc[i]; ftmp *= PLC_BWEXPAND; } } /* previous frame lost and this frame OK, mixing in with new frame */ else if ((*iLBCdec_inst).prevPLI == 1) { lag = (*iLBCdec_inst).prevLag; gain = (*iLBCdec_inst).prevGain; /* if pitch pred gain high, do overlap-add */ if (gain >= PLC_GAINTHRESHOLD) { /* Compute mixing factor of pitch repeatition and noise */ if (gain > PLC_XT_MIX) { pitchfact = PLC_YT_MIX; } else if (gain < PLC_XB_MIX) { pitchfact = PLC_YB_MIX; } else { pitchfact = PLC_YB_MIX + (gain - PLC_XB_MIX) * (PLC_YT_MIX-PLC_YB_MIX)/(PLC_XT_MIX-PLC_XB_MIX); } /* compute concealed residual for 3 subframes */ for (i=0; i<3*SUBL; i++) { (*iLBCdec_inst).seed=((*iLBCdec_inst).seed* 69069L+1) & (0x80000000L-1); randlag = 50 + ((signed long) (*iLBCdec_inst).seed)%70; /* noise component */ pick = i - randlag; if (pick < 0) { randvec[i] = gain * (*iLBCdec_inst).prevResidual[BLOCKL+pick]; } else { randvec[i] = gain * randvec[pick]; } /* pitch repeatition component */ pick = i - lag; if (pick < 0) { PLCresidual[i] = gain * (*iLBCdec_inst).prevResidual[BLOCKL+pick]; } else { PLCresidual[i] = gain * PLCresidual[pick]; } /* mix noise and pitch repeatition */ PLCresidual[i] = (pitchfact * PLCresidual[i] + ((float)1.0 - pitchfact) * randvec[i]); } /* interpolate concealed residual with actual residual */ offset = 3*SUBL; for (i=0; i<offset; i++) { ftmp1 = (float) (i+1) / (float) (offset+1); ftmp = (float)1.0 - ftmp1; PLCresidual[i]=PLCresidual[i]*ftmp+ decresidual[i]*ftmp1; } memcpy(PLCresidual+offset, decresidual+offset, (BLOCKL-offset)*sizeof(float)); } else { memcpy(PLCresidual, decresidual, BLOCKL*sizeof(float)); } /* copy LPC */ memcpy(PLClpc, lpc, (LPC_FILTERORDER+1)*sizeof(float)); (*iLBCdec_inst).consPLICount = 0; } /* no packet loss, copy input */ else { memcpy(PLCresidual, decresidual, BLOCKL*sizeof(float)); memcpy(PLClpc, lpc, (LPC_FILTERORDER+1)*sizeof(float)); } /* update state */ (*iLBCdec_inst).prevLag = lag; (*iLBCdec_inst).prevGain = gain; (*iLBCdec_inst).prevPLI = PLI; memcpy((*iLBCdec_inst).prevLpc, PLClpc, (LPC_FILTERORDER+1)*sizeof(float)); memcpy((*iLBCdec_inst).prevResidual, PLCresidual, BLOCKL*sizeof(float)); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -