diff options
Diffstat (limited to 'codecs/ilbc/doCPLC.c')
-rwxr-xr-x | codecs/ilbc/doCPLC.c | 562 |
1 files changed, 258 insertions, 304 deletions
diff --git a/codecs/ilbc/doCPLC.c b/codecs/ilbc/doCPLC.c index 863d6e0ed..559c64344 100755 --- a/codecs/ilbc/doCPLC.c +++ b/codecs/ilbc/doCPLC.c @@ -1,304 +1,258 @@ - -/****************************************************************** - - 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" -#include "doCPLC.h" - -/*----------------------------------------------------------------* - * Compute cross correlation and pitch gain for pitch prediction - * of last subframe at given lag. - *---------------------------------------------------------------*/ - -static 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], 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)); -} - - + +/****************************************************************** + + iLBC Speech Coder ANSI-C Source Code + + doCPLC.c + + Copyright (C) The Internet Society (2004). + All Rights Reserved. + +******************************************************************/ + +#include <math.h> +#include <string.h> +#include <stdio.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 *pm, + 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, ftmp3; + + /* Guard against getting outside buffer */ + if ((bLen-sRange-lag)<0) { + sRange=bLen-lag; + } + + ftmp1 = 0.0; + ftmp2 = 0.0; + ftmp3 = 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]; + ftmp3 += buffer[bLen-sRange+i] * + buffer[bLen-sRange+i]; + } + + if (ftmp2 > 0.0) { + *cc = ftmp1*ftmp1/ftmp2; + *gc = (float)fabs(ftmp1/ftmp2); + *pm=(float)fabs(ftmp1)/ + ((float)sqrt(ftmp2)*(float)sqrt(ftmp3)); + } + else { + *cc = 0.0; + *gc = 0.0; + *pm=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 use_gain; + float gain_comp, maxcc_comp, per, max_per; + int i, pick, use_lag; + + + float ftmp, randvec[BLOCKL_MAX], pitchfact, energy; + + /* 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, &max_per, + iLBCdec_inst->prevResidual, + lag, iLBCdec_inst->blockl, 60); + for (i=inlag-2;i<=inlag+3;i++) { + compCorr(&maxcc_comp, &gain_comp, &per, + iLBCdec_inst->prevResidual, + i, iLBCdec_inst->blockl, 60); + + if (maxcc_comp>maxcc) { + maxcc=maxcc_comp; + gain=gain_comp; + lag=i; + max_per=per; + } + } + + } + + /* previous frame lost, use recorded lag and periodicity */ + + else { + lag=iLBCdec_inst->prevLag; + max_per=iLBCdec_inst->per; + } + + /* downscaling */ + + use_gain=1.0; + if (iLBCdec_inst->consPLICount*iLBCdec_inst->blockl>320) + use_gain=(float)0.9; + else if (iLBCdec_inst->consPLICount* + iLBCdec_inst->blockl>2*320) + use_gain=(float)0.7; + else if (iLBCdec_inst->consPLICount* + iLBCdec_inst->blockl>3*320) + use_gain=(float)0.5; + else if (iLBCdec_inst->consPLICount* + + + iLBCdec_inst->blockl>4*320) + use_gain=(float)0.0; + + /* mix noise and pitch repeatition */ + ftmp=(float)sqrt(max_per); + if (ftmp>(float)0.7) + pitchfact=(float)1.0; + else if (ftmp>(float)0.4) + pitchfact=(ftmp-(float)0.4)/((float)0.7-(float)0.4); + else + pitchfact=0.0; + + + /* avoid repetition of same pitch cycle */ + use_lag=lag; + if (lag<80) { + use_lag=2*lag; + } + + /* compute concealed residual */ + + energy = 0.0; + for (i=0; i<iLBCdec_inst->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] = + iLBCdec_inst->prevResidual[ + iLBCdec_inst->blockl+pick]; + } else { + randvec[i] = randvec[pick]; + } + + /* pitch repeatition component */ + pick = i - use_lag; + + if (pick < 0) { + PLCresidual[i] = + iLBCdec_inst->prevResidual[ + iLBCdec_inst->blockl+pick]; + } else { + PLCresidual[i] = PLCresidual[pick]; + } + + /* mix random and periodicity component */ + + if (i<80) + PLCresidual[i] = use_gain*(pitchfact * + + + PLCresidual[i] + + ((float)1.0 - pitchfact) * randvec[i]); + else if (i<160) + PLCresidual[i] = (float)0.95*use_gain*(pitchfact * + PLCresidual[i] + + ((float)1.0 - pitchfact) * randvec[i]); + else + PLCresidual[i] = (float)0.9*use_gain*(pitchfact * + PLCresidual[i] + + ((float)1.0 - pitchfact) * randvec[i]); + + energy += PLCresidual[i] * PLCresidual[i]; + } + + /* less than 30 dB, use only noise */ + + if (sqrt(energy/(float)iLBCdec_inst->blockl) < 30.0) { + gain=0.0; + for (i=0; i<iLBCdec_inst->blockl; i++) { + PLCresidual[i] = randvec[i]; + } + } + + /* use old LPC */ + + memcpy(PLClpc,iLBCdec_inst->prevLpc, + (LPC_FILTERORDER+1)*sizeof(float)); + + } + + /* no packet loss, copy input */ + + else { + memcpy(PLCresidual, decresidual, + iLBCdec_inst->blockl*sizeof(float)); + memcpy(PLClpc, lpc, (LPC_FILTERORDER+1)*sizeof(float)); + iLBCdec_inst->consPLICount = 0; + } + + /* update state */ + + if (PLI) { + iLBCdec_inst->prevLag = lag; + iLBCdec_inst->per=max_per; + } + + iLBCdec_inst->prevPLI = PLI; + memcpy(iLBCdec_inst->prevLpc, PLClpc, + (LPC_FILTERORDER+1)*sizeof(float)); + memcpy(iLBCdec_inst->prevResidual, PLCresidual, + iLBCdec_inst->blockl*sizeof(float)); +} + + + + |