/*
 *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

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

 iLBC Speech Coder ANSI-C Source Code

 WebRtcIlbcfix_StateConstruct.c

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

#include "modules/audio_coding/codecs/ilbc/state_construct.h"

#include "modules/audio_coding/codecs/ilbc/constants.h"
#include "modules/audio_coding/codecs/ilbc/defines.h"

/*----------------------------------------------------------------*
 *  decoding of the start state
 *---------------------------------------------------------------*/

void WebRtcIlbcfix_StateConstruct(
    size_t idxForMax,   /* (i) 6-bit index for the quantization of
                                           max amplitude */
    int16_t *idxVec,   /* (i) vector of quantization indexes */
    int16_t *syntDenum,  /* (i) synthesis filter denumerator */
    int16_t *Out_fix,  /* (o) the decoded state vector */
    size_t len    /* (i) length of a state vector */
                                  ) {
  size_t k;
  int16_t maxVal;
  int16_t *tmp1, *tmp2, *tmp3;
  /* Stack based */
  int16_t numerator[1+LPC_FILTERORDER];
  int16_t sampleValVec[2*STATE_SHORT_LEN_30MS+LPC_FILTERORDER];
  int16_t sampleMaVec[2*STATE_SHORT_LEN_30MS+LPC_FILTERORDER];
  int16_t *sampleVal = &sampleValVec[LPC_FILTERORDER];
  int16_t *sampleMa = &sampleMaVec[LPC_FILTERORDER];
  int16_t *sampleAr = &sampleValVec[LPC_FILTERORDER];

  /* initialization of coefficients */

  for (k=0; k<LPC_FILTERORDER+1; k++){
    numerator[k] = syntDenum[LPC_FILTERORDER-k];
  }

  /* decoding of the maximum value */

  maxVal = WebRtcIlbcfix_kFrgQuantMod[idxForMax];

  /* decoding of the sample values */
  tmp1 = sampleVal;
  tmp2 = &idxVec[len-1];

  if (idxForMax<37) {
    for(k=0; k<len; k++){
      /*the shifting is due to the Q13 in sq4_fixQ13[i], also the adding of 2097152 (= 0.5 << 22)
        maxVal is in Q8 and result is in Q(-1) */
      *tmp1 = (int16_t)((maxVal * WebRtcIlbcfix_kStateSq3[*tmp2] + 2097152) >>
          22);
      tmp1++;
      tmp2--;
    }
  } else if (idxForMax<59) {
    for(k=0; k<len; k++){
      /*the shifting is due to the Q13 in sq4_fixQ13[i], also the adding of 262144 (= 0.5 << 19)
        maxVal is in Q5 and result is in Q(-1) */
      *tmp1 = (int16_t)((maxVal * WebRtcIlbcfix_kStateSq3[*tmp2] + 262144) >>
          19);
      tmp1++;
      tmp2--;
    }
  } else {
    for(k=0; k<len; k++){
      /*the shifting is due to the Q13 in sq4_fixQ13[i], also the adding of 65536 (= 0.5 << 17)
        maxVal is in Q3 and result is in Q(-1) */
      *tmp1 = (int16_t)((maxVal * WebRtcIlbcfix_kStateSq3[*tmp2] + 65536) >>
          17);
      tmp1++;
      tmp2--;
    }
  }

  /* Set the rest of the data to zero */
  WebRtcSpl_MemSetW16(&sampleVal[len], 0, len);

  /* circular convolution with all-pass filter */

  /* Set the state to zero */
  WebRtcSpl_MemSetW16(sampleValVec, 0, (LPC_FILTERORDER));

  /* Run MA filter + AR filter */
  WebRtcSpl_FilterMAFastQ12(
      sampleVal, sampleMa,
      numerator, LPC_FILTERORDER+1, len + LPC_FILTERORDER);
  WebRtcSpl_MemSetW16(&sampleMa[len + LPC_FILTERORDER], 0, (len - LPC_FILTERORDER));
  WebRtcSpl_FilterARFastQ12(
      sampleMa, sampleAr,
      syntDenum, LPC_FILTERORDER+1, 2 * len);

  tmp1 = &sampleAr[len-1];
  tmp2 = &sampleAr[2*len-1];
  tmp3 = Out_fix;
  for(k=0;k<len;k++){
    (*tmp3) = (*tmp1) + (*tmp2);
    tmp1--;
    tmp2--;
    tmp3++;
  }
}
