Mercurial > hg > audiostuff
diff intercom/ilbc/doCPLC.c @ 2:13be24d74cd2
import intercom-0.4.1
author | Peter Meerwald <pmeerw@cosy.sbg.ac.at> |
---|---|
date | Fri, 25 Jun 2010 09:57:52 +0200 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/intercom/ilbc/doCPLC.c Fri Jun 25 09:57:52 2010 +0200 @@ -0,0 +1,259 @@ + + /****************************************************************** + + 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)); +}