tech-invite   World Map     

IETF     RFCs     Groups     SIP     ABNFs    |    3GPP     Specs     Glossaries     Architecture     IMS     UICC    |    search

RFC 3951

 
 
 

Internet Low Bit Rate Codec (iLBC)

Part 3 of 6, p. 45 to 76
Prev RFC Part       Next RFC Part

 


prevText      Top      Up      ToC       Page 45 
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      Up      ToC       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      Up      ToC       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      Up      ToC       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      Up      ToC       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      Up      ToC       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      Up      ToC       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      Up      ToC       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      Up      ToC       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      Up      ToC       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      Up      ToC       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      Up      ToC       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      Up      ToC       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      Up      ToC       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      Up      ToC       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      Up      ToC       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      Up      ToC       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      Up      ToC       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      Up      ToC       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      Up      ToC       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      Up      ToC       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      Up      ToC       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      Up      ToC       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      Up      ToC       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      Up      ToC       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      Up      ToC       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      Up      ToC       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      Up      ToC       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      Up      ToC       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      Up      ToC       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      Up      ToC       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      Up      ToC       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 RFC Part