aboutsummaryrefslogtreecommitdiffstats
path: root/trunk/codecs/ilbc/iLBC_decode.c
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/codecs/ilbc/iLBC_decode.c')
-rw-r--r--trunk/codecs/ilbc/iLBC_decode.c619
1 files changed, 619 insertions, 0 deletions
diff --git a/trunk/codecs/ilbc/iLBC_decode.c b/trunk/codecs/ilbc/iLBC_decode.c
new file mode 100644
index 000000000..22bfff792
--- /dev/null
+++ b/trunk/codecs/ilbc/iLBC_decode.c
@@ -0,0 +1,619 @@
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ iLBC_decode.c
+
+ Copyright (C) The Internet Society (2004).
+ All Rights Reserved.
+
+******************************************************************/
+
+#include <math.h>
+#include <stdlib.h>
+
+#include "iLBC_define.h"
+#include "iLBC_decode.h"
+#include "StateConstructW.h"
+#include "LPCdecode.h"
+#include "iCBConstruct.h"
+#include "doCPLC.h"
+#include "helpfun.h"
+#include "constants.h"
+#include "packing.h"
+#include "string.h"
+#include "enhancer.h"
+#include "hpOutput.h"
+#include "syntFilter.h"
+
+/*----------------------------------------------------------------*
+ * Initiation of decoder instance.
+ *---------------------------------------------------------------*/
+
+short initDecode( /* (o) Number of decoded
+ samples */
+ iLBC_Dec_Inst_t *iLBCdec_inst, /* (i/o) Decoder instance */
+ int mode, /* (i) frame size mode */
+ int use_enhancer /* (i) 1 to use enhancer
+ 0 to run without
+ enhancer */
+){
+ int i;
+
+ iLBCdec_inst->mode = mode;
+
+ if (mode==30) {
+ iLBCdec_inst->blockl = BLOCKL_30MS;
+ iLBCdec_inst->nsub = NSUB_30MS;
+ iLBCdec_inst->nasub = NASUB_30MS;
+ iLBCdec_inst->lpc_n = LPC_N_30MS;
+
+
+ iLBCdec_inst->no_of_bytes = NO_OF_BYTES_30MS;
+ iLBCdec_inst->no_of_words = NO_OF_WORDS_30MS;
+ iLBCdec_inst->state_short_len=STATE_SHORT_LEN_30MS;
+ /* ULP init */
+ iLBCdec_inst->ULP_inst=&ULP_30msTbl;
+ }
+ else if (mode==20) {
+ iLBCdec_inst->blockl = BLOCKL_20MS;
+ iLBCdec_inst->nsub = NSUB_20MS;
+ iLBCdec_inst->nasub = NASUB_20MS;
+ iLBCdec_inst->lpc_n = LPC_N_20MS;
+ iLBCdec_inst->no_of_bytes = NO_OF_BYTES_20MS;
+ iLBCdec_inst->no_of_words = NO_OF_WORDS_20MS;
+ iLBCdec_inst->state_short_len=STATE_SHORT_LEN_20MS;
+ /* ULP init */
+ iLBCdec_inst->ULP_inst=&ULP_20msTbl;
+ }
+ else {
+ exit(2);
+ }
+
+ memset(iLBCdec_inst->syntMem, 0,
+ LPC_FILTERORDER*sizeof(float));
+ memcpy((*iLBCdec_inst).lsfdeqold, lsfmeanTbl,
+ LPC_FILTERORDER*sizeof(float));
+
+ memset(iLBCdec_inst->old_syntdenum, 0,
+ ((LPC_FILTERORDER + 1)*NSUB_MAX)*sizeof(float));
+ for (i=0; i<NSUB_MAX; i++)
+ iLBCdec_inst->old_syntdenum[i*(LPC_FILTERORDER+1)]=1.0;
+
+ iLBCdec_inst->last_lag = 20;
+
+ iLBCdec_inst->prevLag = 120;
+ iLBCdec_inst->per = 0.0;
+ iLBCdec_inst->consPLICount = 0;
+ iLBCdec_inst->prevPLI = 0;
+ iLBCdec_inst->prevLpc[0] = 1.0;
+ memset(iLBCdec_inst->prevLpc+1,0,
+ LPC_FILTERORDER*sizeof(float));
+ memset(iLBCdec_inst->prevResidual, 0, BLOCKL_MAX*sizeof(float));
+ iLBCdec_inst->seed=777;
+
+ memset(iLBCdec_inst->hpomem, 0, 4*sizeof(float));
+
+ iLBCdec_inst->use_enhancer = use_enhancer;
+ memset(iLBCdec_inst->enh_buf, 0, ENH_BUFL*sizeof(float));
+ for (i=0;i<ENH_NBLOCKS_TOT;i++)
+ iLBCdec_inst->enh_period[i]=(float)40.0;
+
+ iLBCdec_inst->prev_enh_pl = 0;
+
+ return (iLBCdec_inst->blockl);
+}
+
+
+
+/*----------------------------------------------------------------*
+ * frame residual decoder function (subrutine to iLBC_decode)
+ *---------------------------------------------------------------*/
+
+static void Decode(
+ iLBC_Dec_Inst_t *iLBCdec_inst, /* (i/o) the decoder state
+ structure */
+ float *decresidual, /* (o) decoded residual frame */
+ int start, /* (i) location of start
+ state */
+ int idxForMax, /* (i) codebook index for the
+ maximum value */
+ int *idxVec, /* (i) codebook indexes for the
+ samples in the start
+ state */
+ float *syntdenum, /* (i) the decoded synthesis
+ filter coefficients */
+ int *cb_index, /* (i) the indexes for the
+ adaptive codebook */
+ int *gain_index, /* (i) the indexes for the
+ corresponding gains */
+ int *extra_cb_index, /* (i) the indexes for the
+ adaptive codebook part
+ of start state */
+ int *extra_gain_index, /* (i) the indexes for the
+ corresponding gains */
+ int state_first /* (i) 1 if non adaptive part
+ of start state comes
+ first 0 if that part
+ comes last */
+){
+ float reverseDecresidual[BLOCKL_MAX], mem[CB_MEML];
+ int k, meml_gotten, Nfor, Nback, i;
+ int diff, start_pos;
+ int subcount, subframe;
+
+ diff = STATE_LEN - iLBCdec_inst->state_short_len;
+
+ if (state_first == 1) {
+ start_pos = (start-1)*SUBL;
+ } else {
+ start_pos = (start-1)*SUBL + diff;
+ }
+
+ /* decode scalar part of start state */
+
+ StateConstructW(idxForMax, idxVec,
+ &syntdenum[(start-1)*(LPC_FILTERORDER+1)],
+ &decresidual[start_pos], iLBCdec_inst->state_short_len);
+
+
+ if (state_first) { /* put adaptive part in the end */
+
+
+
+ /* setup memory */
+
+ memset(mem, 0,
+ (CB_MEML-iLBCdec_inst->state_short_len)*sizeof(float));
+ memcpy(mem+CB_MEML-iLBCdec_inst->state_short_len,
+ decresidual+start_pos,
+ iLBCdec_inst->state_short_len*sizeof(float));
+
+ /* construct decoded vector */
+
+ iCBConstruct(
+ &decresidual[start_pos+iLBCdec_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++) {
+ reverseDecresidual[k] =
+ decresidual[(start+1)*SUBL-1-
+ (k+iLBCdec_inst->state_short_len)];
+ }
+
+ /* setup memory */
+
+ meml_gotten = iLBCdec_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));
+
+ /* 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 = iLBCdec_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));
+
+ /* loop over sub-frames to encode */
+
+ for (subframe=0; subframe<Nfor; subframe++) {
+
+ /* 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 */
+
+ memmove(mem, mem+SUBL, (CB_MEML-SUBL)*sizeof(float));
+ memcpy(mem+CB_MEML-SUBL,
+ &decresidual[(start+1+subframe)*SUBL],
+ SUBL*sizeof(float));
+
+ subcount++;
+
+ }
+
+ }
+
+ /* backward prediction of sub-frames */
+
+ Nback = start-1;
+
+ if ( Nback > 0 ) {
+
+ /* setup memory */
+
+ meml_gotten = SUBL*(iLBCdec_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));
+
+ /* loop over subframes to decode */
+
+
+
+ for (subframe=0; subframe<Nback; subframe++) {
+
+ /* 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 */
+
+ memmove(mem, mem+SUBL, (CB_MEML-SUBL)*sizeof(float));
+ memcpy(mem+CB_MEML-SUBL,
+ &reverseDecresidual[subframe*SUBL],
+ SUBL*sizeof(float));
+
+ subcount++;
+ }
+
+ /* get decoded residual from reversed vector */
+
+ for (i=0; i<SUBL*Nback; i++)
+ decresidual[SUBL*Nback - i - 1] =
+ reverseDecresidual[i];
+ }
+}
+
+/*----------------------------------------------------------------*
+ * main decoder function
+ *---------------------------------------------------------------*/
+
+void iLBC_decode(
+ float *decblock, /* (o) decoded signal block */
+ unsigned char *bytes, /* (i) encoded signal bits */
+ iLBC_Dec_Inst_t *iLBCdec_inst, /* (i/o) the decoder state
+ structure */
+ int mode /* (i) 0: bad packet, PLC,
+ 1: normal */
+){
+ float data[BLOCKL_MAX];
+ float lsfdeq[LPC_FILTERORDER*LPC_N_MAX];
+ float PLCresidual[BLOCKL_MAX], PLClpc[LPC_FILTERORDER + 1];
+ float zeros[BLOCKL_MAX], one[LPC_FILTERORDER + 1];
+ int k, i, start, idxForMax, pos, lastpart, ulp;
+ int lag, ilag;
+ float cc, maxcc;
+ int idxVec[STATE_LEN];
+ int check;
+ int gain_index[NASUB_MAX*CB_NSTAGES],
+ 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];
+ int state_first;
+
+
+ int last_bit;
+ unsigned char *pbytes;
+ float weightdenum[(LPC_FILTERORDER + 1)*NSUB_MAX];
+ int order_plus_one;
+ float syntdenum[NSUB_MAX*(LPC_FILTERORDER+1)];
+ float decresidual[BLOCKL_MAX];
+
+ if (mode>0) { /* the data are good */
+
+ /* decode data */
+
+ pbytes=bytes;
+ pos=0;
+
+ /* Set everything to zero before decoding */
+
+ for (k=0; k<LSF_NSPLIT*LPC_N_MAX; k++) {
+ lsf_i[k]=0;
+ }
+ start=0;
+ state_first=0;
+ idxForMax=0;
+ for (k=0; k<iLBCdec_inst->state_short_len; k++) {
+ idxVec[k]=0;
+ }
+ for (k=0; k<CB_NSTAGES; k++) {
+ extra_cb_index[k]=0;
+ }
+ for (k=0; k<CB_NSTAGES; k++) {
+ extra_gain_index[k]=0;
+ }
+ for (i=0; i<iLBCdec_inst->nasub; i++) {
+ for (k=0; k<CB_NSTAGES; k++) {
+ cb_index[i*CB_NSTAGES+k]=0;
+ }
+ }
+ for (i=0; i<iLBCdec_inst->nasub; i++) {
+ for (k=0; k<CB_NSTAGES; k++) {
+ gain_index[i*CB_NSTAGES+k]=0;
+ }
+ }
+
+ /* loop over ULP classes */
+
+ for (ulp=0; ulp<3; ulp++) {
+
+ /* LSF */
+ for (k=0; k<LSF_NSPLIT*iLBCdec_inst->lpc_n; k++){
+ unpack( &pbytes, &lastpart,
+ iLBCdec_inst->ULP_inst->lsf_bits[k][ulp], &pos);
+ packcombine(&lsf_i[k], lastpart,
+ iLBCdec_inst->ULP_inst->lsf_bits[k][ulp]);
+ }
+
+
+
+ /* Start block info */
+
+ unpack( &pbytes, &lastpart,
+ iLBCdec_inst->ULP_inst->start_bits[ulp], &pos);
+ packcombine(&start, lastpart,
+ iLBCdec_inst->ULP_inst->start_bits[ulp]);
+
+ unpack( &pbytes, &lastpart,
+ iLBCdec_inst->ULP_inst->startfirst_bits[ulp], &pos);
+ packcombine(&state_first, lastpart,
+ iLBCdec_inst->ULP_inst->startfirst_bits[ulp]);
+
+ unpack( &pbytes, &lastpart,
+ iLBCdec_inst->ULP_inst->scale_bits[ulp], &pos);
+ packcombine(&idxForMax, lastpart,
+ iLBCdec_inst->ULP_inst->scale_bits[ulp]);
+
+ for (k=0; k<iLBCdec_inst->state_short_len; k++) {
+ unpack( &pbytes, &lastpart,
+ iLBCdec_inst->ULP_inst->state_bits[ulp], &pos);
+ packcombine(idxVec+k, lastpart,
+ iLBCdec_inst->ULP_inst->state_bits[ulp]);
+ }
+
+ /* 23/22 (20ms/30ms) sample block */
+
+ for (k=0; k<CB_NSTAGES; k++) {
+ unpack( &pbytes, &lastpart,
+ iLBCdec_inst->ULP_inst->extra_cb_index[k][ulp],
+ &pos);
+ packcombine(extra_cb_index+k, lastpart,
+ iLBCdec_inst->ULP_inst->extra_cb_index[k][ulp]);
+ }
+ for (k=0; k<CB_NSTAGES; k++) {
+ unpack( &pbytes, &lastpart,
+ iLBCdec_inst->ULP_inst->extra_cb_gain[k][ulp],
+ &pos);
+ packcombine(extra_gain_index+k, lastpart,
+ iLBCdec_inst->ULP_inst->extra_cb_gain[k][ulp]);
+ }
+
+ /* The two/four (20ms/30ms) 40 sample sub-blocks */
+
+ for (i=0; i<iLBCdec_inst->nasub; i++) {
+ for (k=0; k<CB_NSTAGES; k++) {
+ unpack( &pbytes, &lastpart,
+ iLBCdec_inst->ULP_inst->cb_index[i][k][ulp],
+ &pos);
+ packcombine(cb_index+i*CB_NSTAGES+k, lastpart,
+ iLBCdec_inst->ULP_inst->cb_index[i][k][ulp]);
+ }
+ }
+
+ for (i=0; i<iLBCdec_inst->nasub; i++) {
+
+
+ for (k=0; k<CB_NSTAGES; k++) {
+ unpack( &pbytes, &lastpart,
+
+ iLBCdec_inst->ULP_inst->cb_gain[i][k][ulp],
+ &pos);
+ packcombine(gain_index+i*CB_NSTAGES+k, lastpart,
+ iLBCdec_inst->ULP_inst->cb_gain[i][k][ulp]);
+ }
+ }
+ }
+ /* Extract last bit. If it is 1 this indicates an
+ empty/lost frame */
+ unpack( &pbytes, &last_bit, 1, &pos);
+
+ /* Check for bit errors or empty/lost frames */
+ if (start<1)
+ mode = 0;
+ if (iLBCdec_inst->mode==20 && start>3)
+ mode = 0;
+ if (iLBCdec_inst->mode==30 && start>5)
+ mode = 0;
+ if (last_bit==1)
+ mode = 0;
+
+ if (mode==1) { /* No bit errors was detected,
+ continue decoding */
+
+ /* adjust index */
+ index_conv_dec(cb_index);
+
+ /* decode the lsf */
+
+ SimplelsfDEQ(lsfdeq, lsf_i, iLBCdec_inst->lpc_n);
+ check=LSF_check(lsfdeq, LPC_FILTERORDER,
+ iLBCdec_inst->lpc_n);
+ DecoderInterpolateLSF(syntdenum, weightdenum,
+ lsfdeq, LPC_FILTERORDER, iLBCdec_inst);
+
+ Decode(iLBCdec_inst, decresidual, start, idxForMax,
+ idxVec, syntdenum, cb_index, gain_index,
+ extra_cb_index, extra_gain_index,
+ state_first);
+
+ /* preparing the plc for a future loss! */
+
+ doThePLC(PLCresidual, PLClpc, 0, decresidual,
+ syntdenum +
+ (LPC_FILTERORDER + 1)*(iLBCdec_inst->nsub - 1),
+ (*iLBCdec_inst).last_lag, iLBCdec_inst);
+
+
+ memcpy(decresidual, PLCresidual,
+ iLBCdec_inst->blockl*sizeof(float));
+ }
+
+
+
+ }
+
+ if (mode == 0) {
+ /* the data is bad (either a PLC call
+ * was made or a severe bit error was detected)
+ */
+
+ /* packet loss conceal */
+
+ memset(zeros, 0, BLOCKL_MAX*sizeof(float));
+
+ one[0] = 1;
+ memset(one+1, 0, LPC_FILTERORDER*sizeof(float));
+
+ start=0;
+
+ doThePLC(PLCresidual, PLClpc, 1, zeros, one,
+ (*iLBCdec_inst).last_lag, iLBCdec_inst);
+ memcpy(decresidual, PLCresidual,
+ iLBCdec_inst->blockl*sizeof(float));
+
+ order_plus_one = LPC_FILTERORDER + 1;
+ for (i = 0; i < iLBCdec_inst->nsub; i++) {
+ memcpy(syntdenum+(i*order_plus_one), PLClpc,
+ order_plus_one*sizeof(float));
+ }
+ }
+
+ if (iLBCdec_inst->use_enhancer == 1) {
+
+ /* post filtering */
+
+ iLBCdec_inst->last_lag =
+ enhancerInterface(data, decresidual, iLBCdec_inst);
+
+ /* synthesis filtering */
+
+ if (iLBCdec_inst->mode==20) {
+ /* Enhancer has 40 samples delay */
+ i=0;
+ syntFilter(data + i*SUBL,
+ iLBCdec_inst->old_syntdenum +
+ (i+iLBCdec_inst->nsub-1)*(LPC_FILTERORDER+1),
+ SUBL, iLBCdec_inst->syntMem);
+ for (i=1; i < iLBCdec_inst->nsub; i++) {
+ syntFilter(data + i*SUBL,
+ syntdenum + (i-1)*(LPC_FILTERORDER+1),
+ SUBL, iLBCdec_inst->syntMem);
+ }
+ } else if (iLBCdec_inst->mode==30) {
+ /* Enhancer has 80 samples delay */
+ for (i=0; i < 2; i++) {
+ syntFilter(data + i*SUBL,
+
+
+ iLBCdec_inst->old_syntdenum +
+ (i+iLBCdec_inst->nsub-2)*(LPC_FILTERORDER+1),
+ SUBL, iLBCdec_inst->syntMem);
+ }
+ for (i=2; i < iLBCdec_inst->nsub; i++) {
+ syntFilter(data + i*SUBL,
+ syntdenum + (i-2)*(LPC_FILTERORDER+1), SUBL,
+ iLBCdec_inst->syntMem);
+ }
+ }
+
+ } else {
+
+ /* Find last lag */
+ lag = 20;
+ maxcc = xCorrCoef(&decresidual[BLOCKL_MAX-ENH_BLOCKL],
+ &decresidual[BLOCKL_MAX-ENH_BLOCKL-lag], ENH_BLOCKL);
+
+ for (ilag=21; ilag<120; ilag++) {
+ cc = xCorrCoef(&decresidual[BLOCKL_MAX-ENH_BLOCKL],
+ &decresidual[BLOCKL_MAX-ENH_BLOCKL-ilag],
+ ENH_BLOCKL);
+
+ if (cc > maxcc) {
+ maxcc = cc;
+ lag = ilag;
+ }
+ }
+ iLBCdec_inst->last_lag = lag;
+
+ /* copy data and run synthesis filter */
+
+ memcpy(data, decresidual,
+ iLBCdec_inst->blockl*sizeof(float));
+ for (i=0; i < iLBCdec_inst->nsub; i++) {
+ syntFilter(data + i*SUBL,
+ syntdenum + i*(LPC_FILTERORDER+1), SUBL,
+ iLBCdec_inst->syntMem);
+ }
+ }
+
+ /* high pass filtering on output if desired, otherwise
+ copy to out */
+
+ hpOutput(data, iLBCdec_inst->blockl,
+ decblock,iLBCdec_inst->hpomem);
+
+ /* memcpy(decblock,data,iLBCdec_inst->blockl*sizeof(float));*/
+
+ memcpy(iLBCdec_inst->old_syntdenum, syntdenum,
+
+ iLBCdec_inst->nsub*(LPC_FILTERORDER+1)*sizeof(float));
+
+ iLBCdec_inst->prev_enh_pl=0;
+
+
+
+ if (mode==0) { /* PLC was used */
+ iLBCdec_inst->prev_enh_pl=1;
+ }
+}
+
+