Mercurial > hg > audiostuff
view intercom/ilbc/doCPLC.c @ 4:26cd8f1ef0b1
import spandsp-0.0.6pre17
author | Peter Meerwald <pmeerw@cosy.sbg.ac.at> |
---|---|
date | Fri, 25 Jun 2010 15:50:58 +0200 |
parents | 13be24d74cd2 |
children |
line wrap: on
line source
/****************************************************************** 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)); }