
   /******************************************************************

       iLBC Speech Coder ANSI-C Source Code

       iLBC_decode.c

       Copyright (C) The Internet Society (2004).
       All Rights Reserved.

   ******************************************************************/

#include <math.h>
#include <stdlib.h>

#include "iLBC_define.h"
#include "StateConstructW.h"
#include "LPCdecode.h"
#include "iCBConstruct.h"
#include "doCPLC.h"
#include "helpfun.h"
#include "constants.h"
#include "packing.h"
#include "string.h"
#include "enhancer.h"
#include "hpOutput.h"
#include "syntFilter.h"

   /*----------------------------------------------------------------*
    *  Initiation of decoder instance.
    *---------------------------------------------------------------*/

short initDecode(               /* (o) Number of decoded
                                   samples */
  iLBC_Dec_Inst_t * iLBCdec_inst,       /* (i/o) Decoder instance */
  int mode,                     /* (i) frame size mode */
  int use_enhancer              /* (i) 1 to use enhancer
                                   0 to run without
                                   enhancer */
  )
{
  int i;

  iLBCdec_inst->mode = mode;





  if (mode == 30) {
    iLBCdec_inst->blockl = BLOCKL_30MS;
    iLBCdec_inst->nsub = NSUB_30MS;
    iLBCdec_inst->nasub = NASUB_30MS;
    iLBCdec_inst->lpc_n = LPC_N_30MS;
    iLBCdec_inst->no_of_bytes = NO_OF_BYTES_30MS;
    iLBCdec_inst->no_of_words = NO_OF_WORDS_30MS;
    iLBCdec_inst->state_short_len = STATE_SHORT_LEN_30MS;
    /* ULP init */
    iLBCdec_inst->ULP_inst = &ULP_30msTbl;
  } else if (mode == 20) {
    iLBCdec_inst->blockl = BLOCKL_20MS;
    iLBCdec_inst->nsub = NSUB_20MS;
    iLBCdec_inst->nasub = NASUB_20MS;
    iLBCdec_inst->lpc_n = LPC_N_20MS;
    iLBCdec_inst->no_of_bytes = NO_OF_BYTES_20MS;
    iLBCdec_inst->no_of_words = NO_OF_WORDS_20MS;
    iLBCdec_inst->state_short_len = STATE_SHORT_LEN_20MS;
    /* ULP init */
    iLBCdec_inst->ULP_inst = &ULP_20msTbl;
  } else {
    exit(2);
  }

  memset(iLBCdec_inst->syntMem, 0, LPC_FILTERORDER * sizeof(float));
  memcpy((*iLBCdec_inst).lsfdeqold, lsfmeanTbl,
    LPC_FILTERORDER * sizeof(float));

  memset(iLBCdec_inst->old_syntdenum, 0,
    ((LPC_FILTERORDER + 1) * NSUB_MAX) * sizeof(float));
  for (i = 0; i < NSUB_MAX; i++)
    iLBCdec_inst->old_syntdenum[i * (LPC_FILTERORDER + 1)] = 1.0;

  iLBCdec_inst->last_lag = 20;

  iLBCdec_inst->prevLag = 120;
  iLBCdec_inst->per = 0.0;
  iLBCdec_inst->consPLICount = 0;
  iLBCdec_inst->prevPLI = 0;
  iLBCdec_inst->prevLpc[0] = 1.0;
  memset(iLBCdec_inst->prevLpc + 1, 0, LPC_FILTERORDER * sizeof(float));
  memset(iLBCdec_inst->prevResidual, 0, BLOCKL_MAX * sizeof(float));
  iLBCdec_inst->seed = 777;






  memset(iLBCdec_inst->hpomem, 0, 4 * sizeof(float));

  iLBCdec_inst->use_enhancer = use_enhancer;
  memset(iLBCdec_inst->enh_buf, 0, ENH_BUFL * sizeof(float));
  for (i = 0; i < ENH_NBLOCKS_TOT; i++)
    iLBCdec_inst->enh_period[i] = (float) 40.0;

  iLBCdec_inst->prev_enh_pl = 0;

  return (iLBCdec_inst->blockl);
}

   /*----------------------------------------------------------------*
    *  frame residual decoder function (subrutine to iLBC_decode)
    *---------------------------------------------------------------*/

void Decode(iLBC_Dec_Inst_t * iLBCdec_inst,     /* (i/o) the decoder state
                                                   structure */
  float *decresidual,           /* (o) decoded residual frame */
  int start,                    /* (i) location of start
                                   state */
  int idxForMax,                /* (i) codebook index for the
                                   maximum value */
  int *idxVec,                  /* (i) codebook indexes for the
                                   samples  in the start
                                   state */
  float *syntdenum,             /* (i) the decoded synthesis
                                   filter coefficients */
  int *cb_index,                /* (i) the indexes for the
                                   adaptive codebook */
  int *gain_index,              /* (i) the indexes for the
                                   corresponding gains */
  int *extra_cb_index,          /* (i) the indexes for the
                                   adaptive codebook part
                                   of start state */
  int *extra_gain_index,        /* (i) the indexes for the
                                   corresponding gains */
  int state_first               /* (i) 1 if non adaptive part
                                   of start state comes
                                   first 0 if that part
                                   comes last */
  )
{
  float reverseDecresidual[BLOCKL_MAX], mem[CB_MEML];
  int k, meml_gotten, Nfor, Nback, i;
  int diff, start_pos;
  int subcount, subframe;






  diff = STATE_LEN - iLBCdec_inst->state_short_len;

  if (state_first == 1) {
    start_pos = (start - 1) * SUBL;
  } else {
    start_pos = (start - 1) * SUBL + diff;
  }

  /* decode scalar part of start state */

  StateConstructW(idxForMax, idxVec,
    &syntdenum[(start - 1) * (LPC_FILTERORDER + 1)],
    &decresidual[start_pos], iLBCdec_inst->state_short_len);


  if (state_first) {            /* put adaptive part in the end */

    /* setup memory */

    memset(mem, 0,
      (CB_MEML - iLBCdec_inst->state_short_len) * sizeof(float));
    memcpy(mem + CB_MEML - iLBCdec_inst->state_short_len,
      decresidual + start_pos,
      iLBCdec_inst->state_short_len * sizeof(float));

    /* construct decoded vector */

    iCBConstruct(&decresidual[start_pos +
        iLBCdec_inst->state_short_len], extra_cb_index,
      extra_gain_index, mem + CB_MEML - stMemLTbl, stMemLTbl, diff,
      CB_NSTAGES);

  } else {                      /* put adaptive part in the beginning */

    /* create reversed vectors for prediction */

    for (k = 0; k < diff; k++) {
      reverseDecresidual[k] =
        decresidual[(start + 1) * SUBL - 1 -
        (k + iLBCdec_inst->state_short_len)];
    }

    /* setup memory */

    meml_gotten = iLBCdec_inst->state_short_len;
    for (k = 0; k < meml_gotten; k++) {
      mem[CB_MEML - 1 - k] = decresidual[start_pos + k];





    }
    memset(mem, 0, (CB_MEML - k) * sizeof(float));

    /* construct decoded vector */

    iCBConstruct(reverseDecresidual, extra_cb_index,
      extra_gain_index, mem + CB_MEML - stMemLTbl, stMemLTbl,
      diff, CB_NSTAGES);

    /* get decoded residual from reversed vector */

    for (k = 0; k < diff; k++) {
      decresidual[start_pos - 1 - k] = reverseDecresidual[k];
    }
  }

  /* counter for predicted sub-frames */

  subcount = 0;

  /* forward prediction of sub-frames */

  Nfor = iLBCdec_inst->nsub - start - 1;

  if (Nfor > 0) {

    /* setup memory */

    memset(mem, 0, (CB_MEML - STATE_LEN) * sizeof(float));
    memcpy(mem + CB_MEML - STATE_LEN, decresidual + (start - 1) * SUBL,
      STATE_LEN * sizeof(float));

    /* loop over sub-frames to encode */

    for (subframe = 0; subframe < Nfor; subframe++) {

      /* construct decoded vector */

      iCBConstruct(&decresidual[(start + 1 + subframe) * SUBL],
        cb_index + subcount * CB_NSTAGES,
        gain_index + subcount * CB_NSTAGES,
        mem + CB_MEML - memLfTbl[subcount],
        memLfTbl[subcount], SUBL, CB_NSTAGES);

      /* update memory */

      memcpy(mem, mem + SUBL, (CB_MEML - SUBL) * sizeof(float));
      memcpy(mem + CB_MEML - SUBL,
        &decresidual[(start + 1 + subframe) * SUBL],
        SUBL * sizeof(float));

      subcount++;

    }

  }

  /* backward prediction of sub-frames */

  Nback = start - 1;

  if (Nback > 0) {

    /* setup memory */

    meml_gotten = SUBL * (iLBCdec_inst->nsub + 1 - start);

    if (meml_gotten > CB_MEML) {
      meml_gotten = CB_MEML;
    }
    for (k = 0; k < meml_gotten; k++) {
      mem[CB_MEML - 1 - k] = decresidual[(start - 1) * SUBL + k];
    }
    memset(mem, 0, (CB_MEML - k) * sizeof(float));

    /* loop over subframes to decode */

    for (subframe = 0; subframe < Nback; subframe++) {

      /* construct decoded vector */

      iCBConstruct(&reverseDecresidual[subframe * SUBL],
        cb_index + subcount * CB_NSTAGES,
        gain_index + subcount * CB_NSTAGES,
        mem + CB_MEML - memLfTbl[subcount], memLfTbl[subcount],
        SUBL, CB_NSTAGES);

      /* update memory */

      memcpy(mem, mem + SUBL, (CB_MEML - SUBL) * sizeof(float));
      memcpy(mem + CB_MEML - SUBL,
        &reverseDecresidual[subframe * SUBL], SUBL * sizeof(float));

      subcount++;
    }





    /* get decoded residual from reversed vector */

    for (i = 0; i < SUBL * Nback; i++)
      decresidual[SUBL * Nback - i - 1] = reverseDecresidual[i];
  }
}

   /*----------------------------------------------------------------*
    *  main decoder function
    *---------------------------------------------------------------*/

void iLBC_decode(float *decblock,       /* (o) decoded signal block */
  unsigned char *bytes,         /* (i) encoded signal bits */
  iLBC_Dec_Inst_t * iLBCdec_inst,       /* (i/o) the decoder state
                                           structure */
  int mode                      /* (i) 0: bad packet, PLC,
                                   1: normal */
  )
{
  float data[BLOCKL_MAX];
  float lsfdeq[LPC_FILTERORDER * LPC_N_MAX];
  float PLCresidual[BLOCKL_MAX], PLClpc[LPC_FILTERORDER + 1];
  float zeros[BLOCKL_MAX], one[LPC_FILTERORDER + 1];
  int k, i, start, idxForMax, pos, lastpart, ulp;
  int lag, ilag;
  float cc, maxcc;
  int idxVec[STATE_LEN];
  int check;
  int gain_index[NASUB_MAX * CB_NSTAGES], extra_gain_index[CB_NSTAGES];
  int cb_index[CB_NSTAGES * NASUB_MAX], extra_cb_index[CB_NSTAGES];
  int lsf_i[LSF_NSPLIT * LPC_N_MAX];
  int state_first;
  int last_bit;
  unsigned char *pbytes;
  float weightdenum[(LPC_FILTERORDER + 1) * NSUB_MAX];
  int order_plus_one;
  float syntdenum[NSUB_MAX * (LPC_FILTERORDER + 1)];
  float decresidual[BLOCKL_MAX];

  if (mode > 0) {               /* the data are good */

    /* decode data */

    pbytes = bytes;
    pos = 0;






    /* Set everything to zero before decoding */

    for (k = 0; k < LSF_NSPLIT * LPC_N_MAX; k++) {
      lsf_i[k] = 0;
    }
    start = 0;
    state_first = 0;
    idxForMax = 0;
    for (k = 0; k < iLBCdec_inst->state_short_len; k++) {
      idxVec[k] = 0;
    }
    for (k = 0; k < CB_NSTAGES; k++) {
      extra_cb_index[k] = 0;
    }
    for (k = 0; k < CB_NSTAGES; k++) {
      extra_gain_index[k] = 0;
    }
    for (i = 0; i < iLBCdec_inst->nasub; i++) {
      for (k = 0; k < CB_NSTAGES; k++) {
        cb_index[i * CB_NSTAGES + k] = 0;
      }
    }
    for (i = 0; i < iLBCdec_inst->nasub; i++) {
      for (k = 0; k < CB_NSTAGES; k++) {
        gain_index[i * CB_NSTAGES + k] = 0;
      }
    }

    /* loop over ULP classes */

    for (ulp = 0; ulp < 3; ulp++) {

      /* LSF */
      for (k = 0; k < LSF_NSPLIT * iLBCdec_inst->lpc_n; k++) {
        unpack(&pbytes, &lastpart,
          iLBCdec_inst->ULP_inst->lsf_bits[k][ulp], &pos);
        packcombine(&lsf_i[k], lastpart,
          iLBCdec_inst->ULP_inst->lsf_bits[k][ulp]);
      }

      /* Start block info */

      unpack(&pbytes, &lastpart,
        iLBCdec_inst->ULP_inst->start_bits[ulp], &pos);
      packcombine(&start, lastpart,
        iLBCdec_inst->ULP_inst->start_bits[ulp]);

      unpack(&pbytes, &lastpart,
        iLBCdec_inst->ULP_inst->startfirst_bits[ulp], &pos);
      packcombine(&state_first, lastpart,
        iLBCdec_inst->ULP_inst->startfirst_bits[ulp]);

      unpack(&pbytes, &lastpart,
        iLBCdec_inst->ULP_inst->scale_bits[ulp], &pos);
      packcombine(&idxForMax, lastpart,
        iLBCdec_inst->ULP_inst->scale_bits[ulp]);

      for (k = 0; k < iLBCdec_inst->state_short_len; k++) {
        unpack(&pbytes, &lastpart,
          iLBCdec_inst->ULP_inst->state_bits[ulp], &pos);
        packcombine(idxVec + k, lastpart,
          iLBCdec_inst->ULP_inst->state_bits[ulp]);
      }

      /* 23/22 (20ms/30ms) sample block */

      for (k = 0; k < CB_NSTAGES; k++) {
        unpack(&pbytes, &lastpart,
          iLBCdec_inst->ULP_inst->extra_cb_index[k][ulp], &pos);
        packcombine(extra_cb_index + k, lastpart,
          iLBCdec_inst->ULP_inst->extra_cb_index[k][ulp]);
      }
      for (k = 0; k < CB_NSTAGES; k++) {
        unpack(&pbytes, &lastpart,
          iLBCdec_inst->ULP_inst->extra_cb_gain[k][ulp], &pos);
        packcombine(extra_gain_index + k, lastpart,
          iLBCdec_inst->ULP_inst->extra_cb_gain[k][ulp]);
      }

      /* The two/four (20ms/30ms) 40 sample sub-blocks */

      for (i = 0; i < iLBCdec_inst->nasub; i++) {
        for (k = 0; k < CB_NSTAGES; k++) {
          unpack(&pbytes, &lastpart,
            iLBCdec_inst->ULP_inst->cb_index[i][k][ulp], &pos);
          packcombine(cb_index + i * CB_NSTAGES + k, lastpart,
            iLBCdec_inst->ULP_inst->cb_index[i][k][ulp]);
        }
      }

      for (i = 0; i < iLBCdec_inst->nasub; i++) {
        for (k = 0; k < CB_NSTAGES; k++) {
          unpack(&pbytes, &lastpart,
            iLBCdec_inst->ULP_inst->cb_gain[i][k][ulp], &pos);
          packcombine(gain_index + i * CB_NSTAGES + k, lastpart,
            iLBCdec_inst->ULP_inst->cb_gain[i][k][ulp]);
        }
      }
    }
    /* Extract last bit. If it is 1 this indicates an
       empty/lost frame */
    unpack(&pbytes, &last_bit, 1, &pos);

    /* Check for bit errors or empty/lost frames */
    if (start < 1)
      mode = 0;
    if (iLBCdec_inst->mode == 20 && start > 3)
      mode = 0;
    if (iLBCdec_inst->mode == 30 && start > 5)
      mode = 0;
    if (last_bit == 1)
      mode = 0;

    if (mode == 1) {            /* No bit errors was detected,
                                   continue decoding */

      /* adjust index */
      index_conv_dec(cb_index);

      /* decode the lsf */

      SimplelsfDEQ(lsfdeq, lsf_i, iLBCdec_inst->lpc_n);
      check = LSF_check(lsfdeq, LPC_FILTERORDER, iLBCdec_inst->lpc_n);
      DecoderInterpolateLSF(syntdenum, weightdenum,
        lsfdeq, LPC_FILTERORDER, iLBCdec_inst);

      Decode(iLBCdec_inst, decresidual, start, idxForMax,
        idxVec, syntdenum, cb_index, gain_index,
        extra_cb_index, extra_gain_index, state_first);

      /* preparing the plc for a future loss! */

      doThePLC(PLCresidual, PLClpc, 0, decresidual,
        syntdenum +
        (LPC_FILTERORDER + 1) * (iLBCdec_inst->nsub - 1),
        (*iLBCdec_inst).last_lag, iLBCdec_inst);







      memcpy(decresidual, PLCresidual,
        iLBCdec_inst->blockl * sizeof(float));
    }

  }

  if (mode == 0) {
    /* the data is bad (either a PLC call
     * was made or a severe bit error was detected)
     */

    /* packet loss conceal */

    memset(zeros, 0, BLOCKL_MAX * sizeof(float));

    one[0] = 1;
    memset(one + 1, 0, LPC_FILTERORDER * sizeof(float));

    start = 0;

    doThePLC(PLCresidual, PLClpc, 1, zeros, one,
      (*iLBCdec_inst).last_lag, iLBCdec_inst);
    memcpy(decresidual, PLCresidual,
      iLBCdec_inst->blockl * sizeof(float));

    order_plus_one = LPC_FILTERORDER + 1;
    for (i = 0; i < iLBCdec_inst->nsub; i++) {
      memcpy(syntdenum + (i * order_plus_one), PLClpc,
        order_plus_one * sizeof(float));
    }
  }

  if (iLBCdec_inst->use_enhancer == 1) {

    /* post filtering */

    iLBCdec_inst->last_lag =
      enhancerInterface(data, decresidual, iLBCdec_inst);

    /* synthesis filtering */

    if (iLBCdec_inst->mode == 20) {
      /* Enhancer has 40 samples delay */
      i = 0;
      syntFilter(data + i * SUBL,
        iLBCdec_inst->old_syntdenum +
        (i + iLBCdec_inst->nsub - 1) * (LPC_FILTERORDER + 1),
        SUBL, iLBCdec_inst->syntMem);





      for (i = 1; i < iLBCdec_inst->nsub; i++) {
        syntFilter(data + i * SUBL,
          syntdenum + (i - 1) * (LPC_FILTERORDER + 1),
          SUBL, iLBCdec_inst->syntMem);
      }
    } else if (iLBCdec_inst->mode == 30) {
      /* Enhancer has 80 samples delay */
      for (i = 0; i < 2; i++) {
        syntFilter(data + i * SUBL,
          iLBCdec_inst->old_syntdenum +
          (i + iLBCdec_inst->nsub - 2) * (LPC_FILTERORDER + 1),
          SUBL, iLBCdec_inst->syntMem);
      }
      for (i = 2; i < iLBCdec_inst->nsub; i++) {
        syntFilter(data + i * SUBL,
          syntdenum + (i - 2) * (LPC_FILTERORDER + 1), SUBL,
          iLBCdec_inst->syntMem);
      }
    }

  } else {

    /* Find last lag */
    lag = 20;
    maxcc = xCorrCoef(&decresidual[BLOCKL_MAX - ENH_BLOCKL],
      &decresidual[BLOCKL_MAX - ENH_BLOCKL - lag], ENH_BLOCKL);

    for (ilag = 21; ilag < 120; ilag++) {
      cc = xCorrCoef(&decresidual[BLOCKL_MAX - ENH_BLOCKL],
        &decresidual[BLOCKL_MAX - ENH_BLOCKL - ilag], ENH_BLOCKL);

      if (cc > maxcc) {
        maxcc = cc;
        lag = ilag;
      }
    }
    iLBCdec_inst->last_lag = lag;

    /* copy data and run synthesis filter */

    memcpy(data, decresidual, iLBCdec_inst->blockl * sizeof(float));
    for (i = 0; i < iLBCdec_inst->nsub; i++) {
      syntFilter(data + i * SUBL,
        syntdenum + i * (LPC_FILTERORDER + 1), SUBL,
        iLBCdec_inst->syntMem);
    }





  }

  /* high pass filtering on output if desired, otherwise
     copy to out */

  hpOutput(data, iLBCdec_inst->blockl, decblock, iLBCdec_inst->hpomem);

  /* memcpy(decblock,data,iLBCdec_inst->blockl*sizeof(float)); */

  memcpy(iLBCdec_inst->old_syntdenum, syntdenum,
    iLBCdec_inst->nsub * (LPC_FILTERORDER + 1) * sizeof(float));

  iLBCdec_inst->prev_enh_pl = 0;

  if (mode == 0) {              /* PLC was used */
    iLBCdec_inst->prev_enh_pl = 1;
  }
}
