Skip to content
Snippets Groups Projects
iLBC_decode.c 20.2 KiB
Newer Older
  • Learn to ignore specific revisions
  • 
       /******************************************************************
    
           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 */
    
    
                   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 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);
    
                   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;
           }
       }