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

       iLBC Speech Coder ANSI-C Source Code

       LPC_decode.c

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

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

#include <math.h>
#include <string.h>

#include "helpfun.h"
#include "lsf.h"
#include "iLBC_define.h"
#include "constants.h"

   /*---------------------------------------------------------------*
    *  interpolation of lsf coefficients for the decoder
    *--------------------------------------------------------------*/

void LSFinterpolate2a_dec(float *a,     /* (o) lpc coefficients for a sub-frame */
  float *lsf1,                  /* (i) first lsf coefficient vector */
  float *lsf2,                  /* (i) second lsf coefficient vector */
  float coef,                   /* (i) interpolation weight */
  int length                    /* (i) length of lsf vectors */
  )
{
  float lsftmp[LPC_FILTERORDER];

  interpolate(lsftmp, lsf1, lsf2, coef, length);
  lsf2a(a, lsftmp);
}

   /*---------------------------------------------------------------*
    *  obtain dequantized lsf coefficients from quantization index
    *--------------------------------------------------------------*/

void SimplelsfDEQ(float *lsfdeq,        /* (o) dequantized lsf coefficients */
  int *index,                   /* (i) quantization index */
  int lpc_n                     /* (i) number of LPCs */
  )
{
  int i, j, pos, cb_pos;





  /* decode first LSF */

  pos = 0;
  cb_pos = 0;
  for (i = 0; i < LSF_NSPLIT; i++) {
    for (j = 0; j < dim_lsfCbTbl[i]; j++) {
      lsfdeq[pos + j] = lsfCbTbl[cb_pos +
        (long) (index[i]) * dim_lsfCbTbl[i] + j];
    }
    pos += dim_lsfCbTbl[i];
    cb_pos += size_lsfCbTbl[i] * dim_lsfCbTbl[i];
  }

  if (lpc_n > 1) {

    /* decode last LSF */

    pos = 0;
    cb_pos = 0;
    for (i = 0; i < LSF_NSPLIT; i++) {
      for (j = 0; j < dim_lsfCbTbl[i]; j++) {
        lsfdeq[LPC_FILTERORDER + pos + j] =
          lsfCbTbl[cb_pos +
          (long) (index[LSF_NSPLIT + i]) * dim_lsfCbTbl[i] + j];
      }
      pos += dim_lsfCbTbl[i];
      cb_pos += size_lsfCbTbl[i] * dim_lsfCbTbl[i];
    }
  }
}

   /*----------------------------------------------------------------*
    *  obtain synthesis and weighting filters form lsf coefficients
    *---------------------------------------------------------------*/

void DecoderInterpolateLSF(float *syntdenum,    /* (o) synthesis filter coefficients */
  float *weightdenum,           /* (o) weighting denumerator
                                   coefficients */
  float *lsfdeq,                /* (i) dequantized lsf coefficients */
  int length,                   /* (i) length of lsf coefficient vector */
  iLBC_Dec_Inst_t * iLBCdec_inst
  /* (i) the decoder state structure */
  )
{
  int i, pos, lp_length;
  float lp[LPC_FILTERORDER + 1], *lsfdeq2;






  lsfdeq2 = lsfdeq + length;
  lp_length = length + 1;

  if (iLBCdec_inst->mode == 30) {
    /* sub-frame 1: Interpolation between old and first */

    LSFinterpolate2a_dec(lp, iLBCdec_inst->lsfdeqold, lsfdeq,
      lsf_weightTbl_30ms[0], length);
    memcpy(syntdenum, lp, lp_length * sizeof(float));
    bwexpand(weightdenum, lp, LPC_CHIRP_WEIGHTDENUM, lp_length);

    /* sub-frames 2 to 6: interpolation between first
       and last LSF */

    pos = lp_length;
    for (i = 1; i < 6; i++) {
      LSFinterpolate2a_dec(lp, lsfdeq, lsfdeq2,
        lsf_weightTbl_30ms[i], length);
      memcpy(syntdenum + pos, lp, lp_length * sizeof(float));
      bwexpand(weightdenum + pos, lp, LPC_CHIRP_WEIGHTDENUM, lp_length);
      pos += lp_length;
    }
  } else {
    pos = 0;
    for (i = 0; i < iLBCdec_inst->nsub; i++) {
      LSFinterpolate2a_dec(lp, iLBCdec_inst->lsfdeqold,
        lsfdeq, lsf_weightTbl_20ms[i], length);
      memcpy(syntdenum + pos, lp, lp_length * sizeof(float));
      bwexpand(weightdenum + pos, lp, LPC_CHIRP_WEIGHTDENUM, lp_length);
      pos += lp_length;
    }
  }

  /* update memory */

  if (iLBCdec_inst->mode == 30)
    memcpy(iLBCdec_inst->lsfdeqold, lsfdeq2, length * sizeof(float));
  else
    memcpy(iLBCdec_inst->lsfdeqold, lsfdeq, length * sizeof(float));

}
