diff intercom/ilbc/iLBC_encode.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/iLBC_encode.c	Fri Jun 25 09:57:52 2010 +0200
@@ -0,0 +1,507 @@
+
+   /******************************************************************
+
+       iLBC Speech Coder ANSI-C Source Code
+
+       iLBC_encode.c
+
+       Copyright (C) The Internet Society (2004).
+       All Rights Reserved.
+
+   ******************************************************************/
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "iLBC_define.h"
+#include "LPCencode.h"
+#include "FrameClassify.h"
+#include "StateSearchW.h"
+#include "StateConstructW.h"
+#include "helpfun.h"
+#include "constants.h"
+#include "packing.h"
+#include "iCBSearch.h"
+#include "iCBConstruct.h"
+#include "hpInput.h"
+#include "anaFilter.h"
+#include "syntFilter.h"
+
+   /*----------------------------------------------------------------*
+    *  Initiation of encoder instance.
+    *---------------------------------------------------------------*/
+
+short initEncode(               /* (o) Number of bytes
+                                   encoded */
+  iLBC_Enc_Inst_t * iLBCenc_inst,       /* (i/o) Encoder instance */
+  int mode                      /* (i) frame size mode */
+  )
+{
+  iLBCenc_inst->mode = mode;
+  if (mode == 30) {
+    iLBCenc_inst->blockl = BLOCKL_30MS;
+    iLBCenc_inst->nsub = NSUB_30MS;
+    iLBCenc_inst->nasub = NASUB_30MS;
+    iLBCenc_inst->lpc_n = LPC_N_30MS;
+    iLBCenc_inst->no_of_bytes = NO_OF_BYTES_30MS;
+    iLBCenc_inst->no_of_words = NO_OF_WORDS_30MS;
+
+
+
+
+
+    iLBCenc_inst->state_short_len = STATE_SHORT_LEN_30MS;
+    /* ULP init */
+    iLBCenc_inst->ULP_inst = &ULP_30msTbl;
+  } else if (mode == 20) {
+    iLBCenc_inst->blockl = BLOCKL_20MS;
+    iLBCenc_inst->nsub = NSUB_20MS;
+    iLBCenc_inst->nasub = NASUB_20MS;
+    iLBCenc_inst->lpc_n = LPC_N_20MS;
+    iLBCenc_inst->no_of_bytes = NO_OF_BYTES_20MS;
+    iLBCenc_inst->no_of_words = NO_OF_WORDS_20MS;
+    iLBCenc_inst->state_short_len = STATE_SHORT_LEN_20MS;
+    /* ULP init */
+    iLBCenc_inst->ULP_inst = &ULP_20msTbl;
+  } else {
+    exit(2);
+  }
+
+  memset((*iLBCenc_inst).anaMem, 0, LPC_FILTERORDER * sizeof(float));
+  memcpy((*iLBCenc_inst).lsfold, lsfmeanTbl,
+    LPC_FILTERORDER * sizeof(float));
+  memcpy((*iLBCenc_inst).lsfdeqold, lsfmeanTbl,
+    LPC_FILTERORDER * sizeof(float));
+  memset((*iLBCenc_inst).lpc_buffer, 0,
+    (LPC_LOOKBACK + BLOCKL_MAX) * sizeof(float));
+  memset((*iLBCenc_inst).hpimem, 0, 4 * sizeof(float));
+
+  return (iLBCenc_inst->no_of_bytes);
+}
+
+   /*----------------------------------------------------------------*
+    *  main encoder function
+    *---------------------------------------------------------------*/
+
+void iLBC_encode(unsigned char *bytes,  /* (o) encoded data bits iLBC */
+  float *block,                 /* (o) speech vector to
+                                   encode */
+  iLBC_Enc_Inst_t * iLBCenc_inst        /* (i/o) the general encoder
+                                           state */
+  )
+{
+
+  float data[BLOCKL_MAX];
+  float residual[BLOCKL_MAX], reverseResidual[BLOCKL_MAX];
+
+  int start, idxForMax, idxVec[STATE_LEN];
+
+
+
+
+
+  float reverseDecresidual[BLOCKL_MAX], mem[CB_MEML];
+  int n, k, meml_gotten, Nfor, Nback, i, pos;
+  int gain_index[CB_NSTAGES * NASUB_MAX], extra_gain_index[CB_NSTAGES];
+  int cb_index[CB_NSTAGES * NASUB_MAX], extra_cb_index[CB_NSTAGES];
+  int lsf_i[LSF_NSPLIT * LPC_N_MAX];
+  unsigned char *pbytes;
+  int diff, start_pos, state_first;
+  float en1, en2;
+  int index, ulp, firstpart;
+  int subcount, subframe;
+  float weightState[LPC_FILTERORDER];
+  float syntdenum[NSUB_MAX * (LPC_FILTERORDER + 1)];
+  float weightdenum[NSUB_MAX * (LPC_FILTERORDER + 1)];
+  float decresidual[BLOCKL_MAX];
+
+  /* high pass filtering of input signal if such is not done
+     prior to calling this function */
+
+  hpInput(block, iLBCenc_inst->blockl, data, (*iLBCenc_inst).hpimem);
+
+  /* otherwise simply copy */
+
+  /*memcpy(data,block,iLBCenc_inst->blockl*sizeof(float)); */
+
+  /* LPC of hp filtered input data */
+
+  LPCencode(syntdenum, weightdenum, lsf_i, data, iLBCenc_inst);
+
+
+  /* inverse filter to get residual */
+
+  for (n = 0; n < iLBCenc_inst->nsub; n++) {
+    anaFilter(&data[n * SUBL], &syntdenum[n * (LPC_FILTERORDER + 1)],
+      SUBL, &residual[n * SUBL], iLBCenc_inst->anaMem);
+  }
+
+  /* find state location */
+
+  start = FrameClassify(iLBCenc_inst, residual);
+
+  /* check if state should be in first or last part of the
+     two subframes */
+
+  diff = STATE_LEN - iLBCenc_inst->state_short_len;
+  en1 = 0;
+  index = (start - 1) * SUBL;
+
+
+
+
+
+  for (i = 0; i < iLBCenc_inst->state_short_len; i++) {
+    en1 += residual[index + i] * residual[index + i];
+  }
+  en2 = 0;
+  index = (start - 1) * SUBL + diff;
+  for (i = 0; i < iLBCenc_inst->state_short_len; i++) {
+    en2 += residual[index + i] * residual[index + i];
+  }
+
+
+  if (en1 > en2) {
+    state_first = 1;
+    start_pos = (start - 1) * SUBL;
+  } else {
+    state_first = 0;
+    start_pos = (start - 1) * SUBL + diff;
+  }
+
+  /* scalar quantization of state */
+
+  StateSearchW(iLBCenc_inst, &residual[start_pos],
+    &syntdenum[(start - 1) * (LPC_FILTERORDER + 1)],
+    &weightdenum[(start - 1) * (LPC_FILTERORDER + 1)], &idxForMax,
+    idxVec, iLBCenc_inst->state_short_len, state_first);
+
+  StateConstructW(idxForMax, idxVec,
+    &syntdenum[(start - 1) * (LPC_FILTERORDER + 1)],
+    &decresidual[start_pos], iLBCenc_inst->state_short_len);
+
+  /* predictive quantization in state */
+
+  if (state_first) {            /* put adaptive part in the end */
+
+    /* setup memory */
+
+    memset(mem, 0,
+      (CB_MEML - iLBCenc_inst->state_short_len) * sizeof(float));
+    memcpy(mem + CB_MEML - iLBCenc_inst->state_short_len,
+      decresidual + start_pos,
+      iLBCenc_inst->state_short_len * sizeof(float));
+    memset(weightState, 0, LPC_FILTERORDER * sizeof(float));
+
+    /* encode sub-frames */
+
+    iCBSearch(iLBCenc_inst, extra_cb_index, extra_gain_index,
+      &residual[start_pos + iLBCenc_inst->state_short_len],
+      mem + CB_MEML - stMemLTbl,
+      stMemLTbl, diff, CB_NSTAGES,
+      &weightdenum[start * (LPC_FILTERORDER + 1)], weightState, 0);
+
+    /* construct decoded vector */
+
+    iCBConstruct(&decresidual[start_pos +
+        iLBCenc_inst->state_short_len], extra_cb_index,
+      extra_gain_index, mem + CB_MEML - stMemLTbl, stMemLTbl, diff,
+      CB_NSTAGES);
+
+  } else {                      /* put adaptive part in the beginning */
+
+    /* create reversed vectors for prediction */
+
+    for (k = 0; k < diff; k++) {
+      reverseResidual[k] = residual[(start + 1) * SUBL - 1
+        - (k + iLBCenc_inst->state_short_len)];
+    }
+
+    /* setup memory */
+
+    meml_gotten = iLBCenc_inst->state_short_len;
+    for (k = 0; k < meml_gotten; k++) {
+      mem[CB_MEML - 1 - k] = decresidual[start_pos + k];
+    }
+    memset(mem, 0, (CB_MEML - k) * sizeof(float));
+    memset(weightState, 0, LPC_FILTERORDER * sizeof(float));
+
+    /* encode sub-frames */
+
+    iCBSearch(iLBCenc_inst, extra_cb_index, extra_gain_index,
+      reverseResidual, mem + CB_MEML - stMemLTbl, stMemLTbl,
+      diff, CB_NSTAGES,
+      &weightdenum[(start - 1) * (LPC_FILTERORDER + 1)],
+      weightState, 0);
+
+    /* construct decoded vector */
+
+    iCBConstruct(reverseDecresidual, extra_cb_index,
+      extra_gain_index, mem + CB_MEML - stMemLTbl, stMemLTbl,
+      diff, CB_NSTAGES);
+
+    /* get decoded residual from reversed vector */
+
+    for (k = 0; k < diff; k++) {
+      decresidual[start_pos - 1 - k] = reverseDecresidual[k];
+
+
+
+
+
+    }
+  }
+
+  /* counter for predicted sub-frames */
+
+  subcount = 0;
+
+  /* forward prediction of sub-frames */
+
+  Nfor = iLBCenc_inst->nsub - start - 1;
+
+
+  if (Nfor > 0) {
+
+    /* setup memory */
+
+    memset(mem, 0, (CB_MEML - STATE_LEN) * sizeof(float));
+    memcpy(mem + CB_MEML - STATE_LEN, decresidual + (start - 1) * SUBL,
+      STATE_LEN * sizeof(float));
+    memset(weightState, 0, LPC_FILTERORDER * sizeof(float));
+
+    /* loop over sub-frames to encode */
+
+    for (subframe = 0; subframe < Nfor; subframe++) {
+
+      /* encode sub-frame */
+
+      iCBSearch(iLBCenc_inst, cb_index + subcount * CB_NSTAGES,
+        gain_index + subcount * CB_NSTAGES,
+        &residual[(start + 1 + subframe) * SUBL],
+        mem + CB_MEML - memLfTbl[subcount],
+        memLfTbl[subcount], SUBL, CB_NSTAGES,
+        &weightdenum[(start + 1 + subframe) *
+          (LPC_FILTERORDER + 1)], weightState, subcount + 1);
+
+      /* construct decoded vector */
+
+      iCBConstruct(&decresidual[(start + 1 + subframe) * SUBL],
+        cb_index + subcount * CB_NSTAGES,
+        gain_index + subcount * CB_NSTAGES,
+        mem + CB_MEML - memLfTbl[subcount],
+        memLfTbl[subcount], SUBL, CB_NSTAGES);
+
+      /* update memory */
+
+      memcpy(mem, mem + SUBL, (CB_MEML - SUBL) * sizeof(float));
+      memcpy(mem + CB_MEML - SUBL,
+        &decresidual[(start + 1 + subframe) * SUBL],
+        SUBL * sizeof(float));
+      memset(weightState, 0, LPC_FILTERORDER * sizeof(float));
+
+      subcount++;
+    }
+  }
+
+
+  /* backward prediction of sub-frames */
+
+  Nback = start - 1;
+
+
+  if (Nback > 0) {
+
+    /* create reverse order vectors */
+
+    for (n = 0; n < Nback; n++) {
+      for (k = 0; k < SUBL; k++) {
+        reverseResidual[n * SUBL + k] =
+          residual[(start - 1) * SUBL - 1 - n * SUBL - k];
+        reverseDecresidual[n * SUBL + k] =
+          decresidual[(start - 1) * SUBL - 1 - n * SUBL - k];
+      }
+    }
+
+    /* setup memory */
+
+    meml_gotten = SUBL * (iLBCenc_inst->nsub + 1 - start);
+
+
+    if (meml_gotten > CB_MEML) {
+      meml_gotten = CB_MEML;
+    }
+    for (k = 0; k < meml_gotten; k++) {
+      mem[CB_MEML - 1 - k] = decresidual[(start - 1) * SUBL + k];
+    }
+    memset(mem, 0, (CB_MEML - k) * sizeof(float));
+    memset(weightState, 0, LPC_FILTERORDER * sizeof(float));
+
+    /* loop over sub-frames to encode */
+
+    for (subframe = 0; subframe < Nback; subframe++) {
+
+      /* encode sub-frame */
+
+      iCBSearch(iLBCenc_inst, cb_index + subcount * CB_NSTAGES,
+        gain_index + subcount * CB_NSTAGES,
+        &reverseResidual[subframe * SUBL],
+        mem + CB_MEML - memLfTbl[subcount],
+        memLfTbl[subcount], SUBL, CB_NSTAGES,
+        &weightdenum[(start - 2 - subframe) *
+          (LPC_FILTERORDER + 1)], weightState, subcount + 1);
+
+      /* construct decoded vector */
+
+      iCBConstruct(&reverseDecresidual[subframe * SUBL],
+        cb_index + subcount * CB_NSTAGES,
+        gain_index + subcount * CB_NSTAGES,
+        mem + CB_MEML - memLfTbl[subcount],
+        memLfTbl[subcount], SUBL, CB_NSTAGES);
+
+      /* update memory */
+
+      memcpy(mem, mem + SUBL, (CB_MEML - SUBL) * sizeof(float));
+      memcpy(mem + CB_MEML - SUBL,
+        &reverseDecresidual[subframe * SUBL], SUBL * sizeof(float));
+      memset(weightState, 0, LPC_FILTERORDER * sizeof(float));
+
+      subcount++;
+
+    }
+
+    /* get decoded residual from reversed vector */
+
+    for (i = 0; i < SUBL * Nback; i++) {
+      decresidual[SUBL * Nback - i - 1] = reverseDecresidual[i];
+    }
+  }
+  /* end encoding part */
+
+  /* adjust index */
+  index_conv_enc(cb_index);
+
+  /* pack bytes */
+
+  pbytes = bytes;
+  pos = 0;
+
+  /* loop over the 3 ULP classes */
+
+  for (ulp = 0; ulp < 3; ulp++) {
+
+
+
+
+
+
+    /* LSF */
+    for (k = 0; k < LSF_NSPLIT * iLBCenc_inst->lpc_n; k++) {
+      packsplit(&lsf_i[k], &firstpart, &lsf_i[k],
+        iLBCenc_inst->ULP_inst->lsf_bits[k][ulp],
+        iLBCenc_inst->ULP_inst->lsf_bits[k][ulp] +
+        iLBCenc_inst->ULP_inst->lsf_bits[k][ulp + 1] +
+        iLBCenc_inst->ULP_inst->lsf_bits[k][ulp + 2]);
+      dopack(&pbytes, firstpart,
+        iLBCenc_inst->ULP_inst->lsf_bits[k][ulp], &pos);
+    }
+
+    /* Start block info */
+
+    packsplit(&start, &firstpart, &start,
+      iLBCenc_inst->ULP_inst->start_bits[ulp],
+      iLBCenc_inst->ULP_inst->start_bits[ulp] +
+      iLBCenc_inst->ULP_inst->start_bits[ulp + 1] +
+      iLBCenc_inst->ULP_inst->start_bits[ulp + 2]);
+    dopack(&pbytes, firstpart,
+      iLBCenc_inst->ULP_inst->start_bits[ulp], &pos);
+
+    packsplit(&state_first, &firstpart, &state_first,
+      iLBCenc_inst->ULP_inst->startfirst_bits[ulp],
+      iLBCenc_inst->ULP_inst->startfirst_bits[ulp] +
+      iLBCenc_inst->ULP_inst->startfirst_bits[ulp + 1] +
+      iLBCenc_inst->ULP_inst->startfirst_bits[ulp + 2]);
+    dopack(&pbytes, firstpart,
+      iLBCenc_inst->ULP_inst->startfirst_bits[ulp], &pos);
+
+    packsplit(&idxForMax, &firstpart, &idxForMax,
+      iLBCenc_inst->ULP_inst->scale_bits[ulp],
+      iLBCenc_inst->ULP_inst->scale_bits[ulp] +
+      iLBCenc_inst->ULP_inst->scale_bits[ulp + 1] +
+      iLBCenc_inst->ULP_inst->scale_bits[ulp + 2]);
+    dopack(&pbytes, firstpart,
+      iLBCenc_inst->ULP_inst->scale_bits[ulp], &pos);
+
+    for (k = 0; k < iLBCenc_inst->state_short_len; k++) {
+      packsplit(idxVec + k, &firstpart, idxVec + k,
+        iLBCenc_inst->ULP_inst->state_bits[ulp],
+        iLBCenc_inst->ULP_inst->state_bits[ulp] +
+        iLBCenc_inst->ULP_inst->state_bits[ulp + 1] +
+        iLBCenc_inst->ULP_inst->state_bits[ulp + 2]);
+      dopack(&pbytes, firstpart,
+        iLBCenc_inst->ULP_inst->state_bits[ulp], &pos);
+    }
+
+
+
+
+
+
+    /* 23/22 (20ms/30ms) sample block */
+
+    for (k = 0; k < CB_NSTAGES; k++) {
+      packsplit(extra_cb_index + k, &firstpart,
+        extra_cb_index + k,
+        iLBCenc_inst->ULP_inst->extra_cb_index[k][ulp],
+        iLBCenc_inst->ULP_inst->extra_cb_index[k][ulp] +
+        iLBCenc_inst->ULP_inst->extra_cb_index[k][ulp + 1] +
+        iLBCenc_inst->ULP_inst->extra_cb_index[k][ulp + 2]);
+      dopack(&pbytes, firstpart,
+        iLBCenc_inst->ULP_inst->extra_cb_index[k][ulp], &pos);
+    }
+
+    for (k = 0; k < CB_NSTAGES; k++) {
+      packsplit(extra_gain_index + k, &firstpart,
+        extra_gain_index + k,
+        iLBCenc_inst->ULP_inst->extra_cb_gain[k][ulp],
+        iLBCenc_inst->ULP_inst->extra_cb_gain[k][ulp] +
+        iLBCenc_inst->ULP_inst->extra_cb_gain[k][ulp + 1] +
+        iLBCenc_inst->ULP_inst->extra_cb_gain[k][ulp + 2]);
+      dopack(&pbytes, firstpart,
+        iLBCenc_inst->ULP_inst->extra_cb_gain[k][ulp], &pos);
+    }
+
+    /* The two/four (20ms/30ms) 40 sample sub-blocks */
+
+    for (i = 0; i < iLBCenc_inst->nasub; i++) {
+      for (k = 0; k < CB_NSTAGES; k++) {
+        packsplit(cb_index + i * CB_NSTAGES + k, &firstpart,
+          cb_index + i * CB_NSTAGES + k,
+          iLBCenc_inst->ULP_inst->cb_index[i][k][ulp],
+          iLBCenc_inst->ULP_inst->cb_index[i][k][ulp] +
+          iLBCenc_inst->ULP_inst->cb_index[i][k][ulp + 1] +
+          iLBCenc_inst->ULP_inst->cb_index[i][k][ulp + 2]);
+        dopack(&pbytes, firstpart,
+          iLBCenc_inst->ULP_inst->cb_index[i][k][ulp], &pos);
+      }
+    }
+
+    for (i = 0; i < iLBCenc_inst->nasub; i++) {
+      for (k = 0; k < CB_NSTAGES; k++) {
+        packsplit(gain_index + i * CB_NSTAGES + k, &firstpart,
+          gain_index + i * CB_NSTAGES + k,
+          iLBCenc_inst->ULP_inst->cb_gain[i][k][ulp],
+          iLBCenc_inst->ULP_inst->cb_gain[i][k][ulp] +
+          iLBCenc_inst->ULP_inst->cb_gain[i][k][ulp + 1] +
+          iLBCenc_inst->ULP_inst->cb_gain[i][k][ulp + 2]);
+        dopack(&pbytes, firstpart,
+          iLBCenc_inst->ULP_inst->cb_gain[i][k][ulp], &pos);
+      }
+    }
+  }
+
+  /* set the last bit to zero (otherwise the decoder
+     will treat it as a lost frame) */
+  dopack(&pbytes, 0, 1, &pos);
+}

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