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));
+}

Repositories maintained by Peter Meerwald, pmeerw@pmeerw.net.