summaryrefslogtreecommitdiff
path: root/codecs/ilbc/iLBC_decode.c
diff options
context:
space:
mode:
authorMatthew Jordan <mjordan@digium.com>2012-01-18 21:06:29 +0000
committerMatthew Jordan <mjordan@digium.com>2012-01-18 21:06:29 +0000
commit16adf6de8c4e3bf7dbfb1960b7ba2e4e5400d1b2 (patch)
tree51ddec1e752656271970856e230a8312d9394446 /codecs/ilbc/iLBC_decode.c
parentf69fd136f4b43944e95769bf5774dd9d77246405 (diff)
Include iLBC source code for distribution with Asterisk
This patch includes the iLBC source code for distribution with Asterisk. Clarification regarding the iLBC source code was provided by Google, and the appropriate licenses have been included in the codecs/ilbc folder. Review: https://reviewboard.asterisk.org/r/1675 Review: https://reviewboard.asterisk.org/r/1649 (closes issue: ASTERISK-18943) Reporter: Leif Madsen Tested by: Matt Jordan ........ Merged revisions 351450 from http://svn.asterisk.org/svn/asterisk/branches/1.8 ........ Merged revisions 351451 from http://svn.asterisk.org/svn/asterisk/branches/10 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@351452 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'codecs/ilbc/iLBC_decode.c')
-rw-r--r--codecs/ilbc/iLBC_decode.c652
1 files changed, 652 insertions, 0 deletions
diff --git a/codecs/ilbc/iLBC_decode.c b/codecs/ilbc/iLBC_decode.c
new file mode 100644
index 000000000..ae62bf440
--- /dev/null
+++ b/codecs/ilbc/iLBC_decode.c
@@ -0,0 +1,652 @@
+
+ /******************************************************************
+
+ 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 "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)
+ *---------------------------------------------------------------*/
+
+ 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 */
+
+ memcpy(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 */
+
+ memcpy(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;
+ }
+ }
+