Tech-invite3GPPspaceIETFspace
959493929190898887868584838281807978777675747372717069686766656463626160595857565554535251504948474645444342414039383736353433323130292827262524232221201918171615141312111009080706050403020100
in Index   Prev   Next

RFC 3951

Internet Low Bit Rate Codec (iLBC)

Pages: 194
Experimental
Part 3 of 6 – Pages 45 to 76
First   Prev   Next

Top   ToC   RFC3951 - Page 45   prevText

Appendix A. Reference Implementation

This appendix contains the complete c-code for a reference implementation of encoder and decoder for the specified codec. The c-code consists of the following files with highest-level functions: iLBC_test.c: main function for evaluation purpose iLBC_encode.h: encoder header iLBC_encode.c: encoder function iLBC_decode.h: decoder header iLBC_decode.c: decoder function The following files contain global defines and constants: iLBC_define.h: global defines constants.h: global constants header constants.c: global constants memory allocations The following files contain subroutines: anaFilter.h: lpc analysis filter header anaFilter.c: lpc analysis filter function createCB.h: codebook construction header createCB.c: codebook construction function doCPLC.h: packet loss concealment header doCPLC.c: packet loss concealment function enhancer.h: signal enhancement header enhancer.c: signal enhancement function filter.h: general filter header filter.c: general filter functions FrameClassify.h: start state classification header FrameClassify.c: start state classification function gainquant.h: gain quantization header gainquant.c: gain quantization function getCBvec.h: codebook vector construction header getCBvec.c: codebook vector construction function helpfun.h: general purpose header helpfun.c: general purpose functions hpInput.h: input high pass filter header hpInput.c: input high pass filter function hpOutput.h: output high pass filter header hpOutput.c: output high pass filter function iCBConstruct.h: excitation decoding header iCBConstruct.c: excitation decoding function iCBSearch.h: excitation encoding header iCBSearch.c: excitation encoding function
Top   ToC   RFC3951 - Page 46
         LPCdecode.h: lpc decoding header
         LPCdecode.c: lpc decoding function
         LPCencode.h: lpc encoding header
         LPCencode.c: lpc encoding function
         lsf.h: line spectral frequencies header
         lsf.c: line spectral frequencies functions
         packing.h: bitstream packetization header
         packing.c: bitstream packetization functions
         StateConstructW.h: state decoding header
         StateConstructW.c: state decoding functions
         StateSearchW.h: state encoding header
         StateSearchW.c: state encoding function
         syntFilter.h: lpc synthesis filter header
         syntFilter.c: lpc synthesis filter function

   The implementation is portable and should work on many different
   platforms.  However, it is not difficult to optimize the
   implementation on particular platforms, an exercise left to the
   reader.

A.1. iLBC_test.c

/****************************************************************** iLBC Speech Coder ANSI-C Source Code iLBC_test.c Copyright (C) The Internet Society (2004). All Rights Reserved. ******************************************************************/ #include <math.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include "iLBC_define.h" #include "iLBC_encode.h" #include "iLBC_decode.h" /* Runtime statistics */ #include <time.h> #define ILBCNOOFWORDS_MAX (NO_OF_BYTES_30MS/2) /*----------------------------------------------------------------* * Encoder interface function
Top   ToC   RFC3951 - Page 47
    *---------------------------------------------------------------*/

   short encode(   /* (o) Number of bytes encoded */
       iLBC_Enc_Inst_t *iLBCenc_inst,
                                   /* (i/o) Encoder instance */
       short *encoded_data,    /* (o) The encoded bytes */
       short *data                 /* (i) The signal block to encode*/
   ){
       float block[BLOCKL_MAX];
       int k;

       /* convert signal to float */

       for (k=0; k<iLBCenc_inst->blockl; k++)
           block[k] = (float)data[k];

       /* do the actual encoding */

       iLBC_encode((unsigned char *)encoded_data, block, iLBCenc_inst);


       return (iLBCenc_inst->no_of_bytes);
   }

   /*----------------------------------------------------------------*
    *  Decoder interface function
    *---------------------------------------------------------------*/

   short decode(       /* (o) Number of decoded samples */
       iLBC_Dec_Inst_t *iLBCdec_inst,  /* (i/o) Decoder instance */
       short *decoded_data,        /* (o) Decoded signal block*/
       short *encoded_data,        /* (i) Encoded bytes */
       short mode                       /* (i) 0=PL, 1=Normal */
   ){
       int k;
       float decblock[BLOCKL_MAX], dtmp;

       /* check if mode is valid */

       if (mode<0 || mode>1) {
           printf("\nERROR - Wrong mode - 0, 1 allowed\n"); exit(3);}

       /* do actual decoding of block */

       iLBC_decode(decblock, (unsigned char *)encoded_data,
           iLBCdec_inst, mode);

       /* convert to short */
Top   ToC   RFC3951 - Page 48
       for (k=0; k<iLBCdec_inst->blockl; k++){
           dtmp=decblock[k];

           if (dtmp<MIN_SAMPLE)
               dtmp=MIN_SAMPLE;
           else if (dtmp>MAX_SAMPLE)
               dtmp=MAX_SAMPLE;
           decoded_data[k] = (short) dtmp;
       }

       return (iLBCdec_inst->blockl);
   }

   /*---------------------------------------------------------------*
    *  Main program to test iLBC encoding and decoding
    *
    *  Usage:
    *    exefile_name.exe <infile> <bytefile> <outfile> <channel>
    *
    *    <infile>   : Input file, speech for encoder (16-bit pcm file)
    *    <bytefile> : Bit stream output from the encoder
    *    <outfile>  : Output file, decoded speech (16-bit pcm file)
    *    <channel>  : Bit error file, optional (16-bit)
    *                     1 - Packet received correctly
    *                     0 - Packet Lost
    *
    *--------------------------------------------------------------*/

   int main(int argc, char* argv[])
   {

       /* Runtime statistics */

       float starttime;
       float runtime;
       float outtime;

       FILE *ifileid,*efileid,*ofileid, *cfileid;
       short data[BLOCKL_MAX];
       short encoded_data[ILBCNOOFWORDS_MAX], decoded_data[BLOCKL_MAX];
       int len;
       short pli, mode;
       int blockcount = 0;
       int packetlosscount = 0;

       /* Create structs */
       iLBC_Enc_Inst_t Enc_Inst;
       iLBC_Dec_Inst_t Dec_Inst;
Top   ToC   RFC3951 - Page 49
       /* get arguments and open files */

       if ((argc!=5) && (argc!=6)) {
           fprintf(stderr,
           "\n*-----------------------------------------------*\n");
           fprintf(stderr,
           "   %s <20,30> input encoded decoded (channel)\n\n",
               argv[0]);
           fprintf(stderr,
           "   mode    : Frame size for the encoding/decoding\n");
           fprintf(stderr,
           "                 20 - 20 ms\n");
           fprintf(stderr,
           "                 30 - 30 ms\n");
           fprintf(stderr,
           "   input   : Speech for encoder (16-bit pcm file)\n");
           fprintf(stderr,
           "   encoded : Encoded bit stream\n");
           fprintf(stderr,
           "   decoded : Decoded speech (16-bit pcm file)\n");
           fprintf(stderr,
           "   channel : Packet loss pattern, optional (16-bit)\n");
           fprintf(stderr,
           "                  1 - Packet received correctly\n");
           fprintf(stderr,
           "                  0 - Packet Lost\n");
           fprintf(stderr,
           "*-----------------------------------------------*\n\n");
           exit(1);
       }
       mode=atoi(argv[1]);
       if (mode != 20 && mode != 30) {
           fprintf(stderr,"Wrong mode %s, must be 20, or 30\n",
               argv[1]);
           exit(2);
       }
       if ( (ifileid=fopen(argv[2],"rb")) == NULL) {
           fprintf(stderr,"Cannot open input file %s\n", argv[2]);
           exit(2);}
       if ( (efileid=fopen(argv[3],"wb")) == NULL) {
           fprintf(stderr, "Cannot open encoded file %s\n",
               argv[3]); exit(1);}
       if ( (ofileid=fopen(argv[4],"wb")) == NULL) {
           fprintf(stderr, "Cannot open decoded file %s\n",
               argv[4]); exit(1);}
       if (argc==6) {
           if( (cfileid=fopen(argv[5],"rb")) == NULL) {
               fprintf(stderr, "Cannot open channel file %s\n",
Top   ToC   RFC3951 - Page 50
                   argv[5]);
               exit(1);
           }
       } else {
           cfileid=NULL;
       }

       /* print info */

       fprintf(stderr, "\n");
       fprintf(stderr,
           "*---------------------------------------------------*\n");
       fprintf(stderr,
           "*                                                   *\n");
       fprintf(stderr,
           "*      iLBC test program                            *\n");
       fprintf(stderr,
           "*                                                   *\n");
       fprintf(stderr,
           "*                                                   *\n");
       fprintf(stderr,
           "*---------------------------------------------------*\n");
       fprintf(stderr,"\nMode           : %2d ms\n", mode);
       fprintf(stderr,"Input file     : %s\n", argv[2]);
       fprintf(stderr,"Encoded file   : %s\n", argv[3]);
       fprintf(stderr,"Output file    : %s\n", argv[4]);
       if (argc==6) {
           fprintf(stderr,"Channel file   : %s\n", argv[5]);
       }
       fprintf(stderr,"\n");

       /* Initialization */

       initEncode(&Enc_Inst, mode);
       initDecode(&Dec_Inst, mode, 1);

       /* Runtime statistics */

       starttime=clock()/(float)CLOCKS_PER_SEC;

       /* loop over input blocks */

       while (fread(data,sizeof(short),Enc_Inst.blockl,ifileid)==
               Enc_Inst.blockl) {

           blockcount++;

           /* encoding */
Top   ToC   RFC3951 - Page 51
           fprintf(stderr, "--- Encoding block %i --- ",blockcount);
           len=encode(&Enc_Inst, encoded_data, data);
           fprintf(stderr, "\r");

           /* write byte file */

           fwrite(encoded_data, sizeof(unsigned char), len, efileid);

           /* get channel data if provided */
           if (argc==6) {
               if (fread(&pli, sizeof(short), 1, cfileid)) {
                   if ((pli!=0)&&(pli!=1)) {
                       fprintf(stderr, "Error in channel file\n");
                       exit(0);
                   }
                   if (pli==0) {
                       /* Packet loss -> remove info from frame */
                       memset(encoded_data, 0,
                           sizeof(short)*ILBCNOOFWORDS_MAX);
                       packetlosscount++;
                   }
               } else {
                   fprintf(stderr, "Error. Channel file too short\n");
                   exit(0);
               }
           } else {
               pli=1;
           }

           /* decoding */

           fprintf(stderr, "--- Decoding block %i --- ",blockcount);

           len=decode(&Dec_Inst, decoded_data, encoded_data, pli);
           fprintf(stderr, "\r");

           /* write output file */

           fwrite(decoded_data,sizeof(short),len,ofileid);
       }

       /* Runtime statistics */

       runtime = (float)(clock()/(float)CLOCKS_PER_SEC-starttime);
       outtime = (float)((float)blockcount*(float)mode/1000.0);
       printf("\n\nLength of speech file: %.1f s\n", outtime);
       printf("Packet loss          : %.1f%%\n",
           100.0*(float)packetlosscount/(float)blockcount);
Top   ToC   RFC3951 - Page 52
       printf("Time to run iLBC     :");
       printf(" %.1f s (%.1f %% of realtime)\n\n", runtime,
           (100*runtime/outtime));

       /* close files */

       fclose(ifileid);  fclose(efileid); fclose(ofileid);
       if (argc==6) {
           fclose(cfileid);
       }
       return(0);
   }

A.2. iLBC_encode.h

/****************************************************************** iLBC Speech Coder ANSI-C Source Code iLBC_encode.h Copyright (C) The Internet Society (2004). All Rights Reserved. ******************************************************************/ #ifndef __iLBC_ILBCENCODE_H #define __iLBC_ILBCENCODE_H #include "iLBC_define.h" short initEncode( /* (o) Number of bytes encoded */ iLBC_Enc_Inst_t *iLBCenc_inst, /* (i/o) Encoder instance */ int mode /* (i) frame size mode */ ); 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 */ ); #endif
Top   ToC   RFC3951 - Page 53

A.3. iLBC_encode.c

/****************************************************************** 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;
Top   ToC   RFC3951 - Page 54
           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];
Top   ToC   RFC3951 - Page 55
       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;
Top   ToC   RFC3951 - Page 56
       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,
Top   ToC   RFC3951 - Page 57
               &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];
Top   ToC   RFC3951 - Page 58
           }
       }

       /* 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,
Top   ToC   RFC3951 - Page 59
                   &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,
Top   ToC   RFC3951 - Page 60
                   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++) {
Top   ToC   RFC3951 - Page 61
           /* 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);
           }
Top   ToC   RFC3951 - Page 62
           /* 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]+
Top   ToC   RFC3951 - Page 63
                       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);
   }

A.4. iLBC_decode.h

/****************************************************************** iLBC Speech Coder ANSI-C Source Code iLBC_decode.h Copyright (C) The Internet Society (2004). All Rights Reserved. ******************************************************************/ #ifndef __iLBC_ILBCDECODE_H #define __iLBC_ILBCDECODE_H #include "iLBC_define.h" 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 */ ); 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 */
Top   ToC   RFC3951 - Page 64
   );

   #endif

A.5. iLBC_decode.c

/****************************************************************** 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;
Top   ToC   RFC3951 - Page 65
       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;
Top   ToC   RFC3951 - Page 66
       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;
Top   ToC   RFC3951 - Page 67
       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];
Top   ToC   RFC3951 - Page 68
           }
           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,
Top   ToC   RFC3951 - Page 69
                   &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++;
           }
Top   ToC   RFC3951 - Page 70
           /* 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;
Top   ToC   RFC3951 - Page 71
           /* 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,
Top   ToC   RFC3951 - Page 72
                   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,
Top   ToC   RFC3951 - Page 73
                       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);
Top   ToC   RFC3951 - Page 74
               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);
Top   ToC   RFC3951 - Page 75
               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);
           }
Top   ToC   RFC3951 - Page 76
       }

       /* 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;
       }
   }



(page 76 continued on part 4)

Next Section