aboutsummaryrefslogtreecommitdiffstats
path: root/trunk/codecs/ilbc/doCPLC.c
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/codecs/ilbc/doCPLC.c')
-rw-r--r--trunk/codecs/ilbc/doCPLC.c259
1 files changed, 259 insertions, 0 deletions
diff --git a/trunk/codecs/ilbc/doCPLC.c b/trunk/codecs/ilbc/doCPLC.c
new file mode 100644
index 000000000..bb4b56c10
--- /dev/null
+++ b/trunk/codecs/ilbc/doCPLC.c
@@ -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"
+#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 *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));
+}
+
+
+
+