/*
 * ===================================================================
 *  TS 26.104
 *  REL-5 V5.4.0 2004-03
 *  REL-6 V6.1.0 2004-03
 *  3GPP AMR Floating-point Speech Codec
 * ===================================================================
 *
 */

/*
 * sp_dec.c
 *
 *
 * Project:
 *    AMR Floating-Point Codec
 *
 * Contains:
 *    This module contains all the functions needed decoding AMR
 *    encoder parameters to 16-bit speech samples
 *
 */
/*
 * include files
 */
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <math.h>
#include "sp_dec.h"
#include "rom_dec.h"

/*
 * Declare structure types
 */
enum DTXStateType
{
   SPEECH = 0, DTX, DTX_MUTE
};

/*
 * Decoder memory structure
 */
typedef struct
{
   /* history vector of past synthesis speech energy */
   Word32 frameEnergyHist[L_ENERGYHIST];


   /* state flags */
   Word16 bgHangover;   /* counter; number of frames after last speech frame */


}Bgn_scdState;
typedef struct
{
   Word32 hangCount;   /* counter; */
   /* history vector of past synthesis speech energy */
   Word32 cbGainHistory[L_CBGAINHIST];
   Word16 hangVar;   /* counter; */

}Cb_gain_averageState;
typedef struct
{
   Word32 lsp_meanSave[M];   /* Averaged LSPs saved for efficiency  */


}lsp_avgState;
typedef struct
{
   Word32 past_r_q[M];   /* Past quantized prediction error, Q15 */
   Word32 past_lsf_q[M];   /* Past dequantized lsfs, Q15 */


}D_plsfState;
typedef struct
{
   Word32 pbuf[5];
   Word32 past_gain_pit;
   Word32 prev_gp;


}ec_gain_pitchState;
typedef struct
{
   Word32 gbuf[5];
   Word32 past_gain_code;
   Word32 prev_gc;


}ec_gain_codeState;
typedef struct
{
   /*
    * normal MA predictor memory, Q10
    * (contains 20*log10(quaErr))
    */
   Word32 past_qua_en[4];


   /*
    * MA predictor memory for MR122 mode, Q10
    * (contains log2(quaErr))
    */
   Word32 past_qua_en_MR122[4];


}gc_predState;
typedef struct
{
   Word32 gainMem[PHDGAINMEMSIZE];
   Word32 prevCbGain;
   Word32 prevState;
   Word16 lockFull;
   Word16 onset;


}ph_dispState;
typedef struct
{
   enum DTXStateType dtxGlobalState;   /* contains previous state */

   Word32 log_en;
   Word32 old_log_en;
   Word32 pn_seed_rx;
   Word32 lsp[M];
   Word32 lsp_old[M];
   Word32 lsf_hist[M * DTX_HIST_SIZE];
   Word32 lsf_hist_mean[M * DTX_HIST_SIZE];
   Word32 log_en_hist[DTX_HIST_SIZE];
   Word32 true_sid_period_inv;
   Word16 since_last_sid;
   Word16 lsf_hist_ptr;
   Word16 log_pg_mean;
   Word16 log_en_hist_ptr;
   Word16 log_en_adjust;
   Word16 dtxHangoverCount;
   Word16 decAnaElapsedCount;
   Word16 sid_frame;
   Word16 valid_data;
   Word16 dtxHangoverAdded;


   /* updated in main decoder */
   Word16 data_updated;   /* marker to know if CNI data is ever renewed */


}dtx_decState;
typedef struct
{
   Word32 past_gain;


}agcState;
typedef struct
{
   /* Excitation vector */
   Word32 old_exc[L_SUBFR + PIT_MAX + L_INTERPOL];
   Word32 *exc;
   Word32 lsp_old[M];


   /* Filter's memory */
   Word32 mem_syn[M];


   /* pitch sharpening */
   Word32 sharp;
   Word32 old_T0;


   /* Variable holding received ltpLag, used in background noise and BFI */
   Word32 T0_lagBuff;


   /* Variables for the source characteristic detector (SCD) */
   Word32 inBackgroundNoise;
   Word32 voicedHangover;
   Word32 ltpGainHistory[9];


   /* Memories for bad frame handling */
   Word32 excEnergyHist[9];
   Word16 prev_bf;
   Word16 prev_pdf;
   Word16 state;
   Word16 nodataSeed;


   Bgn_scdState * background_state;
   Cb_gain_averageState * Cb_gain_averState;
   lsp_avgState * lsp_avg_st;
   D_plsfState * lsfState;
   ec_gain_pitchState * ec_gain_p_st;
   ec_gain_codeState * ec_gain_c_st;
   gc_predState * pred_state;
   ph_dispState * ph_disp_st;
   dtx_decState * dtxDecoderState;
}Decoder_amrState;
typedef struct
{
   Word32 res2[L_SUBFR];
   Word32 mem_syn_pst[M];
   Word32 synth_buf[M + L_FRAME];
   Word32 preemph_state_mem_pre;
   agcState * agc_state;
}Post_FilterState;
typedef struct
{
   Word32 y2_hi;
   Word32 y2_lo;
   Word32 y1_hi;
   Word32 y1_lo;
   Word32 x0;
   Word32 x1;


}Post_ProcessState;
typedef struct
{
   Decoder_amrState * decoder_amrState;
   Post_FilterState * post_state;
   Post_ProcessState * postHP_state;
}Speech_Decode_FrameState;


/*
 * CodAmrReset
 *
 *
 * Parameters:
 *    state             B: state structure
 *    mode              I: AMR mode
 *
 * Function:
 *    Resets state memory
 *
 * Returns:
 *    void
 */
static void Decoder_amr_reset( Decoder_amrState *state, enum Mode mode )
{
   Word32 i;

   /* Cb_gain_average_reset */
   memset(state->Cb_gain_averState->cbGainHistory, 0, L_CBGAINHIST << 2);
   state->Cb_gain_averState->hangVar = 0;
   state->Cb_gain_averState->hangCount= 0;

   /* Initialize static pointer */
   state->exc = state->old_exc + PIT_MAX + L_INTERPOL;

   /* Static vectors to zero */
   memset( state->old_exc, 0, ( PIT_MAX + L_INTERPOL )<<2 );

   if ( mode != MRDTX )
      memset( state->mem_syn, 0, M <<2 );

   /* initialize pitch sharpening */
   state->sharp = SHARPMIN;
   state->old_T0 = 40;

   /* Initialize state->lsp_old [] */
   if ( mode != MRDTX ) {
      state->lsp_old[0] = 30000;
      state->lsp_old[1] = 26000;
      state->lsp_old[2] = 21000;
      state->lsp_old[3] = 15000;
      state->lsp_old[4] = 8000;
      state->lsp_old[5] = 0;
      state->lsp_old[6] = -8000;
      state->lsp_old[7] = -15000;
      state->lsp_old[8] = -21000;
      state->lsp_old[9] = -26000;
   }

   /* Initialize memories of bad frame handling */
   state->prev_bf = 0;
   state->prev_pdf = 0;
   state->state = 0;
   state->T0_lagBuff = 40;
   state->inBackgroundNoise = 0;
   state->voicedHangover = 0;

   if ( mode != MRDTX )
      memset( state->excEnergyHist, 0, 9 <<2 );
   memset( state->ltpGainHistory, 0, 9 <<2 );

   if ( mode != MRDTX ) {
      state->lsp_avg_st->lsp_meanSave[0] = 1384;
      state->lsp_avg_st->lsp_meanSave[1] = 2077;
      state->lsp_avg_st->lsp_meanSave[2] = 3420;
      state->lsp_avg_st->lsp_meanSave[3] = 5108;
      state->lsp_avg_st->lsp_meanSave[4] = 6742;
      state->lsp_avg_st->lsp_meanSave[5] = 8122;
      state->lsp_avg_st->lsp_meanSave[6] = 9863;
      state->lsp_avg_st->lsp_meanSave[7] = 11092;
      state->lsp_avg_st->lsp_meanSave[8] = 12714;
      state->lsp_avg_st->lsp_meanSave[9] = 13701;
   }
   memset( state->lsfState->past_r_q, 0, M <<2 );

   /* Past dequantized lsfs */
   state->lsfState->past_lsf_q[0] = 1384;
   state->lsfState->past_lsf_q[1] = 2077;
   state->lsfState->past_lsf_q[2] = 3420;
   state->lsfState->past_lsf_q[3] = 5108;
   state->lsfState->past_lsf_q[4] = 6742;
   state->lsfState->past_lsf_q[5] = 8122;
   state->lsfState->past_lsf_q[6] = 9863;
   state->lsfState->past_lsf_q[7] = 11092;
   state->lsfState->past_lsf_q[8] = 12714;
   state->lsfState->past_lsf_q[9] = 13701;

   for ( i = 0; i < 5; i++ )
      state->ec_gain_p_st->pbuf[i] = 1640;
   state->ec_gain_p_st->past_gain_pit = 0;
   state->ec_gain_p_st->prev_gp = 16384;

   for ( i = 0; i < 5; i++ )
      state->ec_gain_c_st->gbuf[i] = 1;
   state->ec_gain_c_st->past_gain_code = 0;
   state->ec_gain_c_st->prev_gc = 1;

   if ( mode != MRDTX ) {
      for ( i = 0; i < NPRED; i++ ) {
         state->pred_state->past_qua_en[i] = MIN_ENERGY;
         state->pred_state->past_qua_en_MR122[i] = MIN_ENERGY_MR122;
      }
   }
   state->nodataSeed = 21845;

   /* Static vectors to zero */
   memset( state->background_state->frameEnergyHist, 0, L_ENERGYHIST <<2 );

   /* Initialize hangover handling */
   state->background_state->bgHangover = 0;

   /* phDispReset */
   memset( state->ph_disp_st->gainMem, 0, PHDGAINMEMSIZE <<2 );
   state->ph_disp_st->prevState = 0;
   state->ph_disp_st->prevCbGain = 0;
   state->ph_disp_st->lockFull = 0;
   state->ph_disp_st->onset = 0;   /* assume no onset in start */

   if ( mode != MRDTX ) {
      state->dtxDecoderState->since_last_sid = 0;
      state->dtxDecoderState->true_sid_period_inv = 8192;
      state->dtxDecoderState->log_en = 3500;
      state->dtxDecoderState->old_log_en = 3500;

      /* low level noise for better performance in  DTX handover cases*/
      state->dtxDecoderState->pn_seed_rx = PN_INITIAL_SEED;

      /* Initialize state->lsp [] */
      state->dtxDecoderState->lsp[0] = 30000;
      state->dtxDecoderState->lsp[1] = 26000;
      state->dtxDecoderState->lsp[2] = 21000;
      state->dtxDecoderState->lsp[3] = 15000;
      state->dtxDecoderState->lsp[4] = 8000;
      state->dtxDecoderState->lsp[5] = 0;
      state->dtxDecoderState->lsp[6] = -8000;
      state->dtxDecoderState->lsp[7] = -15000;
      state->dtxDecoderState->lsp[8] = -21000;
      state->dtxDecoderState->lsp[9] = -26000;

      /* Initialize state->lsp_old [] */
      state->dtxDecoderState->lsp_old[0] = 30000;
      state->dtxDecoderState->lsp_old[1] = 26000;
      state->dtxDecoderState->lsp_old[2] = 21000;
      state->dtxDecoderState->lsp_old[3] = 15000;
      state->dtxDecoderState->lsp_old[4] = 8000;
      state->dtxDecoderState->lsp_old[5] = 0;
      state->dtxDecoderState->lsp_old[6] = -8000;
      state->dtxDecoderState->lsp_old[7] = -15000;
      state->dtxDecoderState->lsp_old[8] = -21000;
      state->dtxDecoderState->lsp_old[9] = -26000;
      state->dtxDecoderState->lsf_hist_ptr = 0;
      state->dtxDecoderState->log_pg_mean = 0;
      state->dtxDecoderState->log_en_hist_ptr = 0;

      /* initialize decoder lsf history */
      state->dtxDecoderState->lsf_hist[0] = 1384;
      state->dtxDecoderState->lsf_hist[1] = 2077;
      state->dtxDecoderState->lsf_hist[2] = 3420;
      state->dtxDecoderState->lsf_hist[3] = 5108;
      state->dtxDecoderState->lsf_hist[4] = 6742;
      state->dtxDecoderState->lsf_hist[5] = 8122;
      state->dtxDecoderState->lsf_hist[6] = 9863;
      state->dtxDecoderState->lsf_hist[7] = 11092;
      state->dtxDecoderState->lsf_hist[8] = 12714;
      state->dtxDecoderState->lsf_hist[9] = 13701;

      for ( i = 1; i < DTX_HIST_SIZE; i++ ) {
         memcpy( &state->dtxDecoderState->lsf_hist[M * i], &state->
               dtxDecoderState->lsf_hist[0], M <<2 );
      }
      memset( state->dtxDecoderState->lsf_hist_mean, 0, M * DTX_HIST_SIZE <<2 );

      /* initialize decoder log frame energy */
      for ( i = 0; i < DTX_HIST_SIZE; i++ ) {
         state->dtxDecoderState->log_en_hist[i] = state->dtxDecoderState->log_en
         ;
      }
      state->dtxDecoderState->log_en_adjust = 0;
      state->dtxDecoderState->dtxHangoverCount = DTX_HANG_CONST;
      state->dtxDecoderState->decAnaElapsedCount = 31;
      state->dtxDecoderState->sid_frame = 0;
      state->dtxDecoderState->valid_data = 0;
      state->dtxDecoderState->dtxHangoverAdded = 0;
      state->dtxDecoderState->dtxGlobalState = DTX;
      state->dtxDecoderState->data_updated = 0;
   }
   return;
}


/*
 * rx_dtx_handler
 *
 *
 * Parameters:
 *    st->dtxGlobalState      I: DTX state
 *    st->since_last_sid      B: Frames after last SID frame
 *    st->data_updated        I: SID update flag
 *    st->decAnaElapsedCount  B: state machine that synch with the GSMEFR txDtx machine
 *    st->dtxHangoverAdded    B: DTX hangover
 *    st->sid_frame           O: SID frame indicator
 *    st->valid_data          O: Vaild data indicator
 *    frame_type              O: Frame type
 *
 * Function:
 *    Find the new DTX state
 *
 * Returns:
 *    DTXStateType            DTX, DTX_MUTE or SPEECH
 */
static enum DTXStateType rx_dtx_handler( dtx_decState *st, enum RXFrameType frame_type )
{
   enum DTXStateType newState;
   enum DTXStateType encState;

   /* DTX if SID frame or previously in DTX{_MUTE} and (NO_RX OR BAD_SPEECH) */
   if ( table_SID[frame_type] | ( ( st->dtxGlobalState != SPEECH ) &
         table_speech_bad[frame_type] ) ) {
      newState = DTX;

      /* stay in mute for these input types */
      if ( ( st->dtxGlobalState == DTX_MUTE ) & table_mute[frame_type] ) {
         newState = DTX_MUTE;
      }

      /*
       * evaluate if noise parameters are too old
       * since_last_sid is reset when CN parameters have been updated
       */
      st->since_last_sid += 1;

      /* no update of sid parameters in DTX for a long while */
      if ((frame_type != RX_SID_UPDATE) & ( st->since_last_sid > DTX_MAX_EMPTY_THRESH )) {
         newState = DTX_MUTE;
      }
   }
   else {
      newState = SPEECH;
      st->since_last_sid = 0;
   }

   /*
    * reset the decAnaElapsed Counter when receiving CNI data the first
    * time, to robustify counter missmatch after handover
    * this might delay the bwd CNI analysis in the new decoder slightly.
    */
   if ( ( st->data_updated == 0 ) & ( frame_type == RX_SID_UPDATE ) ) {
      st->decAnaElapsedCount = 0;
   }

   /*
    * update the SPE-SPD DTX hangover synchronization
    * to know when SPE has added dtx hangover
    */
   st->decAnaElapsedCount += 1;
   st->dtxHangoverAdded = 0;
   encState = SPEECH;

   if ( table_DTX[frame_type] ) {
      encState = DTX;
      if( ( frame_type == RX_NO_DATA ) & ( newState == SPEECH ) ) {
         encState = SPEECH;
      }
   }

   if ( encState == SPEECH ) {
      st->dtxHangoverCount = DTX_HANG_CONST;
   }
   else {
      if ( st->decAnaElapsedCount > DTX_ELAPSED_FRAMES_THRESH ) {
         st->dtxHangoverAdded = 1;
         st->decAnaElapsedCount = 0;
         st->dtxHangoverCount = 0;
      }
      else if ( st->dtxHangoverCount == 0 ) {
         st->decAnaElapsedCount = 0;
      }
      else {
         st->dtxHangoverCount -= 1;
      }
   }

   if ( newState != SPEECH ) {
      /*
       * DTX or DTX_MUTE
       * CN data is not in a first SID, first SIDs are marked as SID_BAD
       * but will do backwards analysis if a hangover period has been added
       * according to the state machine above
       */
      st->sid_frame = 0;
      st->valid_data = 0;

      if ( frame_type == RX_SID_FIRST ) {
         st->sid_frame = 1;
      }
      else if ( frame_type == RX_SID_UPDATE ) {
         st->sid_frame = 1;
         st->valid_data = 1;
      }
      else if ( frame_type == RX_SID_BAD ) {
         st->sid_frame = 1;

         /* use old data */
         st->dtxHangoverAdded = 0;
      }
   }

   /* newState is used by both SPEECH AND DTX synthesis routines */
   return newState;
}


/*
 * Lsf_lsp
 *
 *
 * Parameters:
 *    lsf               I: vector of LSFs
 *    lsp               O: vector of LSPs
 *
 * Function:
 *    Transformation lsf to lsp, order M
 *
 * Returns:
 *    void
 */
static void Lsf_lsp( Word32 lsf[], Word32 lsp[] )
{
   Word32 i, ind, offset, tmp;


   for ( i = 0; i < M; i++ ) {
      /* ind = b8-b15 of lsf[i] */
      ind = lsf[i] >> 8;

      /* offset = b0-b7  of lsf[i] */
      offset = lsf[i] & 0x00ff;

      /* lsp[i] = table[ind]+ ((table[ind+1]-table[ind])*offset) / 256 */
      tmp = ( ( cos_table[ind+1]-cos_table[ind] )*offset ) << 1;
      lsp[i] = cos_table[ind] + ( tmp >> 9 );
   }
   return;
}


/*
 * D_plsf_3
 *
 *
 * Parameters:
 *    st->past_lsf_q    I: Past dequantized LFSs
 *    st->past_r_q      B: past quantized residual
 *    mode              I: AMR mode
 *    bfi               B: bad frame indicator
 *    indice            I: quantization indices of 3 submatrices, Q0
 *    lsp1_q            O: quantized 1st LSP vector
 *
 * Function:
 *    Decodes the LSP parameters using the received quantization indices.
 *    1st order MA prediction and split by 3 vector quantization (split-VQ)
 *
 * Returns:
 *    void
 */
static void D_plsf_3( D_plsfState *st, enum Mode mode, Word16 bfi, Word16 *
      indice, Word32 *lsp1_q )
{
   Word32 lsf1_r[M], lsf1_q[M];
   Word32 i, index, temp;
   const Word32 *p_cb1, *p_cb2, *p_cb3, *p_dico;


   /* if bad frame */
   if ( bfi != 0 ) {
      /* use the past LSFs slightly shifted towards their mean */
      for ( i = 0; i < M; i++ ) {
         /* lsfi_q[i] = ALPHA*past_lsf_q[i] + ONE_ALPHA*meanLsf[i]; */
         lsf1_q[i] = ( ( st->past_lsf_q[i] * ALPHA ) >> 15 ) + ( ( mean_lsf_3[i]
               * ONE_ALPHA ) >> 15 );
      }

      /* estimate past quantized residual to be used in next frame */
      if ( mode != MRDTX ) {
         for ( i = 0; i < M; i++ ) {
            /* temp  = meanLsf[i] +  pastR2_q[i] * pred_fac; */
            temp = mean_lsf_3[i] + ( ( st->past_r_q[i] * pred_fac[i] ) >> 15 );
            st->past_r_q[i] = lsf1_q[i] - temp;
         }
      }
      else {
         for ( i = 0; i < M; i++ ) {
            /* temp  = meanLsf[i] +  pastR2_q[i]; */
            temp = mean_lsf_3[i] + st->past_r_q[i];
            st->past_r_q[i] = lsf1_q[i] - temp;
         }
      }
   }

   /* if good LSFs received */
   else {
      if ( ( mode == MR475 ) | ( mode == MR515 ) ) {
         /* MR475, MR515 */
         p_cb1 = dico1_lsf_3;
         p_cb2 = dico2_lsf_3;
         p_cb3 = mr515_3_lsf;
      }
      else if ( mode == MR795 ) {
         /* MR795 */
         p_cb1 = mr795_1_lsf;
         p_cb2 = dico2_lsf_3;
         p_cb3 = dico3_lsf_3;
      }
      else {
         /* MR59, MR67, MR74, MR102, MRDTX */
         p_cb1 = dico1_lsf_3;
         p_cb2 = dico2_lsf_3;
         p_cb3 = dico3_lsf_3;
      }

      /* decode prediction residuals from 3 received indices */
      index = *indice++;
      p_dico = &p_cb1[index + index + index];
      index = *indice++;
      lsf1_r[0] = *p_dico++;
      lsf1_r[1] = *p_dico++;
      lsf1_r[2] = *p_dico++;

      if ( ( mode == MR475 ) | ( mode == MR515 ) ) {
         /* MR475, MR515 only using every second entry */
         index = index << 1;
      }
      p_dico = &p_cb2[index + index + index];
      index = *indice++;
      lsf1_r[3] = *p_dico++;
      lsf1_r[4] = *p_dico++;
      lsf1_r[5] = *p_dico++;
      p_dico = &p_cb3[index << 2];
      lsf1_r[6] = *p_dico++;
      lsf1_r[7] = *p_dico++;
      lsf1_r[8] = *p_dico++;
      lsf1_r[9] = *p_dico++;

      /* Compute quantized LSFs and update the past quantized residual */
      if ( mode != MRDTX ) {
         for ( i = 0; i < M; i++ ) {
            lsf1_q[i] = lsf1_r[i] + ( mean_lsf_3[i] + ( ( st->past_r_q[i] *
                  pred_fac[i] ) >> 15 ) );
         }
         memcpy( st->past_r_q, lsf1_r, M <<2 );
      }
      else {
         for ( i = 0; i < M; i++ ) {
            lsf1_q[i] = lsf1_r[i] + ( mean_lsf_3[i] + st->past_r_q[i] );
         }
         memcpy( st->past_r_q, lsf1_r, M <<2 );
      }
   }

   /* verification that LSFs has minimum distance of LSF_GAP Hz */
   temp = LSF_GAP;

   for ( i = 0; i < M; i++ ) {
      if ( lsf1_q[i] < temp ) {
         lsf1_q[i] = temp;
      }
      temp = lsf1_q[i] + LSF_GAP;
   }
   memcpy( st->past_lsf_q, lsf1_q, M <<2 );

   /*  convert LSFs to the cosine domain */
   Lsf_lsp( lsf1_q, lsp1_q );
   return;
}


/*
 * pseudonoise
 *
 *
 * Parameters:
 *    shift_reg         B: Old CN generator shift register state
 *    no_bits           I: Number of bits
 *
 * Function:
 *    pseudonoise
 *
 * Returns:
 *    noise_bits
 */
static Word32 pseudonoise( Word32 *shift_reg, Word32 no_bits )
{
   Word32 noise_bits, Sn, i;
   Word32 s_reg;


   s_reg = *shift_reg;
   noise_bits = 0;

   for ( i = 0; i < no_bits; i++ ) {
      /* State n == 31 */
      Sn = s_reg & 0x00000001L;

      /* State n == 3 */
      if ( s_reg & 0x10000000L ) {
         Sn = Sn ^ 0x1L;
      }
      else {
         Sn = Sn ^ 0x0L;
      }
      noise_bits = ( noise_bits << 1 ) | ( s_reg & 1 );
      s_reg = s_reg >> 1;

      if ( Sn & 1 ) {
         s_reg = s_reg | 0x40000000L;
      }
   }
   *shift_reg = s_reg;
   return noise_bits;
}


/*
 * Lsp_lsf
 *
 *
 * Parameters:
 *    lsp               I: LSP vector (range: -1<=val<1)
 *    lsf               O: LSF vector Old CN generator shift register state
 *
 * Function:
 *    Transformation lsp to lsf, LPC order M
 *    lsf[i] = arccos(lsp[i])/(2*pi)
 *
 * Returns:
 *    void
 */
static void Lsp_lsf( Word32 lsp[], Word32 lsf[] )
{
   Word32 i, ind = 63;   /* begin at end of table -1 */


   for ( i = M - 1; i >= 0; i-- ) {
      /* find value in table that is just greater than lsp[i] */
      while ( cos_table[ind] < lsp[i] ) {
         ind--;
      }
      lsf[i] = ( ( ( ( lsp[i] - cos_table[ind] ) * acos_slope[ind] ) + 0x800 )
            >> 12 ) + ( ind << 8 );
   }
   return;
}


/*
 * Reorder_lsf
 *
 *
 * Parameters:
 *    lsf            B: vector of LSFs (range: 0<=val<=0.5)
 *    min_dist       I: minimum required distance
 *
 * Function:
 *    Make sure that the LSFs are properly ordered and to keep a certain minimum
 *    distance between adjacent LSFs. LPC order = M.
 *
 * Returns:
 *    void
 */
static void Reorder_lsf( Word32 *lsf, Word32 min_dist )
{
   Word32 lsf_min, i;


   lsf_min = min_dist;

   for ( i = 0; i < M; i++ ) {
      if ( lsf[i] < lsf_min ) {
         lsf[i] = lsf_min;
      }
      lsf_min = lsf[i] + min_dist;
   }
}

/* VC5.0 Global optimization does not work with this function */
#if _MSC_VER == 1100
#pragma optimize( "g", off )
#endif
/*
 * Get_lsp_pol
 *
 *
 * Parameters:
 *    lsp               I: line spectral frequencies
 *    f                 O: polynomial F1(z) or F2(z)
 *
 * Function:
 *    Find the polynomial F1(z) or F2(z) from the LSPs.
 *
 *    F1(z) = product ( 1 - 2 lsp[i] z^-1 + z^-2 )
 *             i=0,2,4,6,8
 *    F2(z) = product   ( 1 - 2 lsp[i] z^-1 + z^-2 )
 *             i=1,3,5,7,9
 *
 *    where lsp[] is the LSP vector in the cosine domain.
 *
 *    The expansion is performed using the following recursion:
 *
 *    f[0] = 1
 *    b = -2.0 * lsp[0]
 *    f[1] = b
 *    for i=2 to 5 do
 *       b = -2.0 * lsp[2*i-2];
 *       f[i] = b*f[i-1] + 2.0*f[i-2];
 *       for j=i-1 down to 2 do
 *          f[j] = f[j] + b*f[j-1] + f[j-2];
 *       f[1] = f[1] + b;
 *
 * Returns:
 *    void
 */
static void Get_lsp_pol( Word32 *lsp, Word32 *f )
{
   volatile Word32 f0, f1, f2, f3, f4, f5;
   Word32 l1, l2, l3, l4;


   /* f[0] = 1.0; */
   f0 = 16777216L;

   /* f1 = *lsp * -1024; */
   f1 = -lsp[0] << 10;
   l1 = lsp[2];
   l2 = lsp[4];
   l3 = lsp[6];
   l4 = lsp[8];
   f2 = f0 << 1;
   f2 -= ( ( ( f1 >> 16 ) * l1 ) + ( ( ( f1 & 0xFFFE ) * l1 ) >> 16 ) ) << 2;
   f1 -= l1 << 10;
   f3 = f1 << 1;
   f3 -= ( ( ( f2 >> 16 ) * l2 ) + ( ( ( f2 & 0xFFFE ) * l2 ) >> 16 ) ) << 2;
   f2 += f0;
   f2 -= ( ( ( f1 >> 16 ) * l2 ) + ( ( ( f1 & 0xFFFE ) * l2 ) >> 16 ) ) << 2;
   f1 -= l2 << 10;
   f4 = f2 << 1;
   f4 -= ( ( ( f3 >> 16 ) * l3 ) + ( ( ( f3 & 0xFFFE ) * l3 ) >> 16 ) ) << 2;
   f3 += f1;
   f3 -= ( ( ( f2 >> 16 ) * l3 ) + ( ( ( f2 & 0xFFFE ) * l3 ) >> 16 ) ) << 2;
   f2 += f0;
   f2 -= ( ( ( f1 >> 16 ) * l3 ) + ( ( ( f1 & 0xFFFE ) * l3 ) >> 16 ) ) << 2;
   f1 -= l3 << 10;
   f5 = f3 << 1;
   f5 -= ( ( ( f4 >> 16 ) * l4 ) + ( ( ( f4 & 0xFFFE ) * l4 ) >> 16 ) ) << 2;
   f4 += f2;
   f4 -= ( ( ( f3 >> 16 ) * l4 ) + ( ( ( f3 & 0xFFFE ) * l4 ) >> 16 ) ) << 2;
   f3 += f1;
   f3 -= ( ( ( f2 >> 16 ) * l4 ) + ( ( ( f2 & 0xFFFE ) * l4 ) >> 16 ) ) << 2;
   f2 += f0;
   f2 -= ( ( ( f1 >> 16 ) * l4 ) + ( ( ( f1 & 0xFFFE ) * l4 ) >> 16 ) ) << 2;
   f1 -= l4 << 10;
   f[0] = f0;
   f[1] = f1;
   f[2] = f2;
   f[3] = f3;
   f[4] = f4;
   f[5] = f5;
   return;
}
#if _MSC_VER == 1100
#pragma optimize( "", on )
#endif


/*
 * Lsp_Az
 *
 *
 * Parameters:
 *    lsp                 I: Line spectral frequencies
 *    a                   O: Predictor coefficients
 *
 * Function:
 *    Converts from the line spectral pairs (LSP) to LP coefficients,
 *    for a 10th order filter.
 *
 *    Find the coefficients of F1(z) and F2(z)
 *    Multiply F1(z) by 1+z^{-1} and F2(z) by 1-z^{-1}
 *    A(z) = ( F1(z) + F2(z) ) / 2
 *
 * Returns:
 *    void
 */
static void Lsp_Az( Word32 lsp[], Word32 a[] )
{
   Word32 f1[6], f2[6];
   Word32 T0, i, j;


   Get_lsp_pol( &lsp[0], f1 );
   Get_lsp_pol( &lsp[1], f2 );

   for ( i = 5; i > 0; i-- ) {
      f1[i] += f1[i - 1];
      f2[i] -= f2[i - 1];
   }
   a[0] = 4096;

   for ( i = 1, j = 10; i <= 5; i++, j-- ) {
      T0 = f1[i] + f2[i];
      a[i] = (Word16)(T0 >> 13);  /* emulate fixed point bug */
      if ( ( T0 & 4096 ) != 0 ) {
         a[i]++;
      }
      T0 = f1[i] - f2[i];
      a[j] = (Word16)(T0 >> 13);   /* emulate fixed point bug */

      if ( ( T0 & 4096 ) != 0 ) {
         a[j]++;
      }
   }
   return;
}


/*
 * A_Refl
 *
 *
 * Parameters:
 *    a                 I: Directform coefficients
 *    refl              O: Reflection coefficients
 *
 * Function:
 *    Converts from the directform coefficients to reflection coefficients
 *
 * Returns:
 *    void
 */
static void A_Refl( Word32 a[], Word32 refl[] )
{
   /* local variables */
   int normShift;
   Word32 aState[M], bState[M];
   Word32 normProd, acc, temp, mult, scale, i, j;


   /* initialize states */
   memcpy( aState, a, M <<2 );

   /* backward Levinson recursion */
   for ( i = M - 1; i >= 0; i-- ) {
      if ( labs( aState[i] ) >= 4096 ) {
         goto ExitRefl;
      }
      refl[i] = aState[i] << 3;
      temp = ( refl[i] * refl[i] ) << 1;
      acc = ( MAX_32 - temp );
      normShift=0;
      if (acc != 0){
         temp = acc;
         while (!(temp & 0x40000000))
         {
            normShift++;
            temp = temp << 1;
         }
      }
      else{
         normShift = 0;
      }
      scale = 15 - normShift;
      acc = ( acc << normShift );
      temp = ( acc + ( Word32 )0x00008000L );

      if ( temp > 0 ) {
         normProd = temp >> 16;
         mult = 0x20000000L / normProd;
      }
      else
         mult = 16384;

      for ( j = 0; j < i; j++ ) {
         acc = aState[j] << 16;
         acc -= ( refl[i] * aState[i - j - 1] ) << 1;
         temp = ( acc + ( Word32 )0x00008000L ) >> 16;
         temp = ( mult * temp ) << 1;

         if ( scale > 0 ) {
            if ( ( temp & ( ( Word32 )1 << ( scale - 1 ) ) ) != 0 ) {
               temp = ( temp >> scale ) + 1;
            }
            else
               temp = ( temp >> scale );
         }
         else
            temp = ( temp >> scale );

         if ( labs( temp ) > 32767 ) {
            goto ExitRefl;
         }
         bState[j] = temp;
      }
      memcpy( aState, bState, i <<2 );
   }
   return;
ExitRefl:
   memset( refl, 0, M <<2 );
}


/*
 * Log2_norm
 *
 *
 * Parameters:
 *    x                 I: input value
 *    exp               I: exponent
 *    exponent          O: Integer part of Log2. (range: 0<=val<=30)
 *    fraction          O: Fractional part of Log2. (range: 0<=val<1)
 *
 * Function:
 *    Computes log2
 *
 *    Computes log2(L_x, exp),  where   L_x is positive and
 *    normalized, and exp is the normalisation exponent
 *    If L_x is negative or zero, the result is 0.
 *
 *    The function Log2(L_x) is approximated by a table and linear
 *    interpolation. The following steps are used to compute Log2(L_x)
 *
 *    exponent = 30-normExponent
 *    i = bit25-b31 of L_x;  32<=i<=63  (because of normalization).
 *    a = bit10-b24
 *    i -=32
 *    fraction = table[i]<<16 - (table[i] - table[i+1]) * a * 2
 *
 * Returns:
 *    void
 */
static void Log2_norm( Word32 x, Word32 exp, Word32 *exponent, Word32 *
      fraction )
{
   Word32 y, i, a;


   if ( x <= 0 ) {
      *exponent = 0;
      *fraction = 0;
      return;
   }

   /* Extract b25-b31 */
   i = x >> 25;
   i = i - 32;

   /* Extract b10-b24 of fraction */
   a = x >> 9;
   a = a & 0xFFFE;   /* 2a */

   /* fraction */
   y = ( log2_table[i] << 16 ) - a * ( log2_table[i] - log2_table[i + 1] );
   *fraction = y >> 16;
   *exponent = 30 - exp;
   return;
}


/*
 * Log2
 *
 *
 * Parameters:
 *    x                 I: input value
 *    exponent          O: Integer part of Log2. (range: 0<=val<=30)
 *    fraction          O: Fractional part of Log2. (range: 0<=val<1)
 *
 * Function:
 *    Computes log2(L_x)
 *    If x is negative or zero, the result is 0.
 *
 * Returns:
 *    void
 */
static void Log2( Word32 x, Word32 *exponent, Word32 *fraction )
{
   int tmp, exp=0;

   if (x != 0){
         tmp = x;
         while (!((tmp & 0x80000000) ^ ((tmp & 0x40000000) << 1)))
         {
            exp++;
            tmp = tmp << 1;
         }
      }
   Log2_norm( x <<exp, exp, exponent, fraction );
}


/*
 * Pow2
 *
 *
 * Parameters:
 *    exponent          I: Integer part. (range: 0<=val<=30)
 *    fraction          O: Fractional part. (range: 0.0<=val<1.0)
 *
 * Function:
 *    pow(2.0, exponent.fraction)
 *
 *    The function Pow2(L_x) is approximated by a table and linear interpolation.
 *
 *    i = bit10-b15 of fraction, 0 <= i <= 31
 *    a = biT0-b9   of fraction
 *    x = table[i]<<16 - (table[i] - table[i+1]) * a * 2
 *    x = L_x >> (30-exponent) (with rounding)
 *
 * Returns:
 *    result (range: 0<=val<=0x7fffffff)
 */
static Word32 Pow2( Word32 exponent, Word32 fraction )
{
   Word32 i, a, tmp, x, exp;


   /* Extract b10-b16 of fraction */
   i = fraction >> 10;

   /* Extract b0-b9 of fraction */
   a = ( fraction << 5 ) & 0x7fff;

   /* table[i] << 16 */
   x = pow2_table[i] << 16;

   /* table[i] - table[i+1] */
   tmp = pow2_table[i] - pow2_table[i + 1];

   /* L_x -= tmp*a*2 */
   x -= ( tmp * a ) << 1;

   if ( exponent >= -1 ) {
      exp = ( 30 - exponent );

      /* Rounding */
      if ( ( x & ( ( Word32 )1 << ( exp - 1 ) ) ) != 0 ) {
         x = ( x >> exp ) + 1;
      }
      else
         x = x >> exp;
   }
   else
      x = 0;
   return( x );
}


/*
 * Build_CN_code
 *
 *
 * Parameters:
 *    seed              B: Old CN generator shift register state
 *    cod               O: Generated CN fixed codebook vector
 *
 * Function:
 *    Generate CN fixed codebook vector
 *
 * Returns:
 *    void
 */
static void Build_CN_code( Word32 *seed, Word32 cod[] )
{
   Word32 i, j, k;


   memset( cod, 0, L_SUBFR <<2 );

   for ( k = 0; k < 10; k++ ) {
      i = pseudonoise( seed, 2 );   /* generate pulse position */
      i = ( i * 20 ) >> 1;
      i = ( i + k );
      j = pseudonoise( seed, 1 );   /* generate sign           */

      if ( j > 0 ) {
         cod[i] = 4096;
      }
      else {
         cod[i] = -4096;
      }
   }
   return;
}


/*
 * Build_CN_param
 *
 *
 * Parameters:
 *    seed              B: Old CN generator shift register state
 *    nParam            I: number of params
 *    paramSizeTable    I: size of params
 *    parm              O: CN Generated params
 *
 * Function:
 *    Generate parameters for comfort noise generation
 *
 * Returns:
 *    void
 */
static void Build_CN_param( Word16 *seed, enum Mode mode, Word16 parm[] )
{
   Word32 i;
   const Word32 *p;


   *seed = ( Word16 )( ( *seed * 31821 ) + 13849L );
   p = &window_200_40[ * seed & 0x7F];

   switch ( mode ) {
      case MR122:
         for ( i = 0; i < PRMNO_MR122; i++ ) {
            parm[i] = ( Word16 )( *p++ & ~( 0xFFFF << bitno_MR122[i] ) );
         }
         break;

      case MR102:
         for ( i = 0; i < PRMNO_MR102; i++ ) {
            parm[i] = ( Word16 )( *p++ & ~( 0xFFFF << bitno_MR102[i] ) );
         }
         break;

      case MR795:
         for ( i = 0; i < PRMNO_MR795; i++ ) {
            parm[i] = ( Word16 )( *p++ & ~( 0xFFFF << bitno_MR795[i] ) );
         }
         break;

      case MR74:
         for ( i = 0; i < PRMNO_MR74; i++ ) {
            parm[i] = ( Word16 )( *p++ & ~( 0xFFFF << bitno_MR74[i] ) );
         }
         break;

      case MR67:
         for ( i = 0; i < PRMNO_MR67; i++ ) {
            parm[i] = ( Word16 )( *p++ & ~( 0xFFFF << bitno_MR67[i] ) );
         }
         break;

      case MR59:
         for ( i = 0; i < PRMNO_MR59; i++ ) {
            parm[i] = ( Word16 )( *p++ & ~( 0xFFFF << bitno_MR59[i] ) );
         }
         break;

      case MR515:
         for ( i = 0; i < PRMNO_MR515; i++ ) {
            parm[i] = ( Word16 )( *p++ & ~( 0xFFFF << bitno_MR515[i] ) );
         }
         break;

      case MR475:
         for ( i = 0; i < PRMNO_MR475; i++ ) {
            parm[i] = ( Word16 )( *p++ & ~( 0xFFFF << bitno_MR475[i] ) );
         }
         break;
   }
}


/*
 * Syn_filt
 *
 *
 * Parameters:
 *    a                 I: prediction coefficients [M+1]
 *    x                 I: input signal
 *    y                 O: output signal
 *    lg                I: size of filtering
 *    mem               B: memory associated with this filtering
 *    update            I: 0=no update, 1=update of memory.
 *
 * Function:
 *    Perform synthesis filtering through 1/A(z).
 *
 * Returns:
 *    void
 */
static Word32 Syn_filt( Word32 a[], Word32 x[], Word32 y[], Word32 lg, Word32 mem[]
      , Word32 update )
{
   Word32 tmp[50];   /* malloc is slow */
   Word32 s, a0, overflow = 0;
   Word32 *yy, *yy_limit;


   /* Copy mem[] to yy[] */
   memcpy( tmp, mem, 40 );
   yy = tmp + M;
   yy_limit = yy + lg;
   a0 = a[0];

   /* Do the filtering. */
   while ( yy < yy_limit ) {

      s = *x++ * a0;
      s -= yy[-1] * a[1];
      s -= yy[-2] * a[2];
      s -= yy[-3] * a[3];
      s -= yy[-4] * a[4];
      s -= yy[-5] * a[5];
      s -= yy[-6] * a[6];
      s -= yy[-7] * a[7];
      s -= yy[-8] * a[8];
      s -= yy[-9] * a[9];
      s -= yy[-10] * a[10];
      if ( labs( s ) < 0x7ffffff )
         *yy = ( s + 0x800L ) >> 12;
      else if ( s > 0 ) {
         *yy = 32767;
         overflow = 1;
      }
      else {
         *yy = -32768;
         overflow = 1;
      }
      yy++;
   }
   memcpy( y, &tmp[M], lg <<2 );

   /* Update of memory if update==1 */
   if ( update ) {
      memcpy( mem, &y[lg - M], 40 );
   }
   return overflow;
}

/*
 * Syn_filt_overflow
 *
 *
 * Parameters:
 *    a                 I: prediction coefficients [M+1]
 *    x                 I: input signal
 *    y                 O: output signal
 *    lg                I: size of filtering
 *    mem               B: memory associated with this filtering
 *    update            I: 0=no update, 1=update of memory.
 *
 * Function:
 *    Perform synthesis filtering through 1/A(z).
 *    Saturate after every multiplication.
 * Returns:
 *    void
 */
static void Syn_filt_overflow( Word32 a[], Word32 x[], Word32 y[], Word32 lg, Word32 mem[]
      , Word32 update )
{
   Word32 tmp[50];   /* malloc is slow */
   Word32 i, j, s, a0;
   Word32 *yy;


   /* Copy mem[] to yy[] */
   memcpy( tmp, mem, 40 );
   yy = tmp + M;
   a0 = a[0];

   /* Do the filtering. */
   for ( i = 0; i < lg; i++ ) {
      s = x[i] * a0;

      for ( j = 1; j <= M; j++ ) {
         s -= a[j] * yy[ - j];
         if (s > 1073741823){
            s = 1073741823;
         }
         else if ( s < -1073741824) {
            s = -1073741824;
         }
      }

      if ( labs( s ) < 0x7FFE800 )
         *yy = ( s + 0x800L ) >> 12;
      else if ( s > 0 ) {
         *yy = 32767;
      }
      else {
         *yy = -32768;
      }
      yy++;
   }
   memcpy( y, &tmp[M], lg <<2 );

   /* Update of memory if update==1 */
   if ( update ) {
      memcpy( mem, &y[lg - M], 40 );
   }
   return;
}

/*
 * dtx_dec
 *
 *
 * Parameters:
 *    st                            B: DTX state struct
 *    mem_syn                       I: AMR decoder state
 *    lsfState                      B: LSF state struct
 *    pred_state->past_qua_en       O: table of past quantized energies
 *    pred_state->past_qua_en_MR122 O: table of past quantized energies MR122
 *    averState->hangVar            O:
 *    averState->hangCount          O: hangover variable
 *    new_state                     I: new DTX state
 *    mode                          I: AMR mode
 *    parm                          I: vector of synthesis parameters
 *    synth                         O: synthesised speech
 *    A_t                           O: decoded LP filter in 4 subframes
 *
 * Function:
 *    DTX
 *
 * Returns:
 *    void
 */
static void dtx_dec( dtx_decState *st, Word32 *mem_syn, D_plsfState *lsfState,
      gc_predState *pred_state, Cb_gain_averageState *averState, enum
      DTXStateType new_state, enum Mode mode, Word16 parm[], Word32 synth[],
      Word32 A_t[] )
{
   Word32 ex[L_SUBFR], acoeff[11], acoeff_variab[M + 1], lsp_int[M];
   Word32 refl[M], lsf[M], lsf_int[M], lsf_int_variab[M], lsp_int_variab[M];
   Word32 i, j, int_fac, log_en_int, pred_err, log_pg_e, log_pg_m, log_pg;
   Word32 negative, lsf_mean, lsf_variab_index, lsf_variab_factor, ptr;
   Word16 log_en_index, log_en_int_e, log_en_int_m, level, ma_pred_init,
         tmp_int_length;


   if ( ( st->dtxHangoverAdded != 0 ) & ( st->sid_frame != 0 ) ) {
      /*
       * sidFirst after dtx hangover period
       * or sidUpd after dtxhangover
       */
      /* set log_en_adjust to correct value */
      st->log_en_adjust = dtx_log_en_adjust[mode];
      ptr = st->lsf_hist_ptr + M;

      if ( ptr == 80 ) {
         ptr = 0;
      }
      memcpy( &st->lsf_hist[ptr], &st->lsf_hist[st->lsf_hist_ptr], M <<2 );
      ptr = st->log_en_hist_ptr + 1;

      if ( ptr == DTX_HIST_SIZE ) {
         ptr = 0;
      }
      st->log_en_hist[ptr] = st->log_en_hist[st->log_en_hist_ptr];   /* Q11 */

      /*
       * compute mean log energy and lsp
       * from decoded signal (SID_FIRST)
       */
      st->log_en = 0;
      memset( lsf, 0, M <<2 );

      /* average energy and lsp */
      for ( i = 0; i < DTX_HIST_SIZE; i++ ) {
         st->log_en = st->log_en + ( st->log_en_hist[i] >> 3 );

         for ( j = 0; j < M; j++ ) {
            lsf[j] += st->lsf_hist[i * M + j];
         }
      }

      for ( j = 0; j < M; j++ ) {
         lsf[j] = lsf[j] >> 3;   /* divide by 8 */
      }
      Lsf_lsp( lsf, st->lsp );

      /*
       * make log_en speech coder mode independent
       * added again later before synthesis
       */
      st->log_en = st->log_en - st->log_en_adjust;

      /* compute lsf variability vector */
      memcpy( st->lsf_hist_mean, st->lsf_hist, 80 <<2 );

      for ( i = 0; i < M; i++ ) {
         lsf_mean = 0;

         /* compute mean lsf */
         for ( j = 0; j < 8; j++ ) {
            lsf_mean += st->lsf_hist_mean[i + j * M];
         }
         lsf_mean = lsf_mean >> 3;

         /*
          * subtract mean and limit to within reasonable limits
          * moreover the upper lsf's are attenuated
          */
         for ( j = 0; j < 8; j++ ) {
            /* subtract mean */
            st->lsf_hist_mean[i + j * M] = st->lsf_hist_mean[i + j * M] -
                  lsf_mean;

            /* attenuate deviation from mean, especially for upper lsf's */
            st->lsf_hist_mean[i + j * M] = ( st->lsf_hist_mean[i + j * M] *
                  lsf_hist_mean_scale[i] ) >> 15;

            /* limit the deviation */
            if ( st->lsf_hist_mean[i + j * M] < 0 ) {
               negative = 1;
            }
            else {
               negative = 0;
            }
            st->lsf_hist_mean[i + j * M] = labs( st->lsf_hist_mean[i + j * M] );

            /* apply soft limit */
            if ( st->lsf_hist_mean[i + j * M] > 655 ) {
               st->lsf_hist_mean[i + j * M] = 655 + ( ( st->lsf_hist_mean[i + j
                     * M] - 655 ) >> 2 );
            }

            /* apply hard limit */
            if ( st->lsf_hist_mean[i + j * M] > 1310 ) {
               st->lsf_hist_mean[i + j * M] = 1310;
            }

            if ( negative != 0 ) {
               st->lsf_hist_mean[i + j * M] = -st->lsf_hist_mean[i + j * M];
            }
         }
      }
   }

   if ( st->sid_frame != 0 ) {
      /*
       * Set old SID parameters, always shift
       * even if there is no new valid_data
       */
      memcpy( st->lsp_old, st->lsp, M <<2 );
      st->old_log_en = st->log_en;

      if ( st->valid_data != 0 ) /* new data available (no CRC) */ {
      /* Compute interpolation factor, since the division only works
       * for values of since_last_sid < 32 we have to limit the
       * interpolation to 32 frames
       */
         tmp_int_length = st->since_last_sid;
         st->since_last_sid = 0;

         if ( tmp_int_length > 32 ) {
            tmp_int_length = 32;
         }

         if ( tmp_int_length >= 2 ) {
            st->true_sid_period_inv = 0x2000000 / ( tmp_int_length
                  << 10 );
         }
         else {
            st->true_sid_period_inv = 16384;   /* 0.5 it Q15 */
         }
         memcpy( lsfState->past_r_q, &past_rq_init[parm[0] * M], M <<2 );
         D_plsf_3( lsfState, MRDTX, 0, &parm[1], st->lsp );

         /* reset for next speech frame */
         memset( lsfState->past_r_q, 0, M <<2 );
         log_en_index = parm[4];

         /* Q11 and divide by 4 */
         st->log_en = ( Word16 )( log_en_index << 9 );

         /* Subtract 2.5 in Q11 */
         st->log_en = ( Word16 )( st->log_en - 5120 );

         /* Index 0 is reserved for silence */
         if ( log_en_index == 0 ) {
            st->log_en = MIN_16;
         }

         /*
          * no interpolation at startup after coder reset
          * or when SID_UPD has been received right after SPEECH
          */
         if ( ( st->data_updated == 0 ) || ( st->dtxGlobalState == SPEECH ) ) {
            memcpy( st->lsp_old, st->lsp, M <<2 );
            st->old_log_en = st->log_en;
         }
      }   /* endif valid_data */

      /* initialize gain predictor memory of other modes */
      ma_pred_init = ( Word16 )( ( st->log_en >> 1 ) - 9000 );

      if ( ma_pred_init > 0 ) {
         ma_pred_init = 0;
      }

      if ( ma_pred_init < - 14436 ) {
         ma_pred_init = -14436;
      }
      pred_state->past_qua_en[0] = ma_pred_init;
      pred_state->past_qua_en[1] = ma_pred_init;
      pred_state->past_qua_en[2] = ma_pred_init;
      pred_state->past_qua_en[3] = ma_pred_init;

      /* past_qua_en for other modes than MR122 */
      ma_pred_init = ( Word16 )( ( 5443*ma_pred_init ) >> 15 );

      /* scale down by factor 20*log10(2) in Q15 */
      pred_state->past_qua_en_MR122[0] = ma_pred_init;
      pred_state->past_qua_en_MR122[1] = ma_pred_init;
      pred_state->past_qua_en_MR122[2] = ma_pred_init;
      pred_state->past_qua_en_MR122[3] = ma_pred_init;
   }   /* endif sid_frame */

   /*
    * CN generation
    * recompute level adjustment factor Q11
    * st->log_en_adjust = 0.9*st->log_en_adjust +
    *                     0.1*dtx_log_en_adjust[mode]);
    */
   st->log_en_adjust = ( Word16 )( ( ( st->log_en_adjust * 29491 ) >> 15 ) + ( (
         ( dtx_log_en_adjust[mode] << 5 ) * 3277 ) >> 20 ) );

   /* Interpolate SID info */
   /* Q10 */
   if ( st->since_last_sid > 30 )
      int_fac = 32767;
   else
      int_fac = ( Word16 )( (st->since_last_sid + 1) << 10 );

   /* Q10 * Q15 -> Q10 */
   int_fac = ( int_fac * st->true_sid_period_inv ) >> 15;

   /* Maximize to 1.0 in Q10 */
   if ( int_fac > 1024 ) {
      int_fac = 1024;
   }

   /* Q10 -> Q14 */
   int_fac = ( Word16 )( int_fac << 4 );

   /* Q14 * Q11->Q26 */
   log_en_int = ( int_fac * st->log_en ) << 1;

   for ( i = 0; i < M; i++ ) {
      /* Q14 * Q15 -> Q14 */
      lsp_int[i] = ( int_fac * st->lsp[i] ) >> 15;
   }

   /* 1-k in Q14 */
   int_fac = 16384 - int_fac;

   /* (Q14 * Q11 -> Q26) + Q26 -> Q26 */
   log_en_int += ( int_fac * st->old_log_en ) << 1;

   for ( i = 0; i < M; i++ ) {
      /* Q14 + (Q14 * Q15 -> Q14) -> Q14 */
      lsp_int[i] = lsp_int[i] + ( ( int_fac * st->lsp_old[i] ) >> 15 );

      /* Q14 -> Q15 */
      lsp_int[i] = lsp_int[i] << 1;
   }

   /* compute the amount of lsf variability */
   /* -0.6 in Q12 */
   lsf_variab_factor = st->log_pg_mean - 2457;

   /* *0.3 Q12*Q15 -> Q12 */
   lsf_variab_factor = 4096 - ( ( lsf_variab_factor * 9830 ) >> 15 );

   /* limit to values between 0..1 in Q12 */
   if ( lsf_variab_factor >= 4096 ) {
      lsf_variab_factor = 32767;
   }
   else if ( lsf_variab_factor < 0 ) {
      lsf_variab_factor = 0;
   }
   else
      lsf_variab_factor = lsf_variab_factor << 3;   /* -> Q15 */

   /* get index of vector to do variability with */
   lsf_variab_index = pseudonoise( &st->pn_seed_rx, 3 );

   /* convert to lsf */
   Lsp_lsf( lsp_int, lsf_int );

   /* apply lsf variability */
   memcpy( lsf_int_variab, lsf_int, M <<2 );

   for ( i = 0; i < M; i++ ) {
      lsf_int_variab[i] = lsf_int_variab[i] + ( ( lsf_variab_factor * st->
            lsf_hist_mean[i + lsf_variab_index * M] ) >> 15 );
   }

   /* make sure that LSP's are ordered */
   Reorder_lsf( lsf_int, LSF_GAP );
   Reorder_lsf( lsf_int_variab, LSF_GAP );

   /* copy lsf to speech decoders lsf state */
   memcpy( lsfState->past_lsf_q, lsf_int, M <<2 );

   /* convert to lsp */
   Lsf_lsp( lsf_int, lsp_int );
   Lsf_lsp( lsf_int_variab, lsp_int_variab );

     /* Compute acoeffs Q12 acoeff is used for level
      * normalization and Post_Filter, acoeff_variab is
      * used for synthesis filter
      * by doing this we make sure that the level
      * in high frequenncies does not jump up and down
      */
   Lsp_Az( lsp_int, acoeff );
   Lsp_Az( lsp_int_variab, acoeff_variab );

   /* For use in Post_Filter */
   memcpy( &A_t[0], acoeff, MP1 <<2 );
   memcpy( &A_t[MP1], acoeff, MP1 <<2 );
   memcpy( &A_t[MP1 <<1], acoeff, MP1 <<2 );
   memcpy( &A_t[MP1 + MP1 + MP1], acoeff, MP1 <<2 );

   /* Compute reflection coefficients Q15 */
   A_Refl( &acoeff[1], refl );

   /* Compute prediction error in Q15 */
   /* 0.99997 in Q15 */
   pred_err = MAX_16;

   for ( i = 0; i < M; i++ ) {
      pred_err = ( pred_err * ( MAX_16 - ( ( refl[i] * refl[i] ) >> 15 ) ) ) >>
            15;
   }

   /* compute logarithm of prediction gain */
   Log2( pred_err, &log_pg_e, &log_pg_m );

   /* convert exponent and mantissa to Word16 Q12 */
   /* Q12 */
   log_pg = ( log_pg_e - 15 ) << 12;
   /* saturate */
   if (log_pg < -32768) {
      log_pg = -32768;
   }
   log_pg = ( -( log_pg + ( log_pg_m >> 3 ) ) ) >> 1;
   st->log_pg_mean = ( Word16 )( ( ( 29491*st->log_pg_mean ) >> 15 ) + ( ( 3277
         * log_pg ) >> 15 ) );

   /* Compute interpolated log energy */
   /* Q26 -> Q16 */
   log_en_int = log_en_int >> 10;

   /* Add 4 in Q16 */
   log_en_int += 262144L;

   /* subtract prediction gain */
   log_en_int = log_en_int - ( log_pg << 4 );

   /* adjust level to speech coder mode */
   log_en_int += st->log_en_adjust << 5;
   log_en_int_e = ( Word16 )( log_en_int >> 16 );
   log_en_int_m = ( Word16 )( ( log_en_int - ( log_en_int_e << 16 ) ) >> 1 );

   /* Q4 */
   level = ( Word16 )( Pow2( log_en_int_e, log_en_int_m ) );

   for ( i = 0; i < 4; i++ ) {
      /* Compute innovation vector */
      Build_CN_code( &st->pn_seed_rx, ex );

      for ( j = 0; j < L_SUBFR; j++ ) {
         ex[j] = ( level * ex[j] ) >> 15;
      }

      /* Synthesize */
      Syn_filt( acoeff_variab, ex, &synth[i * L_SUBFR], L_SUBFR, mem_syn, 1 );
   }   /* next i */

   /* reset codebook averaging variables */
   averState->hangVar = 20;
   averState->hangCount = 0;

   if ( new_state == DTX_MUTE ) {
        /*
         * mute comfort noise as it has been quite a long time since
         * last SID update  was performed
         */
      Word32 num, denom;


      tmp_int_length = st->since_last_sid;

      if ( tmp_int_length > 32 ) {
         tmp_int_length = 32;
      }

      if ( tmp_int_length == 1 ) {
         st->true_sid_period_inv = MAX_16;
      }
      else {
         num = 1024;
         denom = ( tmp_int_length << 10 );
         st->true_sid_period_inv = 0;

         for ( i = 0; i < 15; i++ ) {
            st->true_sid_period_inv <<= 1;
            num <<= 1;

            if ( num >= denom ) {
               num = num - denom;
               st->true_sid_period_inv += 1;
            }
         }
      }
      st->since_last_sid = 0;
      memcpy( st->lsp_old, st->lsp, M << 2 );
      st->old_log_en = st->log_en;

      /* subtract 1/8 in Q11 i.e -6/8 dB */
      st->log_en = st->log_en - 256;
      if (st->log_en < -32768) st->log_en = -32768;
   }

     /*
      * reset interpolation length timer
      * if data has been updated.
      */
   if ( ( st->sid_frame != 0 ) & ( ( st->valid_data != 0 ) || ( ( st->valid_data
         == 0 ) & ( st->dtxHangoverAdded != 0 ) ) ) ) {
      st->since_last_sid = 0;
      st->data_updated = 1;
   }
   return;
}


/*
 * lsp_avg
 *
 *
 * Parameters:
 *    st->lsp_meanSave  B: LSP averages
 *    lsp               I: LSPs
 *
 * Function:
 *    Calculate the LSP averages
 *
 * Returns:
 *    void
 */
static void lsp_avg( lsp_avgState *st, Word32 *lsp )
{
   Word32 i, tmp;


   for ( i = 0; i < M; i++ ) {
      /* mean = 0.84*mean */
      tmp = ( st->lsp_meanSave[i] << 16 );
      tmp -= ( EXPCONST * st->lsp_meanSave[i] ) << 1;

      /* Add 0.16 of newest LSPs to mean */
      tmp += ( EXPCONST * lsp[i] ) << 1;

      /* Save means */
      tmp += 0x00008000L;
      st->lsp_meanSave[i] = tmp >> 16;
   }
   return;
}


/*
 * Int_lpc_1and3
 *
 *
 * Parameters:
 *    lsp_old        I: LSP vector at the 4th subfr. of past frame      [M]
 *    lsp_mid        I: LSP vector at the 2nd subframe of present frame [M]
 *    lsp_new        I: LSP vector at the 4th subframe of present frame [M]
 *    Az             O: interpolated LP parameters in subframes 1 and 3
 *                                                                   [AZ_SIZE]
 *
 * Function:
 *    Interpolates the LSPs and converts to LPC parameters
 *    to get a different LP filter in each subframe.
 *
 *    The 20 ms speech frame is divided into 4 subframes.
 *    The LSPs are quantized and transmitted at the 2nd and
 *    4th subframes (twice per frame) and interpolated at the
 *    1st and 3rd subframe.
 *
 * Returns:
 *    void
 */
static void Int_lpc_1and3( Word32 lsp_old[], Word32 lsp_mid[], Word32 lsp_new[],
      Word32 Az[] )
{
   Word32 lsp[M];
   Word32 i;


   /* lsp[i] = lsp_mid[i] * 0.5 + lsp_old[i] * 0.5 */
   for ( i = 0; i < 10; i++ ) {
      lsp[i] = ( lsp_mid[i] >> 1 ) + ( lsp_old[i] >> 1 );
   }

   /* Subframe 1 */
   Lsp_Az( lsp, Az );
   Az += MP1;

   /* Subframe 2 */
   Lsp_Az( lsp_mid, Az );
   Az += MP1;

   for ( i = 0; i < 10; i++ ) {
      lsp[i] = ( lsp_mid[i] >> 1 ) + ( lsp_new[i] >> 1 );
   }

   /* Subframe 3 */
   Lsp_Az( lsp, Az );
   Az += MP1;

   /* Subframe 4 */
   Lsp_Az( lsp_new, Az );
   return;
}


/*
 * Int_lpc_1to3
 *
 *
 * Parameters:
 *    lsp_old           I: LSP vector at the 4th subframe of past frame    [M]
 *    lsp_new           I: LSP vector at the 4th subframe of present frame [M]
 *    Az                O: interpolated LP parameters in all subframes
 *                                                                   [AZ_SIZE]
 *
 * Function:
 *    Interpolates the LSPs and converts to LPC parameters to get a different
 *    LP filter in each subframe.
 *
 *    The 20 ms speech frame is divided into 4 subframes.
 *    The LSPs are quantized and transmitted at the 4th
 *    subframes (once per frame) and interpolated at the
 *    1st, 2nd and 3rd subframe.
 *
 * Returns:
 *    void
 */
static void Int_lpc_1to3( Word32 lsp_old[], Word32 lsp_new[], Word32 Az[] )
{
   Word32 lsp[M];
   Word32 i;


   for ( i = 0; i < 10; i++ ) {
      lsp[i] = ( lsp_new[i] >> 2 ) + ( lsp_old[i] - ( lsp_old[i] >> 2 ) );
   }

   /* Subframe 1 */
   Lsp_Az( lsp, Az );
   Az += MP1;

   for ( i = 0; i < 10; i++ ) {
      lsp[i] = ( lsp_old[i] >> 1 ) + ( lsp_new[i] >> 1 );
   }

   /* Subframe 2 */
   Lsp_Az( lsp, Az );
   Az += MP1;

   for ( i = 0; i < 10; i++ ) {
      lsp[i] = ( lsp_old[i] >> 2 ) + ( lsp_new[i] - ( lsp_new[i] >> 2 ) );
   }

   /* Subframe 3 */
   Lsp_Az( lsp, Az );
   Az += MP1;

   /* Subframe 4 */
   Lsp_Az( lsp_new, Az );
   return;
}


/*
 * D_plsf_5
 *
 *
 * Parameters:
 *    st->past_lsf_q I: Past dequantized LFSs
 *    st->past_r_q      B: past quantized residual
 *    bfi               B: bad frame indicator
 *    indice            I: quantization indices of 3 submatrices, Q0
 *    lsp1_q            O: quantized 1st LSP vector
 *    lsp2_q            O: quantized 2nd LSP vector
 *
 * Function:
 *    Decodes the 2 sets of LSP parameters in a frame
 *    using the received quantization indices.
 *
 * Returns:
 *    void
 */
static void D_plsf_5( D_plsfState *st, Word16 bfi, Word16 *indice, Word32 *lsp1_q
      , Word32 *lsp2_q )
{
   Word32 lsf1_r[M], lsf2_r[M], lsf1_q[M], lsf2_q[M];
   Word32 i, temp1, temp2, sign;
   const Word32 *p_dico;


   /* if bad frame */
   if ( bfi != 0 ) {
      /* use the past LSFs slightly shifted towards their mean */
      for ( i = 0; i < M; i += 2 ) {
         /* lsfi_q[i] = ALPHA*st->past_lsf_q[i] + ONE_ALPHA*meanLsf[i]; */
         lsf1_q[i] = ( ( st->past_lsf_q[i] * ALPHA_122 ) >> 15 ) + ( ( mean_lsf_5[i]
               * ONE_ALPHA_122 ) >> 15 );
         lsf1_q[i + 1] = ( ( st->past_lsf_q[i + 1] * ALPHA_122 ) >> 15 ) + ( (
               mean_lsf_5[i + 1] * ONE_ALPHA_122 ) >> 15 );
      }
      memcpy( lsf2_q, lsf1_q, M <<2 );

      /* estimate past quantized residual to be used in next frame */
      for ( i = 0; i < M; i += 2 ) {
         /* temp  = meanLsf[i] +  st->past_r_q[i] * LSPPpred_facMR122; */
         temp1 = mean_lsf_5[i] + ( ( st->past_r_q[i] * LSP_PRED_FAC_MR122 ) >>
               15 );
         temp2 = mean_lsf_5[i + 1] +( ( st->past_r_q[i + 1] *LSP_PRED_FAC_MR122
               ) >> 15 );
         st->past_r_q[i] = lsf2_q[i] - temp1;
         st->past_r_q[i + 1] = lsf2_q[i + 1] -temp2;
      }
   }

   /* if good LSFs received */
   else {
      /* decode prediction residuals from 5 received indices */
      p_dico = &dico1_lsf_5[indice[0] << 2];
      lsf1_r[0] = *p_dico++;
      lsf1_r[1] = *p_dico++;
      lsf2_r[0] = *p_dico++;
      lsf2_r[1] = *p_dico++;
      p_dico = &dico2_lsf_5[indice[1] << 2];
      lsf1_r[2] = *p_dico++;
      lsf1_r[3] = *p_dico++;
      lsf2_r[2] = *p_dico++;
      lsf2_r[3] = *p_dico++;
      sign = ( Word16 )( indice[2] & 1 );
      i = indice[2] >> 1;
      p_dico = &dico3_lsf_5[i << 2];

      if ( sign == 0 ) {
         lsf1_r[4] = *p_dico++;
         lsf1_r[5] = *p_dico++;
         lsf2_r[4] = *p_dico++;
         lsf2_r[5] = *p_dico++;
      }
      else {
         lsf1_r[4] = ( Word16 )( -( *p_dico++ ) );
         lsf1_r[5] = ( Word16 )( -( *p_dico++ ) );
         lsf2_r[4] = ( Word16 )( -( *p_dico++ ) );
         lsf2_r[5] = ( Word16 )( -( *p_dico++ ) );
      }
      p_dico = &dico4_lsf_5[( indice[3]<<2 )];
      lsf1_r[6] = *p_dico++;
      lsf1_r[7] = *p_dico++;
      lsf2_r[6] = *p_dico++;
      lsf2_r[7] = *p_dico++;
      p_dico = &dico5_lsf_5[( indice[4]<<2 )];
      lsf1_r[8] = *p_dico++;
      lsf1_r[9] = *p_dico++;
      lsf2_r[8] = *p_dico++;
      lsf2_r[9] = *p_dico++;

      /* Compute quantized LSFs and update the past quantized residual */
      for ( i = 0; i < M; i++ ) {
         temp1 = mean_lsf_5[i] + ( ( st->past_r_q[i] * LSP_PRED_FAC_MR122 ) >>
               15 );
         lsf1_q[i] = lsf1_r[i] + temp1;
         lsf2_q[i] = lsf2_r[i] + temp1;
         st->past_r_q[i] = lsf2_r[i];
      }
   }

   /* verification that LSFs have minimum distance of LSF_GAP Hz */
   Reorder_lsf( lsf1_q, LSF_GAP );
   Reorder_lsf( lsf2_q, LSF_GAP );
   memcpy( st->past_lsf_q, lsf2_q, M <<2 );

   /*  convert LSFs to the cosine domain */
   Lsf_lsp( lsf1_q, lsp1_q );
   Lsf_lsp( lsf2_q, lsp2_q );
   return;
}


/*
 * Dec_lag3
 *
 *
 * Parameters:
 *    index             I: received pitch index
 *    t0_min            I: minimum of search range
 *    t0_max            I: maximum of search range
 *    i_subfr           I: subframe flag
 *    T0_prev           I: integer pitch delay of last subframe used
 *                         in 2nd and 4th subframes
 *    T0                O: integer part of pitch lag
 *    T0_frac           O : fractional part of pitch lag
 *    flag4             I : flag for encoding with 4 bits
 * Function:
 *    Decoding of fractional pitch lag with 1/3 resolution.
 *    Extract the integer and fraction parts of the pitch lag from
 *    the received adaptive codebook index.
 *
 *    The fractional lag in 1st and 3rd subframes is encoded with 8 bits
 *    while that in 2nd and 4th subframes is relatively encoded with 4, 5
 *    and 6 bits depending on the mode.
 *
 * Returns:
 *    void
 */
static void Dec_lag3( Word32 index, Word32 t0_min, Word32 t0_max, Word32 i_subfr
      , Word32 T0_prev, Word32 *T0, Word32 *T0_frac, Word32 flag4 )
{
   Word32 i, tmp_lag;


   /* if 1st or 3rd subframe */
   if ( i_subfr == 0 ) {
      if ( index < 197 ) {
         *T0 = ( ( ( index + 2 ) * 10923 ) >> 15 ) + 19;
         i = *T0 + *T0 + *T0;
         *T0_frac = ( index - i ) + 58;
      }
      else {
         *T0 = index - 112;
         *T0_frac = 0;
      }
   }

   /* 2nd or 4th subframe */
   else {
      if ( flag4 == 0 ) {
         /* 'normal' decoding: either with 5 or 6 bit resolution */
         i = ( ( ( index + 2 ) * 10923 ) >> 15 ) - 1;
         *T0 = i + t0_min;
         i = i + i + i;
         *T0_frac = ( index - 2 ) - i;
      }
      else {
         /* decoding with 4 bit resolution */
         tmp_lag = T0_prev;

         if ( ( tmp_lag - t0_min ) > 5 )
            tmp_lag = t0_min + 5;

         if ( ( t0_max - tmp_lag ) > 4 )
            tmp_lag = t0_max - 4;

         if ( index < 4 ) {
            i = ( tmp_lag - 5 );
            *T0 = i + index;
            *T0_frac = 0;
         }
         else {
            if ( index < 12 ) {
               i = ( ( ( index - 5 ) * 10923 ) >> 15 ) - 1;
               *T0 = i + tmp_lag;
               i = i + i + i;
               *T0_frac = ( index - 9 ) - i;
            }
            else {
               i = ( index - 12 ) + tmp_lag;
               *T0 = i + 1;
               *T0_frac = 0;
            }
         }
      }   /* end if (decoding with 4 bit resolution) */
   }
   return;
}


/*
 * Pred_lt_3or6_40
 *
 *
 * Parameters:
 *    exc               B: excitation buffer
 *    T0                I: integer pitch lag
 *    frac              I: fraction of lag
 *    flag3             I: if set, upsampling rate = 3 (6 otherwise)
 *
 * Function:
 *    Compute the result of long term prediction with fractional
 *    interpolation of resolution 1/3 or 1/6. (Interpolated past excitation).
 *
 *    Once the fractional pitch lag is determined,
 *    the adaptive codebook vector v(n) is computed by interpolating
 *    the past excitation signal u(n) at the given integer delay k
 *    and phase (fraction)  :
 *
 *          9                       9
 *    v(n) = SUM[ u(n-k-i) * b60(t+i*6) ] + SUM[ u(n-k+1+i) * b60(6-t+i*6) ],
 *          i=0                       i=0
 *    n = 0, ...,39, t = 0, ...,5.
 *
 *    The interpolation filter b60 is based on a Hamming windowed sin(x)/x
 *    function truncated at ± 59 and padded with zeros at ± 60 (b60(60)=0)).
 *    The filter has a cut-off frequency (-3 dB) at 3 600 Hz in
 *    the over-sampled domain.
 *
 * Returns:
 *    void
 */
static void Pred_lt_3or6_40( Word32 exc[], Word32 T0, Word32 frac, Word32 flag3 )
{
   Word32 s, i;
   Word32 *x0, *x1, *x2;
   const Word32 *c1, *c2;


   x0 = &exc[ - T0];
   frac = -frac;

   if ( flag3 != 0 ) {
      frac <<= 1;   /* inter_3l[k] = inter6[2*k] -> k' = 2*k */
   }

   if ( frac < 0 ) {
      frac += 6;
      x0--;
   }
   c1 = &inter6[frac];
   c2 = &inter6[6 - frac];

   for ( i = 0; i < 40; i++ ) {
      x1 = x0++;
      x2 = x0;
      s = x1[0] * c1[0];
      s += x1[ - 1] * c1[6];
      s += x1[ - 2] * c1[12];
      s += x1[ - 3] * c1[18];
      s += x1[ - 4] * c1[24];
      s += x1[ - 5] * c1[30];
      s += x1[ - 6] * c1[36];
      s += x1[ - 7] * c1[42];
      s += x1[ - 8] * c1[48];
      s += x1[ - 9] * c1[54];
      s += x2[0] * c2[0];
      s += x2[1] * c2[6];
      s += x2[2] * c2[12];
      s += x2[3] * c2[18];
      s += x2[4] * c2[24];
      s += x2[5] * c2[30];
      s += x2[6] * c2[36];
      s += x2[7] * c2[42];
      s += x2[8] * c2[48];
      s += x2[9] * c2[54];
      exc[i] = ( s + 0x4000 ) >> 15;

   }
}


/*
 * Dec_lag6
 *
 *
 * Parameters:
 *    index             I: received pitch index
 *    pit_min           I: minimum pitch lag
 *    pit_max           I: maximum pitch lag
 *    i_subfr           I: subframe flag
 *    T0                B: integer part of pitch lag
 *    T0_frac           O : fractional part of pitch lag
 *
 * Function:
 *    Decoding of fractional pitch lag with 1/6 resolution.
 *    Extract the integer and fraction parts of the pitch lag from
 *    the received adaptive codebook index.
 *
 *    The fractional lag in 1st and 3rd subframes is encoded with 9 bits
 *    while that in 2nd and 4th subframes is relatively encoded with 6 bits.
 *    Note that in relative encoding only 61 values are used. If the
 *    decoder receives 61, 62, or 63 as the relative pitch index, it means
 *    that a transmission error occurred. In this case, the pitch lag from
 *    previous subframe (actually from previous frame) is used.
 *
 * Returns:
 *    void
 */
static void Dec_lag6( Word32 index, Word32 pit_min, Word32 pit_max, Word32
      i_subfr, Word32 *T0, Word32 *T0_frac )
{
   Word32 t0_min, t0_max, i;


   /* if 1st or 3rd subframe */
   if ( i_subfr == 0 ) {
      if ( index < 463 ) {
         /* T0 = (index+5)/6 + 17 */
         *T0 = ( index + 5 ) / 6 + 17;
         i = *T0 + *T0 + *T0;

         /* *T0_frac = index - T0*6 + 105 */
         *T0_frac = ( index - ( i + i ) ) + 105;
      }
      else {
         *T0 = index - 368;
         *T0_frac = 0;
      }
   }

   /* second or fourth subframe */
   else {
      /* find t0_min and t0_max for 2nd (or 4th) subframe */
      t0_min = *T0 - 5;

      if ( t0_min < pit_min ) {
         t0_min = pit_min;
      }
      t0_max = t0_min + 9;

      if ( t0_max > pit_max ) {
         t0_max = pit_max;
         t0_min = t0_max - 9;
      }

      /* i = (index+5)/6 - 1 */
      i = ( index + 5 ) / 6 - 1;
      *T0 = i + t0_min;
      i = i + i + i;
      *T0_frac = ( index - 3 ) - ( i + i );
   }
}


/*
 * decompress10
 *
 *
 * Parameters:
 *    MSBs              I: MSB part of the index
 *    LSBs              I: LSB part of the index
 *    index1            I: index for first pos in posIndex
 *    index2            I: index for second pos in posIndex
 *    index3            I: index for third pos in posIndex
 *    pos_indx          O: position of 3 pulses (decompressed)
 * Function:
 *    Decompression of the linear codeword
 *
 * Returns:
 *    void
 */
static void decompress10( Word32 MSBs, Word32 LSBs, Word32 index1, Word32 index2
      , Word32 index3, Word32 pos_indx[] )
{
   Word32 divMSB;

   if (MSBs > 124)
   {
      MSBs = 124;
   }
   /*
    * pos_indx[index1] = ((MSBs-25*(MSBs/25))%5)*2 + (LSBs-4*(LSBs/4))%2;
    * pos_indx[index2] = ((MSBs-25*(MSBs/25))/5)*2 + (LSBs-4*(LSBs/4))/2;
    * pos_indx[index3] = (MSBs/25)*2 + LSBs/4;
    */
   divMSB = MSBs / 25;
   pos_indx[index1] = ( ( ( MSBs - 25 * ( divMSB ) ) % 5 ) << 1 ) + ( LSBs & 0x1
         );
   pos_indx[index2] = ( ( ( MSBs - 25 * ( divMSB ) ) / 5 ) << 1 ) + ( ( LSBs &
         0x2 ) >> 1 );
   pos_indx[index3] = ( divMSB << 1 ) + ( LSBs >> 2 );
   return;
}


/*
 * decompress_codewords
 *
 *
 * Parameters:
 *    indx              I: position of 8 pulses (compressed)
 *    pos_indx          O: position index of 8 pulses (position only)
 *
 * Function:
 *    Decompression of the linear codewords to 4+three indeces
 *    one bit from each pulse is made robust to errors by
 *    minimizing the phase shift of a bit error.
 *
 *    i0,i4,i1 => one index (7+3) bits, 3   LSBs more robust
 *    i2,i6,i5 => one index (7+3) bits, 3   LSBs more robust
 *    i3,i7    => one index (5+2) bits, 2-3 LSbs more robust
 *
 * Returns:
 *    void
 */
static void decompress_codewords( Word16 indx[], Word32 pos_indx[] )
{
   Word32 ia, ib, MSBs, LSBs, MSBs0_24, tmp;


    /*
     * First index: 10x10x10 -> 2x5x2x5x2x5-> 125x2x2x2 -> 7+1x3 bits
     * MSBs = indx[NB_TRACK]/8;
     * LSBs = indx[NB_TRACK]%8;
     */
   MSBs = *indx >> 3;
   LSBs = *indx & 0x7;
   decompress10( MSBs, LSBs, 0, 4, 1, pos_indx );

    /*
     * Second index: 10x10x10 -> 2x5x2x5x2x5-> 125x2x2x2 -> 7+1x3 bits
     * MSBs = indx[NB_TRACK+1]/8;
     * LSBs = indx[NB_TRACK+1]%8;
     */
   MSBs = indx[1] >> 3;
   LSBs = indx[1] & 0x7;
   decompress10( MSBs, LSBs, 2, 6, 5, pos_indx );

    /*
     * Third index: 10x10 -> 2x5x2x5-> 25x2x2 -> 5+1x2 bits
     * MSBs = indx[NB_TRACK+2]/4;
     * LSBs = indx[NB_TRACK+2]%4;
     * MSBs0_24 = (MSBs*25+12)/32;
     * if ((MSBs0_24/5)%2==1)
     *    pos_indx[3] = (4-(MSBs0_24%5))*2 + LSBs%2;
     * else
     *    pos_indx[3] = (MSBs0_24%5)*2 + LSBs%2;
     * pos_indx[7] = (MSBs0_24/5)*2 + LSBs/2;
     */
   MSBs = indx[2] >> 2;
   LSBs = indx[2] & 0x3;
   MSBs0_24 = ( ( ( MSBs * 25 ) + 12 ) >> 5 );
   tmp = ( MSBs0_24 * 6554 ) >> 15;
   ia = tmp & 0x1;
   ib = ( MSBs0_24 - ( tmp * 5 ) );

   if ( ia == 1 ) {
      ib = 4 - ib;
   }
   pos_indx[3] = ( ib << 1 ) + ( LSBs & 0x1 );
   pos_indx[7] = ( tmp << 1 ) + ( LSBs >> 1 );
}


/*
 * decode_2i40_9bits
 *
 *
 * Parameters:
 *    subNr             I: subframe number
 *    sign              I: signs of 2 pulses
 *    index             I: Positions of the 2 pulses
 *    cod               O: algebraic (fixed) codebook excitation
 *
 * Function:
 *    Algebraic codebook decoder
 *
 * Returns:
 *    void
 */
static void decode_2i40_9bits( Word32 subNr, Word32 sign, Word32 index, Word32
      cod[] )
{
   Word32 pos[2];
   Word32 i, j, k;


   /* Decode the positions */
   /* table bit  is the MSB */
   j = ( index & 64 ) >> 6;
   i = index & 7;

   /* pos0 =i*5+startPos[j*8+subNr*2] */
   i = ( i + ( i << 2 ) );
   k = startPos[( j <<3 )+( subNr << 1 )];
   pos[0] = i + k;
   index = index >> 3;
   i = index & 7;

   /* pos1 =i*5+startPos[j*8+subNr*2+1] */
   i = ( i + ( i << 2 ) );
   k = startPos[( ( j <<3 )+ ( subNr <<1 ) ) + 1];
   pos[1] = ( Word16 )( i + k );

   /* decode the signs  and build the codeword */
   memset( cod, 0, L_SUBFR <<2 );

   for ( j = 0; j < 2; j++ ) {
      i = sign & 1;
      sign = sign >> 1;

      if ( i != 0 ) {
         cod[pos[j]] = 8191;   /* +1.0 */
      }
      else {
         cod[pos[j]] = -8192;   /* -1.0 */
      }
   }
   return;
}


/*
 * decode_2i40_11bits
 *
 *
 * Parameters:
 *    sign              I: signs of 2 pulses
 *    index             I: Positions of the 2 pulses
 *    cod               O: algebraic (fixed) codebook excitation
 *
 * Function:
 *    Algebraic codebook decoder
 *
 * Returns:
 *    void
 */
static void decode_2i40_11bits( Word32 sign, Word32 index, Word32 cod[] )
{
   Word32 pos[2];
   Word32 i, j;


   /* Decode the positions */
   j = index & 1;
   index = index >> 1;
   i = index & 7;

   /* pos0 =i*5+1+j*2 */
   i = ( i + ( i << 2 ) );
   i = ( i + 1 );
   j = ( j << 1 );
   pos[0] = i + j;
   index = index >> 3;
   j = index & 3;
   index = index >> 2;
   i = index & 7;

   if ( j == 3 ) {
      /* pos1 =i*5+4 */
      i = ( i + ( i << 2 ) );
      pos[1] = i + 4;
   }
   else {
      /* pos1 =i*5+j */
      i = ( i + ( i << 2 ) );
      pos[1] = i + j;
   }

   /* decode the signs  and build the codeword */
   memset( cod, 0, L_SUBFR <<2 );

   for ( j = 0; j < 2; j++ ) {
      i = sign & 1;
      sign = sign >> 1;

      if ( i != 0 ) {
         cod[pos[j]] = 8191;   /* +1.0 */
      }
      else {
         cod[pos[j]] = -8192;   /* -1.0 */
      }
   }
   return;
}


/*
 * decode_3i40_14bits
 *
 *
 * Parameters:
 *    sign              I: signs of 3 pulses
 *    index             I: Positions of the 3 pulses
 *    cod               O: algebraic (fixed) codebook excitation
 *
 * Function:
 *    Algebraic codebook decoder
 *
 * Returns:
 *    void
 */
static void decode_3i40_14bits( Word32 sign, Word32 index, Word32 cod[] )
{
   Word32 pos[3];
   Word32 i, j;


   /* Decode the positions */
   i = index & 7;

   /* pos0 =i*5 */
   pos[0] = i + ( i << 2 );
   index = index >> 3;
   j = index & 1;
   index = index >> 1;
   i = index & 7;

   /* pos1 =i*5+1+j*2 */
   i = ( i + ( i << 2 ) );
   i = ( i + 1 );
   j = ( j << 1 );
   pos[1] = i + j;
   index = index >> 3;
   j = index & 1;
   index = index >> 1;
   i = index & 7;

   /* pos2 =i*5+2+j*2 */
   i = ( i + ( i << 2 ) );
   i = ( i + 2 );
   j = ( j << 1 );
   pos[2] = i + j;

   /* decode the signs  and build the codeword */
   memset( cod, 0, L_SUBFR <<2 );

   for ( j = 0; j < 3; j++ ) {
      i = sign & 1;
      sign = sign >> 1;

      if ( i > 0 ) {
         cod[pos[j]] = 8191;   /* +1.0 */
      }
      else {
         cod[pos[j]] = -8192;   /* -1.0 */
      }
   }
   return;
}


/*
 * decode_3i40_14bits
 *
 *
 * Parameters:
 *    sign              I: signs of 4 pulses
 *    index             I: Positions of the 4 pulses
 *    cod               O: algebraic (fixed) codebook excitation
 *
 * Function:
 *    Algebraic codebook decoder
 *
 * Returns:
 *    void
 */
static void decode_4i40_17bits( Word32 sign, Word32 index, Word32 cod[] )
{
   Word32 pos[4];
   Word32 i, j;


   /* Decode the positions */
   i = index & 7;
   i = dgray[i];

   /* pos0 =i*5 */
   pos[0] = i + ( i << 2 );
   index = index >> 3;
   i = index & 7;
   i = dgray[i];

   /* pos1 =i*5+1 */
   i = ( i + ( i << 2 ) );
   pos[1] = i + 1;
   index = index >> 3;
   i = index & 7;
   i = dgray[i];

   /* pos2 =i*5+1 */
   i = ( i + ( i << 2 ) );
   pos[2] = i + 2;
   index = index >> 3;
   j = index & 1;
   index = index >> 1;
   i = index & 7;
   i = dgray[i];

   /* pos3 =i*5+3+j */
   i = ( i + ( i << 2 ) );
   i = ( i + 3 );
   pos[3] = i + j;

   /* decode the signs  and build the codeword */
   memset( cod, 0, L_SUBFR <<2 );

   for ( j = 0; j < 4; j++ ) {
      i = sign & 1;
      sign = sign >> 1;

      if ( i != 0 ) {
         cod[pos[j]] = 8191;
      }
      else {
         cod[pos[j]] = -8192;
      }
   }
   return;
}


/*
 * decode_8i40_31bits
 *
 *
 * Parameters:
 *    index             I: index of 8 pulses (sign+position)
 *    cod               O: algebraic (fixed) codebook excitation
 *
 * Function:
 *    Algebraic codebook decoder
 *
 * Returns:
 *    void
 */
static void decode_8i40_31bits( Word16 index[], Word32 cod[] )
{
   Word32 linear_codewords[8];
   Word32 i, j, pos1, pos2, sign;


   memset( cod, 0, L_CODE <<2 );
   decompress_codewords( &index[NB_TRACK_MR102], linear_codewords );

   /* decode the positions and signs of pulses and build the codeword */
   for ( j = 0; j < NB_TRACK_MR102; j++ ) {
      /* compute index i */
      i = linear_codewords[j];
      i <<= 2;

      /* position of pulse "j" */
      pos1 = i + j;

      if ( index[j] == 0 ) {
         sign = POS_CODE;   /* +1.0 */
      }
      else {
         sign = -NEG_CODE;   /* -1.0 */
      }

      /* compute index i */
      i = linear_codewords[j + 4];
      i = i << 2;

      /* position of pulse "j+4" */
      pos2 = i + j;
      cod[pos1] = sign;

      if ( pos2 < pos1 ) {
         sign = -( sign );
      }
      cod[pos2] = cod[pos2] + sign;
   }
   return;
}


/*
 * decode_10i40_35bits
 *
 *
 * Parameters:
 *    index             I: index of 10 pulses (sign+position)
 *    cod               O: algebraic (fixed) codebook excitation
 *
 * Function:
 *    Algebraic codebook decoder
 *
 * Returns:
 *    void
 */
static void decode_10i40_35bits( Word16 index[], Word32 cod[] )
{
   Word32 i, j, pos1, pos2, sign, tmp;


   memset( cod, 0, L_CODE <<2 );

   /* decode the positions and signs of pulses and build the codeword */
   for ( j = 0; j < 5; j++ ) {
      /* compute index i */
      tmp = index[j];
      i = tmp & 7;
      i = dgray[i];
      i = ( i * 5 );

      /* position of pulse "j" */
      pos1 = ( i + j );
      i = ( tmp >> 3 ) & 1;

      if ( i == 0 ) {
         sign = 4096;   /* +1.0 */
      }
      else {
         sign = -4096;   /* -1.0 */
      }

      /* compute index i */
      i = index[j + 5] & 7;
      i = dgray[i];
      i = i * 5;

      /* position of pulse "j+5" */
      pos2 = ( i + j );
      cod[pos1] = sign;

      if ( pos2 < pos1 ) {
         sign = -( sign );
      }
      cod[pos2] = cod[pos2] + sign;
   }
   return;
}


/*
 * gmed_n
 *
 *
 * Parameters:
 *    ind               I: values
 *    n                 I: The number of gains (odd)
 *
 * Function:
 *    Calculates N-point median.
 *
 * Returns:
 *    index of the median value
 */
static Word32 gmed_n( Word32 ind[], Word32 n )
{
   Word32 tmp[NMAX], tmp2[NMAX];
   Word32 max, medianIndex, i, j, ix = 0;


   for ( i = 0; i < n; i++ ) {
      tmp2[i] = ind[i];
   }

   for ( i = 0; i < n; i++ ) {
      max = -32767;

      for ( j = 0; j < n; j++ ) {
         if ( tmp2[j] >= max ) {
            max = tmp2[j];
            ix = j;
         }
      }
      tmp2[ix] = -32768;
      tmp[i] = ix;
   }
   medianIndex = tmp[( n >>1 )];
   return( ind[medianIndex] );
}


/*
 * ec_gain_pitch
 *
 *
 * Parameters:
 *    st->pbuf          I: last five gains
 *    st->past_gain_pit I: past gain
 *    state             I: state of the state machine
 *    gain_pitch        O: pitch gain
 *
 * Function:
 *    Calculates pitch from previous values.
 *
 * Returns:
 *    void
 */
static void ec_gain_pitch( ec_gain_pitchState *st, Word16 state, Word32 *
      gain_pitch )
{
   Word32 tmp;


   /* calculate median of last five gains */
   tmp = gmed_n( st->pbuf, 5 );

   /* new gain = minimum(median, past_gain) * pdown[state] */
   if ( tmp > st->past_gain_pit ) {
      tmp = st->past_gain_pit;
   }
   *gain_pitch = ( tmp * pdown[state] ) >> 15;
}


/*
 * d_gain_pitch
 *
 *
 * Parameters:
 *    mode              I: AMR mode
 *    index             I: index of quantization
 *
 * Function:
 *    Decodes the pitch gain using the received index
 *
 * Returns:
 *    gain
 */
static Word32 d_gain_pitch( enum Mode mode, Word32 index )
{
   Word32 gain;


   if ( mode == MR122 ) {
      /* clear 2 LSBits */
      gain = ( qua_gain_pitch[index] >> 2 ) << 2;
   }
   else {
      gain = qua_gain_pitch[index];
   }
   return gain;
}


/*
 * ec_gain_pitch_update
 *
 *
 * Parameters:
 *    st->prev_gp       B: previous pitch gain
 *    st->past_gain_pit O: past gain
 *    st->pbuf          B: past gain buffer
 *    bfi               I: bad frame indicator
 *    prev_bf           I: previous frame was bad
 *    gain_pitch        B: pitch gain
 *
 * Function:
 *    Update the pitch gain concealment state
 *    Limit gain_pitch if the previous frame was bad
 *
 * Returns:
 *    gain
 */
static void ec_gain_pitch_update( ec_gain_pitchState *st, Word32 bfi,
      Word32 prev_bf, Word32 *gain_pitch )
{
   if ( bfi == 0 ) {
      if ( prev_bf != 0 ) {
         if ( *gain_pitch > st->prev_gp ) {
            *gain_pitch = st->prev_gp;
         }
      }
      st->prev_gp = *gain_pitch;
   }
   st->past_gain_pit = *gain_pitch;

   /* if (st->past_gain_pit > 1.0) */
   if ( st->past_gain_pit > 16384 ) {
      st->past_gain_pit = 16384;
   }
   st->pbuf[0] = st->pbuf[1];
   st->pbuf[1] = st->pbuf[2];
   st->pbuf[2] = st->pbuf[3];
   st->pbuf[3] = st->pbuf[4];
   st->pbuf[4] = st->past_gain_pit;
}


/*
 * gc_pred (366)
 *
 *
 * Parameters:
 *    st->past_qua_en         I: MA predictor
 *    st->past_qua_en_MR122   I: MA predictor MR122
 *    mode                    I: AMR mode
 *    code                    I: innovative codebook vector
 *    exp_gcode0              O: predicted gain factor (exponent)
 *    frac_gcode0             O: predicted gain factor (fraction)
 *    exp_en                  I: innovation energy (MR795) (exponent)
 *    frac_en                 I: innovation energy (MR795) (fraction)
 *
 * Function:
 *    MA prediction of the innovation energy
 *
 *    Mean removed innovation energy (dB) in subframe n
 *                          N-1
 *    E(n) = 10*log(gc*gc * SUM[(code(i) * code(i)]/N) - EMean
 *                          i=0
 *    N=40
 *
 *    Mean innovation energy (dB)
 *                   N-1
 *    Ei(n) = 10*log(SUM[(code(i) * code(i)]/N)
 *                   i=0
 *
 *    Predicted energy
 *              4
 *    Ep(n) = SUM[b(i) * R(n-i)]
 *            i=1
 *    b = [0.68 0.58 0.34 0.19]
 *    R(k) is quantified prediction error at subframe k
 *
 *    E_Mean = 36 dB (MR122)
 *
 *    Predicted gain gc is found by
 *
 *    gc = POW[10, 0.05 * (Ep(n) + EMean - Ei)]
 *
 * Returns:
 *    void
 */
static void gc_pred( gc_predState *st, enum Mode mode, Word32 *code, Word32 *
      exp_gcode0, Word32 *frac_gcode0, Word32 *exp_en, Word32 *frac_en )
{
   Word32 exp, frac, ener_code = 0, i = 0;


    /* energy of code:
     * ener_code = sum(code[i]^2)
     */
   while ( i < L_SUBFR ) {
      ener_code += code[i] * code[i];
      i++;
   }

   if ( ( 0x3fffffff <= ener_code ) | ( ener_code < 0 ) )
      ener_code = MAX_32;
   else
      ener_code <<= 1;

   if ( mode == MR122 ) {
      Word32 ener;


      /* ener_code = ener_code / lcode; lcode = 40; 1/40 = 26214 Q20       */
      ener_code = ( ( ener_code + 0x00008000L ) >> 16 ) * 52428;

      /* Q9  * Q20 -> Q30 */
        /* energy of code:
         * ener_code(Q17) = 10 * Log10(energy) / constant
         *                = 1/2 * Log2(energy)
         * constant = 20*Log10(2)
         */
      /* ener_code = 1/2 * Log2(ener_code); Note: Log2=log2+30 */
      Log2( ener_code, &exp, &frac );
      ener_code = ( ( exp - 30 ) << 16 ) + ( frac << 1 );

      /* Q16 for log(), ->Q17 for 1/2 log() */
         /*
          * predicted energy:
          * ener(Q24) = (Emean + sum{pred[i]*pastEn[i]})/constant
          *           = MEAN_ENER + sum(pred[i]*past_qua_en[i])
          * constant = 20*Log10(2)
          */
      ener = 0;
      i = 0;

      while ( i < 4 ) {
         ener += st->past_qua_en_MR122[i] * pred_MR122[i];
         i++;
      }
      ener <<= 1;
      ener += MEAN_ENER_MR122;

        /*
         * predicted codebook gain

         * gc0 = Pow10( (ener*constant - ener_code*constant) / 20 )
         *     = Pow2(ener-ener_code)
         *     = Pow2(int(d)+frac(d))
         */
      ener = ( ener - ener_code ) >> 1;   /* Q16 */
      *exp_gcode0 = ener >> 16;
      *frac_gcode0 = ( ener >> 1 ) - ( *exp_gcode0 << 15 );
   }

   /* all modes except 12.2 */
   else {
      Word32 tmp, gcode0;
      int exp_code;


        /*
         * Compute: meansEner - 10log10(ener_code/ LSufr)
         */
      exp_code=0;
      if (ener_code != 0){
         while (!(ener_code & 0x40000000))
         {
            exp_code++;
            ener_code = ener_code << 1;
         }
      }

      /* Log2 = log2 + 27 */
      Log2_norm( ener_code, exp_code, &exp, &frac );

      /* fact = 10/log2(10) = 3.01 = 24660 Q13 */
      /* Q0.Q15 * Q13 -> Q14 */
      tmp = ( exp * ( -49320 ) ) + ( ( ( frac * ( -24660 ) ) >> 15 ) << 1 );

      /*
       * tmp = meansEner - 10log10(ener_code/L_SUBFR)
       *       = meansEner - 10log10(ener_code) + 10log10(L_SUBFR)
       *       = K - fact * Log2(ener_code)
       *     = K - fact * log2(ener_code) - fact*27
       *
       *   ==> K = meansEner + fact*27 + 10log10(L_SUBFR)
       *
       *   meansEner =       33    =  540672    Q14  (MR475, MR515, MR59)
       *   meansEner =       28.75 =  471040    Q14  (MR67)
       *   meansEner =       30    =  491520    Q14  (MR74)
       *   meansEner =       36    =  589824    Q14  (MR795)
       *   meansEner =       33    =  540672    Q14  (MR102)
       *   10log10(L_SUBFR) = 16.02 =  262481.51 Q14
       *   fact * 27                = 1331640    Q14
       *   -----------------------------------------
       *   (MR475, MR515, MR59)   K = 2134793.51 Q14 ~= 16678 * 64 * 2
       *   (MR67)                 K = 2065161.51 Q14 ~= 32268 * 32 * 2
       *   (MR74)                 K = 2085641.51 Q14 ~= 32588 * 32 * 2
       *   (MR795)                K = 2183945.51 Q14 ~= 17062 * 64 * 2
       *   (MR102)                K = 2134793.51 Q14 ~= 16678 * 64 * 2
       */
      if ( mode == MR102 ) {
         /* mean = 33 dB */
         tmp += 2134784;   /* Q14 */
      }
      else if ( mode == MR795 ) {
         /* mean = 36 dB */
         tmp += 2183936;   /* Q14 */

         /*
          * ener_code  = <xn xn> * 2^27*2^exp_code
          * frac_en    = ener_code / 2^16
          *            = <xn xn> * 2^11*2^exp_code
          * <xn xn>    = <xn xn>*2^11*2^exp * 2^exp_en
          *           := frac_en            * 2^exp_en
          *
          * ==> exp_en = -11-exp_code;
          */
         *frac_en = ener_code >> 16;
         *exp_en = -11 - exp_code;
      }
      else if ( mode == MR74 ) {
         /* mean = 30 dB */
         tmp += 2085632;   /* Q14 */
      }
      else if ( mode == MR67 ) {
         /* mean = 28.75 dB */
         tmp += 2065152;   /* Q14 */
      }
      else /* MR59, MR515, MR475 */ {
         /* mean = 33 dB */
         tmp += 2134784;   /* Q14 */
      }

        /*
         * Compute gcode0
         * = Sum(i=0,3) pred[i]*past_qua_en[i] - ener_code + meanEner
         */
      tmp = tmp << 9;   /* Q23 */

      /* Q13 * Q10 -> Q23 */
      i = 0;

      while ( i < 4 ) {
         tmp += pred[i] * st->past_qua_en[i];
         i++;
      }
      gcode0 = tmp >> 15;   /* Q8  */

        /*
         * gcode0 = pow(10.0, gcode0/20)
         *        = pow(2, 3.3219*gcode0/20)
         *        = pow(2, 0.166*gcode0)
         */
      /* 5439 Q15 = 0.165985                                        */
      /* (correct: 1/(20*log10(2)) 0.166096 = 5443 Q15)             */
      /* For IS641 bitexactness */
      if ( mode == MR74 ) {
         /* Q8 * Q15 -> Q24 */
         tmp = gcode0 * 10878;
      }
      else {
         /* Q8 * Q15 -> Q24 */
         tmp = gcode0 * 10886;
      }
      tmp = tmp >> 9;   /* -> Q15 */

      /* -> Q0.Q15 */
      *exp_gcode0 = tmp >> 15;
      *frac_gcode0 = tmp - ( *exp_gcode0 * 32768 );
   }
}


/*
 * gc_pred_update
 *
 *
 * Parameters:
 *    st->past_qua_en         B: MA predictor
 *    st->past_qua_en_MR122   B: MA predictor MR122
 *    qua_ener_MR122          I: quantized energy for update (log2(quaErr))
 *    qua_ener                I: quantized energy for update (20*log10(quaErr))
 *
 * Function:
 *    Update MA predictor with last quantized energy
 *
 * Returns:
 *    void
 */
static void gc_pred_update( gc_predState *st, Word32 qua_ener_MR122,
      Word32 qua_ener )
{
   Word32 i;


   for ( i = 3; i > 0; i-- ) {
      st->past_qua_en[i] = st->past_qua_en[i - 1];
      st->past_qua_en_MR122[i] = st->past_qua_en_MR122[i - 1];
   }
   st->past_qua_en_MR122[0] = qua_ener_MR122;   /* log2 (quaErr), Q10 */
   st->past_qua_en[0] = qua_ener;   /* 20*log10(quaErr), Q10 */
}


/*
 * Dec_gain
 *
 *
 * Parameters:
 *    pred_state->past_qua_en       B: MA predictor
 *    pred_state->past_qua_en_MR122 B: MA predictor MR122
 *    mode                          I: AMR mode
 *    index                         I: index of quantization
 *    code                          I: Innovative vector
 *    evenSubfr                     I: Flag for even subframes
 *    gain_pit                      O: Pitch gain
 *    gain_cod                      O: Code gain
 *
 * Function:
 *    Decode the pitch and codebook gains
 *
 * Returns:
 *    void
 */
static void Dec_gain( gc_predState *pred_state, enum Mode mode, Word32 index,
      Word32 code[], Word32 evenSubfr, Word32 *gain_pit, Word32 *gain_cod )
{
   Word32 frac, gcode0, exp, qua_ener, qua_ener_MR122, g_code, tmp;
   const Word32 *p;


   /* Read the quantized gains (table depends on mode) */
   index = index << 2;

   if ( ( mode == MR102 ) || ( mode == MR74 ) || ( mode == MR67 ) ) {
      p = &table_gain_highrates[index];
      *gain_pit = *p++;
      g_code = *p++;
      qua_ener_MR122 = *p++;
      qua_ener = *p;
   }
   else {
      if ( mode == MR475 ) {
         index = index + ( ( 1 - evenSubfr ) << 1 );
         p = &table_gain_MR475[index];
         *gain_pit = *p++;
         g_code = *p++;

            /*
             * calculate predictor update values (not stored in 4.75
             * quantizer table to save space):
             *   qua_ener       = log2(g)
             *   qua_ener_MR122 = 20*log10(g)
             */
         /* Log2(x Q12) = log2(x) + 12 */
         Log2( g_code, &exp, &frac );
         exp = exp - 12;
         tmp = frac >> 5;

         if ( ( frac & ( ( Word16 )1 << 4 ) ) != 0 ) {
            tmp++;
         }
         qua_ener_MR122 = tmp + ( exp << 10 );

         /* 24660 Q12 ~= 6.0206 = 20*log10(2) */
         tmp = exp * 49320;
         tmp += ( ( ( frac * 24660 ) >> 15 ) << 1 );

         /* Q12 * Q0 = Q13 -> Q10 */
         qua_ener = ( ( tmp << 13 ) + 0x00008000L ) >> 16;
      }
      else {
         p = &table_gain_lowrates[index];
         *gain_pit = *p++;
         g_code = *p++;
         qua_ener_MR122 = *p++;
         qua_ener = *p;
      }
   }

    /*
     * predict codebook gain
     * gc0 = Pow2(int(d)+frac(d))
     *     = 2^exp + 2^frac
     * gcode0 (Q14) = 2^14*2^frac = gc0 * 2^(14-exp)
     */
   gc_pred( pred_state, mode, code, &exp, &frac, NULL, NULL );
   gcode0 = Pow2( 14, frac );

    /*
     * read quantized gains, update table of past quantized energies
     * st->past_qua_en(Q10) = 20 * Log10(gFac) / constant
     *                      = Log2(gFac)
     *                      = qua_ener
     * constant = 20*Log10(2)
     */
   if ( exp < 11 ) {
      *gain_cod = ( g_code * gcode0 ) >> ( 25 - exp );
   }
   else {
      tmp = ( ( g_code * gcode0 ) << ( exp - 9 ) );

      if ( ( tmp >> ( exp - 9 ) ) != ( g_code * gcode0 ) ) {
         *gain_cod = 0x7FFF;
      }
      else {
         *gain_cod = tmp >> 16;
      }
   }

   /* update table of past quantized energies */
   gc_pred_update( pred_state, qua_ener_MR122, qua_ener );
   return;
}


/*
 * gc_pred_average_limited
 *
 *
 * Parameters:
 *    st->past_qua_en         I: MA predictor
 *    st->past_qua_en_MR122   I: MA predictor MR122
 *    ener_avg_MR122          O: everaged quantized energy (log2(quaErr))
 *    ener_avg                O: averaged quantized energy (20*log10(quaErr))
 *
 * Function:
 *    Compute average limited quantized energy
 * Returns:
 *    void
 */
static void gc_pred_average_limited( gc_predState *st, Word32 *ener_avg_MR122,
      Word32 *ener_avg )
{
   Word32 av_pred_en, i;


   /* do average in MR122 mode (log2() domain) */
   av_pred_en = 0;

   for ( i = 0; i < NPRED; i++ ) {
      av_pred_en = ( av_pred_en + st->past_qua_en_MR122[i] );
   }

   /* av_pred_en = 0.25*av_pred_en */
   av_pred_en = ( av_pred_en * 8192 ) >> 15;

   /* if (av_pred_en < -14/(20Log10(2))) av_pred_en = .. */
   if ( av_pred_en < MIN_ENERGY_MR122 ) {
      av_pred_en = MIN_ENERGY_MR122;
   }
   *ener_avg_MR122 = ( Word16 )av_pred_en;

   /* do average for other modes (20*log10() domain) */
   av_pred_en = 0;

   for ( i = 0; i < NPRED; i++ ) {
      av_pred_en = ( av_pred_en + st->past_qua_en[i] );
      if (av_pred_en < -32768)
         av_pred_en = -32768;
      else if (av_pred_en > 32767)
         av_pred_en = 32767;
   }

   /* av_pred_en = 0.25*av_pred_en */
   av_pred_en = ( av_pred_en * 8192 ) >> 15;

   *ener_avg = av_pred_en;
}


/*
 * ec_gain_code
 *
 *
 * Parameters:
 *    st->gbuf             I: last five gains
 *    st->past_gain_code   I: past gain
 *    pred_state           B: MA predictor state
 *    state                I: state of the state machine
 *    gain_code            O: decoded innovation gain
 *
 * Function:
 *    Conceal the codebook gain
 *
 * Returns:
 *    void
 */
static void ec_gain_code( ec_gain_codeState *st, gc_predState *pred_state,
      Word16 state, Word32 *gain_code )
{
   Word32 tmp, qua_ener_MR122, qua_ener;


   /* calculate median of last five gain values */
   tmp = gmed_n( st->gbuf, 5 );

   /* new gain = minimum(median, past_gain) * cdown[state] */
   if ( tmp > st->past_gain_code ) {
      tmp = st->past_gain_code;
   }
   tmp = ( tmp * cdown[state] ) >> 15;
   *gain_code = tmp;

      /*
       * update table of past quantized energies with average of
       * current values
       */
   gc_pred_average_limited( pred_state, &qua_ener_MR122, &qua_ener );
   gc_pred_update( pred_state, qua_ener_MR122, qua_ener );
}


/*
 * ec_gain_code_update
 *
 *
 * Parameters:
 *    st->gbuf             B: last five gains
 *    st->past_gain_code   O: past gain
 *    st->prev_gc          B  previous gain
 *    bfi                  I: bad indicator
 *    prev_bf              I: previous frame bad indicator
 *    gain_code            O: decoded innovation gain
 *
 * Function:
 *    Update the codebook gain concealment state
 *
 * Returns:
 *    void
 */
static void ec_gain_code_update( ec_gain_codeState *st, Word16 bfi,
      Word16 prev_bf, Word32 *gain_code )
{
   /* limit gain_code by previous good gain if previous frame was bad */
   if ( bfi == 0 ) {
      if ( prev_bf != 0 ) {
         if ( *gain_code > st->prev_gc ) {
            *gain_code = st->prev_gc;
         }
      }
      st->prev_gc = *gain_code;
   }

   /* update EC states: previous gain, gain buffer */
   st->past_gain_code = *gain_code;
   st->gbuf[0] = st->gbuf[1];
   st->gbuf[1] = st->gbuf[2];
   st->gbuf[2] = st->gbuf[3];
   st->gbuf[3] = st->gbuf[4];
   st->gbuf[4] = *gain_code;
   return;
}


/*
 * d_gain_code
 *
 *
 * Parameters:
 *    pred_state        B: MA predictor state
 *    mode              I: AMR mode (MR795 or MR122)
 *    index             I: received quantization index
 *    code              I: innovation codevector
 *    gain_code         O: decoded innovation gain
 *
 * Function:
 *    Decode the fixed codebook gain using the received index
 *
 * Returns:
 *    void
 */
static void d_gain_code( gc_predState *pred_state, enum Mode mode, Word32 index,
                        Word32 code[], Word32 *gain_code )
{
   Word32 g_code0, exp, frac, qua_ener_MR122, qua_ener;
   Word32 exp_inn_en, frac_inn_en, tmp, tmp2, i;
   const Word32 *p;


   /*
    * Decode codebook gain
    */
   gc_pred( pred_state, mode, code, &exp, &frac, &exp_inn_en, &frac_inn_en );
   p = &qua_gain_code[( ( index + index )+ index )];

   /* Different scalings between MR122 and the other modes */
   if ( mode == MR122 ) {
      /* predicted gain */
      g_code0 = Pow2( exp, frac );

      if ( g_code0 <= 2047 )
         g_code0 = g_code0 << 4;
      else
         g_code0 = 32767;
      *gain_code = ( ( g_code0 * *p++ ) >> 15 ) << 1;
      if (*gain_code & 0xFFFF8000)
         *gain_code = 32767;

   }
   else {
      g_code0 = Pow2( 14, frac );
      tmp = ( *p++ * g_code0 ) << 1;
      exp = 9 - exp;

      if ( exp > 0 ) {
         tmp = tmp >> exp;
      }
      else {
         for (i = exp; i < 0; i++) {
            tmp2 = tmp << 1;
            if ((tmp ^ tmp2) & 0x80000000) {
               tmp = (tmp & 0x80000000) ? 0x80000000 : 0x7FFFFFFF;
               break;
            }
            else {
               tmp = tmp2;
            }
         }
      }
      *gain_code = tmp >> 16;
      if (*gain_code & 0xFFFF8000)
         *gain_code = 32767;
   }

   /*
    * update table of past quantized energies
    */
   qua_ener_MR122 = *p++;
   qua_ener = *p++;
   gc_pred_update( pred_state, qua_ener_MR122, qua_ener );
   return;
}


/*
 * Int_lsf
 *
 *
 * Parameters:
 *    lsf_old           I: LSF vector at the 4th subframe of past frame
 *    lsf_new           I: LSF vector at the 4th subframe of present frame
 *    i_subfr           I: current subframe
 *    lsf_out           O: interpolated LSF parameters for current subframe
 *
 * Function:
 *    Interpolates the LSFs for selected subframe
 *
 *    The LSFs are interpolated at the 1st, 2nd and 3rd
 *    ubframe and only forwarded at the 4th subframe.
 *
 *    sf1:  3/4 F0 + 1/4 F1
 *    sf2:  1/2 F0 + 1/2 F1
 *    sf3:  1/4 F0 + 3/4 F1
 *    sf4:  F1
 *
 * Returns:
 *    void
 */
static void Int_lsf( Word32 lsf_old[], Word32 lsf_new[], int i_subfr, Word32
      lsf_out[] )
{
   Word32 i;


   switch ( i_subfr ) {
      case 0:
         for ( i = 0; i < 10; i++ ) {
            lsf_out[i] = lsf_old[i] - ( lsf_old[i] >> 2 ) + ( lsf_new[i] >> 2 );
         }
         break;

      case 40:
         for ( i = 0; i < 10; i++ ) {
            lsf_out[i] = ( lsf_old[i] >> 1 ) + ( lsf_new[i] >> 1 );
         }
         break;

      case 80:
         for ( i = 0; i < 10; i++ ) {
            lsf_out[i] = ( lsf_old[i] >> 2 ) - ( lsf_new[i] >> 2 ) +
                  lsf_new[i];
         }
         break;

      case 120:
         memcpy( lsf_out, lsf_new, M <<2 );
         break;
   }
}


/*
 * Cb_gain_average
 *
 *
 * Parameters:
 *    st->cbGainHistory B: codebook gain history
 *    st->hangCount     B: hangover counter
 *    mode              I: AMR mode
 *    gain_code         I: codebook gain
 *    lsp               I: The LSP for the current frame
 *    lspAver           I: The average of LSP for 8 frames
 *    bfi               I: bad frame indication
 *    prev_bf           I: previous bad frame indication
 *    pdfi              I: potential degraded bad frame indication
 *    prev_pdf          I: previous potential degraded bad frame indication
 *    inBackgroundNoise I: background noise decision
 *    voicedHangover    I: number of frames after last voiced frame
 *
 * Function:
 *    The mixed codebook gain, used to make codebook gain more smooth in background
 *
 *
 * Returns:
 *    void
 */
static Word32 Cb_gain_average( Cb_gain_averageState *st, enum Mode mode, Word32
      gain_code, Word32 lsp[], Word32 lspAver[], Word16 bfi, Word16 prev_bf,
      Word16 pdfi, Word16 prev_pdf, Word32 inBackgroundNoise, Word32
      voicedHangover )
{
   Word32 tmp[M];
   Word32 i, cbGainMix, tmp_diff, bgMix, cbGainMean, sum, diff, tmp1, tmp2;
   int shift1, shift2, shift;


   /* set correct cbGainMix for MR74, MR795, MR122 */
   cbGainMix = gain_code;

   /*
    * Store list of CB gain needed in the CB gain averaging                                           *
    */
   st->cbGainHistory[0] = st->cbGainHistory[1];
   st->cbGainHistory[1] = st->cbGainHistory[2];
   st->cbGainHistory[2] = st->cbGainHistory[3];
   st->cbGainHistory[3] = st->cbGainHistory[4];
   st->cbGainHistory[4] = st->cbGainHistory[5];
   st->cbGainHistory[5] = st->cbGainHistory[6];
   st->cbGainHistory[6] = gain_code;

   /* compute lsp difference */
   for ( i = 0; i < M; i++ ) {
      tmp1 = labs( lspAver[i]- lsp[i] );
      shift1 = 0;
      if (tmp1 != 0){
         while (!(tmp1 & 0x2000))
         {
            shift1++;
            tmp1 = tmp1 << 1;
         }
      }
      tmp2 = lspAver[i];
      shift2 = 0;
      if (tmp2 != 0){
         while (!(tmp2 & 0x4000))
         {
            shift2++;
            tmp2 = tmp2 << 1;
         }
      }
      tmp[i] = ( tmp1 << 15 ) / tmp2;
      shift = 2 + shift1 - shift2;

      if ( shift >= 0 ) {
         tmp[i] = tmp[i] >> shift;
      }
      else {
         tmp[i] = tmp[i] << -( shift );
      }
   }
   diff = *tmp + tmp[1] + tmp[2] + tmp[3] + tmp[4] + tmp[5] + tmp[6] + tmp[7] +
         tmp[8] + tmp[9];

   /* saturate */
   if ( diff > 32767 ) {
      diff = 32767;
   }

   /* Compute hangover */
   st->hangVar += 1;

   if ( diff <= 5325 ) {
      st->hangVar = 0;
   }

   if ( st->hangVar > 10 ) {
      /* Speech period, reset hangover variable */
      st->hangCount = 0;
   }

   /* Compute mix constant (bgMix) */
   bgMix = 8192;

   /* MR475, MR515, MR59, MR67, MR102 */
   if ( ( mode <= MR67 ) | ( mode == MR102 ) ) {
      /* disable mix if too short time since */
      if ( ( st->hangCount >= 40 ) & ( diff <= 5325 ) ) /* 0.65 in Q13 */ {
         /* if errors and presumed noise make smoothing probability stronger */
         if ( ( ( ( ( pdfi != 0 ) & ( prev_pdf != 0 ) ) | ( bfi != 0 ) | (
               prev_bf != 0 ) ) & ( ( voicedHangover > 1 ) ) & (
               inBackgroundNoise != 0 ) & ( mode < MR67 ) ) ) {
            /* bgMix = min(0.25, max(0.0, diff-0.55)) / 0.25; */
            tmp_diff = diff - 4506;   /* 0.55 in Q13 */

            /* max(0.0, diff-0.55) */
            tmp1 = 0;

            if ( tmp_diff > 0 ) {
               tmp1 = tmp_diff;
            }

            /* min(0.25, tmp1) */
            if ( 2048 >= tmp1 ) {
               bgMix = tmp1 << 2;
            }
         }
         else {
            /* bgMix = min(0.25, max(0.0, diff-0.40)) / 0.25; */
            tmp_diff = diff - 3277;   /* 0.4 in Q13 */

            /* max(0.0, diff-0.40) */
            tmp1 = 0;

            if ( tmp_diff > 0 ) {
               tmp1 = tmp_diff;
            }

            /* min(0.25, tmp1) */
            if ( 2048 >= tmp1 ) {
               bgMix = tmp1 << 2;
            }
         }
      }

      /*
       * Smoothen the cb gain trajectory
       * smoothing depends on mix constant bgMix
       */
      sum = st->cbGainHistory[2] + st->cbGainHistory[3] + st->cbGainHistory[4] +
            st->cbGainHistory[5] + st->cbGainHistory[6];

      if ( sum > 163822 ) {
         cbGainMean = 32767;
      }
      else {
         cbGainMean = ( 3277 * sum + 0x00002000L ) >> 14;   /* Q1 */
      }

      /* more smoothing in error and bg noise (NB no DFI used  here) */
      if ( ( ( bfi != 0 ) | ( prev_bf != 0 ) ) & ( inBackgroundNoise != 0 ) & (
            mode < MR67 ) ) {
         sum = 9362 * ( st->cbGainHistory[0] + st->cbGainHistory[1] + st->
               cbGainHistory[2] + st->cbGainHistory[3] + st->cbGainHistory[4] +
               st->cbGainHistory[5] + st->cbGainHistory[6] );
         cbGainMean = ( sum + 0x00008000L ) >> 16;   /* Q1 */
      }

      /* cbGainMix = bgMix*cbGainMix + (1-bgMix)*cbGainMean; */
      sum = bgMix * cbGainMix;   /* sum in Q14 */
      sum += cbGainMean << 13;
      sum -= bgMix * cbGainMean;
      cbGainMix = ( sum + 0x00001000L ) >> 13;

      /* Q1 */
   }
   st->hangCount += 1;
   if (st->hangCount & 0x80000000)
      st->hangCount = 40;
   return cbGainMix;
}


/*
 * ph_disp
 *
 *
 * Parameters:
 *    state->gainMem    B: LTP gain memory
 *    state->prevCbGain B: Codebook gain memory
 *    mode              I: AMR mode
 *    x                 B: LTP excitation signal -> total excitation signal
 *    cbGain            I: Codebook gain
 *    ltpGain           I: LTP gain
 *    inno              B: Innovation vector
 *    pitch_fac         I: pitch factor used to scale the LTP excitation
 *    tmp_shift         I: shift factor applied to sum of scaled LTP ex & innov.
 *                         before rounding
 *
 * Function:
 *    Adaptive phase dispersion; forming of total excitation
 *
 *
 * Returns:
 *    void
 */
static void ph_disp( ph_dispState *state, enum Mode mode, Word32 x[],
                    Word32 cbGain, Word32 ltpGain, Word32 inno[],
                    Word32 pitch_fac, Word32 tmp_shift)
{
   Word32 inno_sav[L_SUBFR], ps_poss[L_SUBFR];
   Word32 i, i1, impNr, temp1, temp2, j, nze, nPulse, ppos;
   const Word32 *ph_imp;   /* Pointer to phase dispersion filter */


   /* Update LTP gain memory */
   state->gainMem[4] = state->gainMem[3];
   state->gainMem[3] = state->gainMem[2];
   state->gainMem[2] = state->gainMem[1];
   state->gainMem[1] = state->gainMem[0];
   state->gainMem[0] = ltpGain;

   /* basic adaption of phase dispersion */
   /* no dispersion */
   impNr = 2;

   /* if (ltpGain < 0.9) */
   if ( ltpGain < PHDTHR2LTP ) {
      /* maximum dispersion */
      impNr = 0;

      /* if (ltpGain > 0.6 */
      if ( ltpGain > PHDTHR1LTP ) {
         /* medium dispersion */
         impNr = 1;
      }
   }

   /* onset indicator */
   /* onset = (cbGain  > onFact * cbGainMem[0]) */
   temp1 = ( ( state->prevCbGain * ONFACTPLUS1 ) + 0x1000 ) >> 13;

   if ( cbGain > temp1 ) {
      state->onset = ONLENGTH;
   }
   else {
      if ( state->onset > 0 ) {
         state->onset--;
      }
   }

   /*
    * if not onset, check ltpGain buffer and use max phase dispersion if
    * half or more of the ltpGain-parameters say so
    */
   if ( state->onset == 0 ) {
      /* Check LTP gain memory and set filter accordingly */
      i1 = 0;

      for ( i = 0; i < PHDGAINMEMSIZE; i++ ) {
         if ( state->gainMem[i] < PHDTHR1LTP ) {
            i1++;
         }
      }

      if ( i1 > 2 ) {
         impNr = 0;
      }
   }

   /* Restrict decrease in phase dispersion to one step if not onset */
   if ( ( impNr > ( state->prevState + 1 ) ) & ( state->onset == 0 ) ) {
      impNr--;
   }

   /* if onset, use one step less phase dispersion */
   if ( ( impNr<2 )&( state->onset>0 ) ) {
      impNr++;
   }

   /* disable for very low levels */
   if ( cbGain < 10 ) {
      impNr = 2;
   }

   if ( state->lockFull == 1 ) {
      impNr = 0;
   }

   /* update static memory */
   state->prevState = impNr;
   state->prevCbGain = cbGain;

   /*
    * do phase dispersion for all modes but 12.2 and 7.4;
    * don't modify the innovation if impNr >=2 (= no phase disp)
    */
   if ( ( mode != MR122 ) & ( mode != MR102 ) & ( mode != MR74 ) & ( impNr < 2 )
      ) {
      /*
       * track pulse positions, save innovation,
       * and initialize new innovation
       */
      nze = 0;

      for ( i = 0; i < L_SUBFR; i++ ) {
         if ( inno[i] != 0 ) {
            ps_poss[nze] = i;
            nze++;
         }
      }
      memcpy( inno_sav, inno, L_SUBFR <<2 );
      memset( inno, 0, L_SUBFR <<2 );

      /* Choose filter corresponding to codec mode and dispersion criterium */
      ph_imp = ph_imp_mid;

      if ( impNr == 0 ) {
         ph_imp = ph_imp_low;
      }

      if ( mode == MR795 ) {
         ph_imp = ph_imp_mid_MR795;

         if ( impNr == 0 ) {
            ph_imp = ph_imp_low_MR795;
         }
      }

      /* Do phase dispersion of innovation */
      for ( nPulse = 0; nPulse < nze; nPulse++ ) {
         ppos = ps_poss[nPulse];

         /* circular convolution with impulse response */
         j = 0;

         for ( i = ppos; i < L_SUBFR; i++ ) {
            /* inno[i1] += inno_sav[ppos] * ph_imp[i1-ppos] */
            temp1 = ( inno_sav[ppos] * ph_imp[j++] ) >> 15;
            inno[i] = inno[i] + temp1;
         }

         for ( i = 0; i < ppos; i++ ) {
            /* inno[i] += inno_sav[ppos] * ph_imp[L_SUBFR-ppos+i] */
            temp1 = ( inno_sav[ppos] * ph_imp[j++] ) >> 15;
            inno[i] = inno[i] + temp1;
         }
      }
   }

   /*
    * compute total excitation for synthesis part of decoder
    * (using modified innovation if phase dispersion is active)
    */
   for ( i = 0; i < L_SUBFR; i++ ) {
      /* x[i] = gain_pit*x[i] + cbGain*code[i]; */
      temp1 = x[i] * pitch_fac + inno[i] * cbGain;
      temp2 = temp1 << tmp_shift;
      x[i] = ( temp2 + 0x4000 ) >> 15;
      if (labs(x[i]) > 32767)
      {
         if ((temp1 ^ temp2) & 0x80000000) {
            x[i] = (temp1 & 0x80000000) ? -32768: 32767;
         }
         else {
            x[i] = (temp2 & 0x80000000) ? -32768: 32767;
         }
      }
   }
   return;
}


/*
 * sqrt_l_exp
 *
 *
 * Parameters:
 *    x                 I: input value
 *    exp               O: right shift to be applied to result
 *
 * Function:
 *    Sqrt with exponent value.
 *
 *    y = sqrt(x)
 *    x = f * 2^-e,   0.5 <= f < 1   (normalization)
 *    y = sqrt(f) * 2^(-e/2)
 *
 *    a) e = 2k   --> y = sqrt(f)   * 2^-k
 *       (k = e div 2, 0.707 <= sqrt(f) < 1)
 *    b) e = 2k+1 --> y = sqrt(f/2) * 2^-k
 *       (k = e div 2, 0.5 <= sqrt(f/2) < 0.707)
 *
 *
 * Returns:
 *    y                 output value
 */
static Word32 sqrt_l_exp( Word32 x, Word32 *exp )
{
   Word32 y, a, i, tmp;
   int e;


   if ( x <= ( Word32 )0 ) {
      *exp = 0;
      return( Word32 )0;
   }
   e=0;
   if (x != 0){
      tmp = x;
      while (!(tmp & 0x40000000))
      {
         e++;
         tmp = tmp << 1;
      }
   }
   e = e & 0xFFFE;
   x = ( x << e );
   *exp = ( Word16 )e;
   x = ( x >> 9 );
   i = ( Word16 )( x >> 16 );
   x = ( x >> 1 );
   a = x & ( Word16 )0x7fff;
   i = ( i - 16 );
   y = ( sqrt_table[i] << 16 );
   tmp = ( sqrt_table[i] - sqrt_table[i + 1] );
   y -= ( tmp * a ) << 1;
   return( y );
}


/*
 * Ex_ctrl
 *
 *
 * Parameters:
 *    excitation        B: Current subframe excitation
 *    excEnergy         I: Exc. Energy, sqrt(totEx*totEx)
 *    exEnergyHist      I: History of subframe energies
 *    voicedHangover    I: number of frames after last voiced frame
 *    prevBFI           I: Set i previous bad frame indicators
 *    carefulFlag       I: Restrict dymamic in scaling
 *
 * Function:
 *    Charaterice synthesis speech and detect background noise
 *
 * Returns:
 *    background noise decision; 0 = no bgn, 1 = bgn
 */
static Word16 Ex_ctrl( Word32 excitation[], Word32 excEnergy, Word32
      exEnergyHist[], Word32 voicedHangover, Word16 prevBFI, Word16 carefulFlag
      )
{
   Word32 i, testEnergy, scaleFactor, avgEnergy, prevEnergy, T0;
   int exp;


   /* get target level */
   avgEnergy = gmed_n( exEnergyHist, 9 );
   prevEnergy = ( exEnergyHist[7] + exEnergyHist[8] ) >> 1;

   if ( exEnergyHist[8] < prevEnergy ) {
      prevEnergy = exEnergyHist[8];
   }

   /* upscaling to avoid too rapid energy rises  for some cases */
   if ( ( excEnergy<avgEnergy )&( excEnergy>5 ) ) {
      /* testEnergy = 4*prevEnergy; */
      testEnergy = prevEnergy << 2;

      if ( ( voicedHangover < 7 ) || prevBFI != 0 ) {
         /* testEnergy = 3*prevEnergy */
         testEnergy = testEnergy - prevEnergy;
      }

      if ( avgEnergy > testEnergy ) {
         avgEnergy = testEnergy;
      }

      /* scaleFactor=avgEnergy/excEnergy in Q0 */
      exp=0;
      if (excEnergy != 0){
         while (!(excEnergy & 0x4000))
         {
            exp++;
            excEnergy = excEnergy << 1;
         }
      }
      excEnergy = 536838144 / excEnergy;
      T0 = ( avgEnergy * excEnergy ) << 1;
      T0 = ( T0 >> ( 20 - exp ) );

      if ( T0 > 32767 ) {
         /* saturate  */
         T0 = 32767;
      }
      scaleFactor = T0;

      /* test if scaleFactor > 3.0 */
      if ( ( carefulFlag != 0 ) & ( scaleFactor > 3072 ) ) {
         scaleFactor = 3072;
      }

      /* scale the excitation by scaleFactor */
      for ( i = 0; i < L_SUBFR; i++ ) {
         T0 = ( scaleFactor * excitation[i] ) << 1;
         T0 = ( T0 >> 11 );
         excitation[i] = T0;
      }
   }
   return 0;
}


/*
 * Inv_sqrt
 *
 *
 * Parameters:
 *    x                 I: input value
 *
 * Function:
 *    1/sqrt(x)
 *
 * Returns:
 *    y                 1/sqrt(x)
 */
static Word32 Inv_sqrt( Word32 x )
{
   int i, a, tmp, exp;
   Word32 y;


   if ( x <= ( Word32 )0 )
      return( ( Word32 )0x3fffffffL );
   exp=0;
   while (!(x & 0x40000000))
   {
      exp++;
      x = x << 1;
   }

   /* x is normalized */
   exp = ( 30 - exp );

   /* If exponent even -> shift right */
   if ( ( exp & 1 ) == 0 ) {
      x = ( x >> 1 );
   }
   exp = ( exp >> 1 );
   exp = ( exp + 1 );
   x = ( x >> 9 );

   /* Extract b25-b31 */
   i = ( Word16 )( x >> 16 );

   /* Extract b10-b24 */
   x = ( x >> 1 );
   a = x & ( Word16 )0x7fff;
   i = ( i - 16 );

   /* table[i] << 16 */
   y = inv_sqrt_table[i] << 16;

   /* table[i] - table[i+1]) */
   tmp = ( inv_sqrt_table[i] - inv_sqrt_table[i + 1] );

   /* y -= tmp*a*2 */
   y -= ( tmp * a ) << 1;

   /* denormalization */
   y = ( y >> exp );
   return( y );
}


/*
 * energy_old
 *
 *
 * Parameters:
 *    in                I: input value
 *
 * Function:
 *    Energy of signal
 *
 * Returns:
 *    Energy
 */
static Word32 energy_old( Word32 in[] )
{
   Word32 temp, i, sum = 0;


   for ( i = 0; i < L_SUBFR; i += 8 ) {
      temp = in[i] >> 2;
      sum += temp * temp;
      temp = in[i + 1] >> 2;
      sum += temp * temp;
      temp = in[i + 2] >> 2;
      sum += temp * temp;
      temp = in[i + 3] >> 2;
      sum += temp * temp;
      temp = in[i + 4] >> 2;
      sum += temp * temp;
      temp = in[i + 5] >> 2;
      sum += temp * temp;
      temp = in[i + 6] >> 2;
      sum += temp * temp;
      temp = in[i + 7] >> 2;
      sum += temp * temp;
   }

   if ( sum & 0xC0000000 ) {
      return 0x7FFFFFFF;
   }
   return( sum << 1 );
}


/*
 * energy_new
 *
 *
 * Parameters:
 *    in                I: input value
 *
 * Function:
 *    Energy of signal
 *
 * Returns:
 *    Energy
 */
static Word32 energy_new( Word32 in[] )
{
   Word32 i, s = 0, overflow = 0;

   s += in[0] * in[0];
   for ( i = 1; i < L_SUBFR; i += 3 ) {
      s += in[i] * in[i];
      s += in[i + 1] *in[i + 1];
      s += in[i + 2] * in[i + 2];


      if ( s & 0xC0000000 ) {
         overflow = 1;
         break;
      }
   }

   /* check for overflow */
   if ( overflow ) {
      s = energy_old( in );
   }
   else {
      s = ( s >> 3 );
   }
   return s;
}


/*
 * agc2
 *
 *
 * Parameters:
 *    sig_in            I: Post_Filter input signal
 *    sig_out           B: Post_Filter output signal
 *
 * Function:
 *    Scales the excitation on a subframe basis
 *
 * Returns:
 *    Energy
 */
static void agc2( Word32 *sig_in, Word32 *sig_out )
{
   Word32 s;
   int i, exp;
   Word16 gain_in, gain_out, g0;


   /* calculate gain_out with exponent */
   s = energy_new( sig_out );

   if ( s == 0 ) {
      return;
   }
   exp=0;
   while (!(s & 0x20000000))
   {
      exp++;
      s = s << 1;
   }

   gain_out = ( Word16 )( ( s + 0x00008000L ) >> 16 );

   /* calculate gain_in with exponent */
   s = energy_new( sig_in );

   if ( s == 0 ) {
      g0 = 0;
   }
   else {
      i = 0;
      while (!(s & 0x40000000))
      {
         i++;
         s = s << 1;
      }

      if ( s < 0x7fff7fff )
         gain_in = ( Word16 )( ( s + 0x00008000L ) >> 16 );
      else
         gain_in = 32767;
      exp = ( exp - i );

        /*
         * g0 = sqrt(gain_in/gain_out);
         */
      /* s = gain_out / gain_in */
      s = ( gain_out << 15 ) / gain_in;
      s = ( s << 7 );

      if ( exp > 0 )
         s = ( s >> exp );
      else
         s = ( s << ( -exp ) );
      s = Inv_sqrt( s );
      g0 = ( Word16 )( ( ( s << 9 ) + 0x00008000L ) >> 16 );
   }

   /* sig_out(n) = gain(n) * sig_out(n) */
   for ( i = 0; i < L_SUBFR; i++ ) {
      sig_out[i] = ( sig_out[i] * g0 ) >> 12;
   }
   return;
}


/*
 * Bgn_scd
 *
 *
 * Parameters:
 *    st->frameEnergyHist  B: Frame Energy memory
 *    st->bgHangover       B: Background hangover counter
 *    ltpGainHist          I: LTP gain history
 *    speech               I: synthesis speech frame
 *    voicedHangover       O: number of frames after last voiced frame
 *
 * Function:
 *    Charaterice synthesis speech and detect background noise
 *
 * Returns:
 *    inbgNoise         background noise decision; 0 = no bgn, 1 = bgn
 */
static Word16 Bgn_scd( Bgn_scdState *st, Word32 ltpGainHist[], Word32 speech[],
      Word32 *voicedHangover )
{
   Word32 temp, ltpLimit, frame_energyMin, currEnergy, noiseFloor, maxEnergy,
         maxEnergyLastPart, s, i;
   Word16 prevVoiced, inbgNoise;


   /*
    * Update the inBackgroundNoise flag (valid for use in next frame if BFI)
    * it now works as a energy detector floating on top
    * not as good as a VAD.
    */
   s = 0;

   for ( i = 0; i < L_FRAME; i++ ) {
      s += speech[i] * speech[i];
   }

   if ( (s < 0xFFFFFFF) & (s >= 0) )
      currEnergy = s >> 13;
   else
      currEnergy = 32767;
   frame_energyMin = 32767;

   for ( i = 0; i < L_ENERGYHIST; i++ ) {
      if ( st->frameEnergyHist[i] < frame_energyMin )
         frame_energyMin = st->frameEnergyHist[i];
   }

   /* Frame Energy Margin of 16 */
   noiseFloor = frame_energyMin << 4;
   maxEnergy = st->frameEnergyHist[0];

   for ( i = 1; i < L_ENERGYHIST - 4; i++ ) {
      if ( maxEnergy < st->frameEnergyHist[i] ) {
         maxEnergy = st->frameEnergyHist[i];
      }
   }
   maxEnergyLastPart = st->frameEnergyHist[2 * L_ENERGYHIST / 3];

   for ( i = 2 * L_ENERGYHIST / 3 + 1; i < L_ENERGYHIST; i++ ) {
      if ( maxEnergyLastPart < st->frameEnergyHist[i] ) {
         maxEnergyLastPart = st->frameEnergyHist[i];
      }
   }

   /* false */
   inbgNoise = 0;

   /*
    * Do not consider silence as noise
    * Do not consider continuous high volume as noise
    * Or if the current noise level is very low
    * Mark as noise if under current noise limit
    * OR if the maximum energy is below the upper limit
    */
   if ( ( maxEnergy> LOWERNOISELIMIT )&( currEnergy<FRAMEENERGYLIMIT )&(
         currEnergy>LOWERNOISELIMIT ) & ( ( currEnergy < noiseFloor ) || (
         maxEnergyLastPart < UPPERNOISELIMIT ) ) ) {
      if ( ( st->bgHangover + 1 ) > 30 ) {
         st->bgHangover = 30;
      }
      else {
         st->bgHangover += 1;
      }
   }
   else {
      st->bgHangover = 0;
   }

   /* make final decision about frame state, act somewhat cautiosly */
   if ( st->bgHangover > 1 )
      inbgNoise = 1;   /* true  */

   for ( i = 0; i < L_ENERGYHIST - 1; i++ ) {
      st->frameEnergyHist[i] = st->frameEnergyHist[i + 1];
   }
   st->frameEnergyHist[L_ENERGYHIST - 1] = currEnergy;

   /*
    * prepare for voicing decision;
    * tighten the threshold after some time in noise
    */
   ltpLimit = 13926;   /* 0.85  Q14 */

   if ( st->bgHangover > 8 ) {
      ltpLimit = 15565;   /* 0.95  Q14 */
   }

   if ( st->bgHangover > 15 ) {
      ltpLimit = 16383;   /* 1.00  Q14 */
   }

   /* weak sort of voicing indication. */
   prevVoiced = 0;   /* false */

   if ( gmed_n( &ltpGainHist[4], 5 ) > ltpLimit ) {
      prevVoiced = 1;   /* true  */
   }

   if ( st->bgHangover > 20 ) {
      if ( gmed_n( ltpGainHist, 9 ) > ltpLimit ) {
         prevVoiced = 1;   /* true  */
      }
      else {
         prevVoiced = 0;   /* false  */
      }
   }

   if ( prevVoiced ) {
      *voicedHangover = 0;
   }
   else {
      temp = *voicedHangover + 1;

      if ( temp > 10 ) {
         *voicedHangover = 10;
      }
      else {
         *voicedHangover = temp;
      }
   }
   return inbgNoise;
}


/*
 * dtx_dec_activity_update
 *
 *
 * Parameters:
 *    st->lsf_hist_ptr  B: LSF history pointer
 *    st->lsf_hist      B: LSF history
 *    lsf               I: lsf
 *    frame             I: noise frame
 *
 * Function:
 *    Update lsp history and compute log energy.
 *
 * Returns:
 *    void
 */
static void dtx_dec_activity_update( dtx_decState *st, Word32 lsf[], Word32
      frame[] )
{
   Word32 frame_en;
   Word32 log_en_e, log_en_m, log_en, i;


   /* update lsp history */
   st->lsf_hist_ptr += M;

   if ( st->lsf_hist_ptr == 80 ) {
      st->lsf_hist_ptr = 0;
   }
   memcpy( &st->lsf_hist[st->lsf_hist_ptr], lsf, M <<2 );

   /* compute log energy based on frame energy */
   frame_en = 0;   /* Q0 */

   for ( i = 0; (i < L_FRAME); i ++ ) {
      frame_en += frame[i] * frame[i];
      if (frame_en & 0x80000000)
         break;
   }

   log_en = (frame_en & 0xC0000000) ? 0x7FFFFFFE: (Word32)frame_en << 1;

   Log2( log_en , &log_en_e, &log_en_m );

   /* convert exponent and mantissa to Word16 Q10 */
   log_en = log_en_e << 10;   /* Q10 */
   log_en = log_en + ( log_en_m >> 5 );

   /* divide with L_FRAME i.e subtract with log2(L_FRAME) = 7.32193 */
   log_en = log_en - 8521;

   /*
    * insert into log energy buffer, no division by two as
    * log_en in decoder is Q11
    */
   st->log_en_hist_ptr += 1;

   if ( st->log_en_hist_ptr == DTX_HIST_SIZE ) {
      st->log_en_hist_ptr = 0;
   }
   st->log_en_hist[st->log_en_hist_ptr] = log_en;   /* Q11 */
}


/*
 * Decoder_amr
 *
 *
 * Parameters:
 *    st                B: State variables
 *    mode              I: AMR mode
 *    parm              I: vector of synthesis parameters
 *    frame_type        I: received frame type
 *    synth             O: synthesis speech
 *    A_t               O: decoded LP filter in 4 subframes
 *
 * Function:
 *    Speech decoder routine
 *
 * Returns:
 *    void
 */
static void Decoder_amr( Decoder_amrState *st, enum Mode mode, Word16 parm[],
      enum RXFrameType frame_type, Word32 synth[], Word32 A_t[] )
{
   /* LSPs */
   Word32 lsp_new[M];
   Word32 lsp_mid[M];


   /* LSFs */
   Word32 prev_lsf[M];
   Word32 lsf_i[M];


   /* Algebraic codevector */
   Word32 code[L_SUBFR];


   /* excitation */
   Word32 excp[L_SUBFR];
   Word32 exc_enhanced[L_SUBFR];


   /* Scalars */
   Word32 i, i_subfr, overflow, T0_frac, index, temp, temp2, subfrNr, excEnergy;
   Word32 gain_code, gain_code_mix, pit_sharp, pit_flag, pitch_fac, t0_min, t0_max;
   Word32 gain_pit = 0, evenSubfr = 0, T0 = 0, index_mr475 = 0;
   Word32 *Az;   /* Pointer on A_t */
   Word16 flag4, carefulFlag;
   Word16 delta_frc_low, delta_frc_range, tmp_shift;
   Word16 bfi = 0, pdfi = 0;
   /* bad frame indication flag, potential degraded bad frame flag */


   enum DTXStateType newDTXState;   /* SPEECH , DTX, DTX_MUTE */

   /* find the new  DTX state  SPEECH OR DTX */
   newDTXState = rx_dtx_handler( st->dtxDecoderState, frame_type );

   /* DTX actions */
   if ( newDTXState != SPEECH ) {
      Decoder_amr_reset( st, MRDTX );
      dtx_dec( st->dtxDecoderState, st->mem_syn, st->lsfState, st->pred_state,
            st->Cb_gain_averState, newDTXState, mode, parm, synth, A_t );

      /* update average lsp */
      Lsf_lsp( st->lsfState->past_lsf_q, st->lsp_old );
      lsp_avg( st->lsp_avg_st, st->lsfState->past_lsf_q );
      goto theEnd;
   }

   /* SPEECH action state machine  */
   if ( table_speech_bad[frame_type] ) {
      bfi = 1;

      if ( frame_type != RX_SPEECH_BAD ) {
         Build_CN_param( &st->nodataSeed, mode, parm );
      }
   }
   else if ( frame_type == RX_SPEECH_DEGRADED ) {
      pdfi = 1;
   }

   if ( bfi != 0 ) {
      st->state += 1;
   }
   else if ( st->state == 6 ) {
      st->state = 5;
   }
   else {
      st->state = 0;
   }

   if ( st->state > 6 ) {
      st->state = 6;
   }

    /*
     * If this frame is the first speech frame after CNI period,
     * set the BFH state machine to an appropriate state depending
     * on whether there was DTX muting before start of speech or not
     * If there was DTX muting, the first speech frame is muted.
     * If there was no DTX muting, the first speech frame is not
     * muted. The BFH state machine starts from state 5, however, to
     * keep the audible noise resulting from a SID frame which is
     * erroneously interpreted as a good speech frame as small as
     * possible (the decoder output in this case is quickly muted)
     */
   if ( st->dtxDecoderState->dtxGlobalState == DTX ) {
      st->state = 5;
      st->prev_bf = 0;
   }
   else if ( st->dtxDecoderState->dtxGlobalState == DTX_MUTE ) {
      st->state = 5;
      st->prev_bf = 1;
   }

   /* save old LSFs for CB gain smoothing */
   memcpy( prev_lsf, st->lsfState->past_lsf_q, M <<2 );

    /*
     * decode LSF parameters and generate interpolated lpc coefficients
     * for the 4 subframes
     */
   if ( mode != MR122 ) {
      D_plsf_3( st->lsfState, mode, bfi, parm, lsp_new );

      /* Advance synthesis parameters pointer */
      parm += 3;
      Int_lpc_1to3( st->lsp_old, lsp_new, A_t );
   }
   else {
      D_plsf_5( st->lsfState, bfi, parm, lsp_mid, lsp_new );

      /* Advance synthesis parameters pointer */
      parm += 5;
      Int_lpc_1and3( st->lsp_old, lsp_mid, lsp_new, A_t );
   }

   /* update the LSPs for the next frame */
   memcpy( st->lsp_old, lsp_new, M <<2 );

   /*
    * Loop for every subframe in the analysis frame
    *
    * The subframe size is L_SUBFR and the loop is repeated
    * L_FRAME/L_SUBFR times                                                                 *
    *  - decode the pitch delay
    *  - decode algebraic code
    *  - decode pitch and codebook gains
    *  - find the excitation and compute synthesis speech
    */
   /* pointer to interpolated LPC parameters */
   Az = A_t;
   evenSubfr = 0;
   subfrNr = -1;

   for ( i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR ) {
      subfrNr += 1;
      evenSubfr = 1 - evenSubfr;

      /* flag for first and 3th subframe */
      pit_flag = i_subfr;

      if ( i_subfr == L_FRAME_BY2 ) {
         if ( ( mode != MR475 ) & ( mode != MR515 ) ) {
            pit_flag = 0;
         }
      }

      /* pitch index */
      index = *parm++;

       /*
        * decode pitch lag and find adaptive codebook vector.
        */
      if ( mode != MR122 ) {
          /*
           * flag4 indicates encoding with 4 bit resolution;
           * this is needed for mode MR475, MR515, MR59 and MR67
           */
         flag4 = 0;

         if ( ( mode == MR475 ) || ( mode == MR515 ) || ( mode == MR59 ) || (
               mode == MR67 ) ) {
            flag4 = 1;
         }

          /*
           * get ranges for the t0_min and t0_max
           * only needed in delta decoding
           */
         delta_frc_low = 5;
         delta_frc_range = 9;

         if ( mode == MR795 ) {
            delta_frc_low = 10;
            delta_frc_range = 19;
         }
         t0_min = st->old_T0 - delta_frc_low;

         if ( t0_min < PIT_MIN ) {
            t0_min = PIT_MIN;
         }
         t0_max = t0_min + delta_frc_range;

         if ( t0_max > PIT_MAX ) {
            t0_max = PIT_MAX;
            t0_min = t0_max - delta_frc_range;
         }
         Dec_lag3( index, t0_min, t0_max, pit_flag, st->old_T0, &T0, &T0_frac,
               flag4 );
         st->T0_lagBuff = T0;

         if ( bfi != 0 ) {
            if ( st->old_T0 < PIT_MAX ) {
               /* Graceful pitch degradation */
               st->old_T0 += 1;
            }
            T0 = st->old_T0;
            T0_frac = 0;

            if ( ( st->inBackgroundNoise != 0 ) & ( st->voicedHangover > 4 ) & (
                  ( mode == MR475 ) || ( mode == MR515 ) || ( mode == MR59 ) ) )
            {
               T0 = st->T0_lagBuff;
            }
         }
         Pred_lt_3or6_40( st->exc, T0, T0_frac, 1 );
      }
      else {
         Dec_lag6( index, PIT_MIN_MR122, PIT_MAX, pit_flag, &T0, &T0_frac );

         if ( ( bfi != 0 ) || ( ( pit_flag != 0 ) & ( index > 60 ) ) ) {
            st->T0_lagBuff = T0;
            T0 = st->old_T0;
            T0_frac = 0;
         }
         Pred_lt_3or6_40( st->exc, T0, T0_frac, 0 );
      }

       /*
        * (MR122 only: Decode pitch gain.)
        * Decode innovative codebook.
        * set pitch sharpening factor
        */
      /* MR475, MR515 */
      if ( ( mode == MR475 ) || ( mode == MR515 ) ) {
         /* index of position */
         index = *parm++;

         /* signs */
         i = *parm++;
         decode_2i40_9bits( subfrNr, i, index, code );
         pit_sharp = st->sharp << 1;
      }

      /* MR59 */
      else if ( mode == MR59 ) {
         /* index of position */
         index = *parm++;

         /* signs */
         i = *parm++;
         decode_2i40_11bits( i, index, code );
         pit_sharp = st->sharp << 1;
      }

      /* MR67 */
      else if ( mode == MR67 ) {
         /* index of position */
         index = *parm++;

         /* signs */
         i = *parm++;
         decode_3i40_14bits( i, index, code );
         pit_sharp = st->sharp << 1;
      }

      /* MR74, MR795 */
      else if ( mode <= MR795 ) {
         /* index of position */
         index = *parm++;

         /* signs */
         i = *parm++;
         decode_4i40_17bits( i, index, code );
         pit_sharp = st->sharp << 1;
      }

      /* MR102 */
      else if ( mode == MR102 ) {
         decode_8i40_31bits( parm, code );
         parm += 7;
         pit_sharp = st->sharp << 1;
      }

      /* MR122 */
      else {
         index = *parm++;

         if ( bfi != 0 ) {
            ec_gain_pitch( st->ec_gain_p_st, st->state, &gain_pit );
         }
         else {
            gain_pit = d_gain_pitch( mode, index );
         }
         ec_gain_pitch_update( st->ec_gain_p_st, bfi, st->prev_bf, &gain_pit );
         decode_10i40_35bits( parm, code );
         parm += 10;

           /*
            * pit_sharp = gain_pit;
            * if (pit_sharp > 1.0) pit_sharp = 1.0;
            */
         pit_sharp = gain_pit;

         if ( pit_sharp > 16383 )
            pit_sharp = 32767;
         else
            pit_sharp *= 2;
      }

        /*
         * Add the pitch contribution to code[].
         */
      for ( i = T0; i < L_SUBFR; i++ ) {
         temp = ( code[i - T0] * pit_sharp ) >> 15;
         code[i] = code[i] + temp;
      }

        /*
         * Decode codebook gain (MR122) or both pitch
         * gain and codebook gain (all others)
         * Update pitch sharpening "sharp" with quantized gain_pit
         */
      if ( mode == MR475 ) {
         /* read and decode pitch and code gain */
         if ( evenSubfr != 0 ) {
            /* index of gain(s) */
            index_mr475 = *parm++;
         }

         if ( bfi == 0 ) {
            Dec_gain( st->pred_state, mode, index_mr475, code, evenSubfr, &
                  gain_pit, &gain_code );
         }
         else {
            ec_gain_pitch( st->ec_gain_p_st, st->state, &gain_pit );
            ec_gain_code( st->ec_gain_c_st, st->pred_state, st->state, &
                  gain_code );
         }
         ec_gain_pitch_update( st->ec_gain_p_st, bfi, st->prev_bf, &gain_pit );
         ec_gain_code_update( st->ec_gain_c_st, bfi, st->prev_bf, &gain_code );
         pit_sharp = gain_pit;

         if ( pit_sharp > SHARPMAX ) {
            pit_sharp = SHARPMAX;
         }
      }
      else if ( ( mode <= MR74 ) || ( mode == MR102 ) ) {
         /* read and decode pitch and code gain */
         /* index of gain(s) */
         index = *parm++;

         if ( bfi == 0 ) {
            Dec_gain( st->pred_state, mode, index, code, evenSubfr, &gain_pit, &
                  gain_code );
         }
         else {
            ec_gain_pitch( st->ec_gain_p_st, st->state, &gain_pit );
            ec_gain_code( st->ec_gain_c_st, st->pred_state, st->state, &
                  gain_code );
         }
         ec_gain_pitch_update( st->ec_gain_p_st, bfi, st->prev_bf, &gain_pit );
         ec_gain_code_update( st->ec_gain_c_st, bfi, st->prev_bf, &gain_code );
         pit_sharp = gain_pit;

         if ( pit_sharp > SHARPMAX ) {
            pit_sharp = SHARPMAX;
         }

         if ( mode == MR102 ) {
            if ( st->old_T0 > ( L_SUBFR + 5 ) ) {
               pit_sharp = pit_sharp >> 2;
            }
         }
      }
      else {
         /* read and decode pitch gain */
         /* index of gain(s) */
         index = *parm++;

         if ( mode == MR795 ) {
            /* decode pitch gain */
            if ( bfi != 0 ) {
               ec_gain_pitch( st->ec_gain_p_st, st->state, &gain_pit );
            }
            else {
               gain_pit = d_gain_pitch( mode, index );
            }
            ec_gain_pitch_update( st->ec_gain_p_st, bfi, st->prev_bf, &gain_pit
                  );

            /* read and decode code gain */
            index = *parm++;

            if ( bfi == 0 ) {
               d_gain_code( st->pred_state, mode, index, code, &gain_code );
            }
            else {
               ec_gain_code( st->ec_gain_c_st, st->pred_state, st->state, &
                     gain_code );
            }
            ec_gain_code_update( st->ec_gain_c_st, bfi, st->prev_bf, &gain_code
                  );
            pit_sharp = gain_pit;

            if ( pit_sharp > SHARPMAX ) {
               pit_sharp = SHARPMAX;
            }
         }
         else {   /* MR122 */

            if ( bfi == 0 ) {
               d_gain_code( st->pred_state, mode, index, code, &gain_code );
            }
            else {
               ec_gain_code( st->ec_gain_c_st, st->pred_state, st->state, &
                     gain_code );
            }
            ec_gain_code_update( st->ec_gain_c_st, bfi, st->prev_bf, &gain_code
                  );
            pit_sharp = gain_pit;
         }
      }

        /*
         * store pitch sharpening for next subframe
         * (for modes which use the previous pitch gain for
         *  pitch sharpening in the search phase)
         * do not update sharpening in even subframes for MR475
         */
      if ( ( mode != MR475 ) || evenSubfr == 0 ) {
         st->sharp = gain_pit;

         if ( st->sharp > SHARPMAX ) {
            st->sharp = SHARPMAX;
         }
      }

      if ( pit_sharp > 16383 )
         pit_sharp = 32767;
      else
         pit_sharp *= 2;

      if ( pit_sharp > 16384 ) {
         for ( i = 0; i < L_SUBFR; i++ ) {
            temp = ( st->exc[i] * pit_sharp ) >> 15;
            temp2 = ( temp * gain_pit ) << 1;

            if ( mode == MR122 ) {
               temp2 = ( temp2 >> 1 );
            }
            excp[i] = ( temp2 + 0x00008000L ) >> 16;
         }
      }

        /*
         * Store list of LTP gains needed in the source
         * characteristic detector (SCD)
         */
      if ( bfi == 0 ) {
         for (i = 0; i < 8; i++){
            st->ltpGainHistory[i] = st->ltpGainHistory[i+1];
         }
         st->ltpGainHistory[8] = gain_pit;
      }


        /*
         * Limit gain_pit if in background noise and BFI
         * for MR475, MR515, MR59
         */
      if ( ( st->prev_bf != 0 || bfi != 0 ) & ( st->inBackgroundNoise != 0 ) & (
            ( mode == MR475 ) || ( mode == MR515 ) || ( mode == MR59 ) ) ) {
         /* if (gain_pit > 0.75) in Q14*/
         if ( gain_pit > 12288 )
            /* gain_pit = (gain_pit-0.75)/2.0 + 0.75; */
            gain_pit = ( ( gain_pit - 12288 ) >> 1 ) + 12288;

         /* if (gain_pit > 0.90) in Q14*/
         if ( gain_pit > 14745 ) {
            gain_pit = 14745;
         }
      }

        /*
         * Calculate CB mixed gain
         */
      Int_lsf( prev_lsf, st->lsfState->past_lsf_q, i_subfr, lsf_i );
      gain_code_mix = Cb_gain_average( st->Cb_gain_averState, mode, gain_code,
            lsf_i, st->lsp_avg_st->lsp_meanSave, bfi, st->prev_bf, pdfi, st->
            prev_pdf, st->inBackgroundNoise, st->voicedHangover );

      /* make sure that MR74, MR795, MR122 have original codeGain*/
      /* MR74, MR795, MR122 */
      if ( ( mode > MR67 ) & ( mode != MR102 ) ) {
         gain_code_mix = gain_code;
      }

        /*
         * Find the total excitation.
         * Find synthesis speech corresponding to st->exc[].
         */
      /* MR475, MR515, MR59, MR67, MR74, MR795, MR102*/
      if ( mode <= MR102 ) {
         pitch_fac = gain_pit;
         tmp_shift = 1;
      }

      /* MR122 */
      else {
         pitch_fac = gain_pit >> 1;
         tmp_shift = 2;
      }

        /*
         * copy unscaled LTP excitation to exc_enhanced (used in phase
         * dispersion below) and compute total excitation for LTP feedback
         */
      memcpy( exc_enhanced, st->exc, L_SUBFR <<2 );

      for ( i = 0; i < L_SUBFR; i++ ) {
         /* st->exc[i] = gain_pit*st->exc[i] + gain_code*code[i]; */
         temp = ( st->exc[i] * pitch_fac ) + ( code[i] * gain_code );
         temp2 = ( temp << tmp_shift );
         if (((temp2 >> 1) ^ temp2) & 0x40000000) {
            if ((temp ^ temp2) & 0x80000000) {
               temp2 = (temp & 0x80000000) ? (-1073741824L) : 1073725439;
            }
            else {
               temp2 = (temp2 & 0x80000000) ? (-1073741824L) : 1073725439;
            }
         }
         st->exc[i] = ( temp2 + 0x00004000L ) >> 15;
      }
      /*
       * Adaptive phase dispersion
       */

      /* free phase dispersion adaption */
      st->ph_disp_st->lockFull = 0;

      if ( ( ( mode == MR475 ) || ( mode == MR515 ) || ( mode == MR59 ) ) & ( st
            ->voicedHangover > 3 ) & ( st->inBackgroundNoise != 0 ) & ( bfi != 0
            ) ) {
           /*
            * Always Use full Phase Disp.
            * if error in bg noise
            */
         st->ph_disp_st->lockFull = 1;
      }

        /*
         * apply phase dispersion to innovation (if enabled) and
         * compute total excitation for synthesis part
         */
      ph_disp( st->ph_disp_st, mode, exc_enhanced, gain_code_mix, gain_pit, code
            , pitch_fac, tmp_shift );

        /*
         * The Excitation control module are active during BFI.
         * Conceal drops in signal energy if in bg noise.
         */
      temp2 = 0;

      for ( i = 0; i < L_SUBFR; i++ ) {
         temp2 += ( exc_enhanced[i] * exc_enhanced[i] );
      }

      if ( temp2 > 0x3FFFFFFF ) {
         excEnergy = 11584;
      }
      else {
         temp2 = sqrt_l_exp( temp2, &temp );
         temp2 = ( temp2 >> ( ( temp >> 1 ) + 15 ) );
         excEnergy = temp2 >> 2;
      }

      if ( ( ( mode == MR475 ) || ( mode == MR515 ) || ( mode == MR59 ) ) & ( st
            ->voicedHangover > 5 ) & ( st->inBackgroundNoise != 0 ) & ( st->
            state < 4 ) & ( ( ( pdfi != 0 ) & ( st->prev_pdf != 0 ) ) || bfi !=
            0 || st->prev_bf != 0 ) ) {
         carefulFlag = 0;

         if ( ( pdfi != 0 ) & ( bfi == 0 ) ) {
            carefulFlag = 1;
         }
         Ex_ctrl( exc_enhanced, excEnergy, st->excEnergyHist, st->voicedHangover
               , st->prev_bf, carefulFlag );
      }

      if ( ( st->inBackgroundNoise != 0 ) & ( bfi != 0 || st->prev_bf != 0 ) & (
            st->state < 4 ) ) {;   /* do nothing! */
      }
      else {
         /* Update energy history for all modes */
         for (i = 0; i < 8; i++){
            st->excEnergyHist[i] = st->excEnergyHist[i+1];
         }
         st->excEnergyHist[8] = excEnergy;
      }

        /*
         * Excitation control module end.
         */
      if ( pit_sharp > 16384 ) {
         for ( i = 0; i < L_SUBFR; i++ ) {
            excp[i] = excp[i] + exc_enhanced[i];
            if (labs(excp[i]) > 32767)
               excp[i] = (excp[i] & 0x80000000) ? -32768 : 32767;
         }
         agc2( exc_enhanced, excp );
         overflow = Syn_filt( Az, excp, &synth[i_subfr], L_SUBFR, st->mem_syn, 0
            );
      }
      else {
         overflow = Syn_filt( Az, exc_enhanced, &synth[i_subfr], L_SUBFR, st->
            mem_syn, 0 );
      }

      if ( overflow ) {
         for ( i = 0; i < PIT_MAX + L_INTERPOL + L_SUBFR; i++ ) {
            st->old_exc[i] = st->old_exc[i] >> 2;
         }

         for ( i = 0; i < L_SUBFR; i++ ) {
            exc_enhanced[i] = exc_enhanced[i] >> 2;
         }
         Syn_filt_overflow( Az, exc_enhanced, &synth[i_subfr], L_SUBFR, st->mem_syn, 1 );
      }
      else {
         memcpy( st->mem_syn, &synth[i_subfr + 30], 40 );
      }

        /*
         * Update signal for next frame.
         * -> shift to the left by L_SUBFR  st->exc[]
         */
      memcpy( &st->old_exc[0], &st->old_exc[L_SUBFR], ( PIT_MAX + L_INTERPOL )<<
            2 );

      /* interpolated LPC parameters for next subframe */
      Az += MP1;

      /* store T0 for next subframe */
      st->old_T0 = T0;
   }

    /*
     * Call the Source Characteristic Detector which updates
     * st->inBackgroundNoise and st->voicedHangover.
     */
   st->inBackgroundNoise = Bgn_scd( st->background_state, &( st->ltpGainHistory[
         0] ), &( synth[0] ), &( st->voicedHangover ) );
   dtx_dec_activity_update( st->dtxDecoderState, st->lsfState->past_lsf_q, synth
         );

   /* store bfi for next subframe */
   st->prev_bf = bfi;
   st->prev_pdf = pdfi;

    /*
     * Calculate the LSF averages on the eight
     * previous frames
     */
   lsp_avg( st->lsp_avg_st, st->lsfState->past_lsf_q );
theEnd:
   st->dtxDecoderState->dtxGlobalState = newDTXState;
   return;
}


/*
 * Residu40
 *
 *
 * Parameters:
 *    a                 I: prediction coefficients
 *    x                 I: speech signal
 *    y                 O: residual signal
 *
 * Function:
 *    The LP residual is computed by filtering the input
 *    speech through the LP inverse filter a(z)
 *
 * Returns:
 *    void
 */
static void Residu40( Word32 a[], Word32 x[], Word32 y[] )
{
   Word32 s, i, j;


   for ( i = 0; i < 40; i++ ) {
      s = a[0] * x[i] + a[1] * x[i - 1] + a[2] * x[i - 2] + a[3] * x[i - 3];
      s += a[4] * x[i - 4] + a[5] * x[i - 5] + a[6] * x[i - 6] + a[7] * x[i - 7]
         ;
      s += a[8] * x[i - 8] + a[9] * x[i - 9] + a[10] * x[i - 10];
      y[i] = ( s + 0x800 ) >> 12;
      if (abs(y[i]) > 32767){
         /* go to safe mode */
         for (i = 0; i < 40; i++) {
            s = a[0] * x[i];
            for (j = 1; j <= 10; j++) {
               s += a[j] * x[i - j];
               if (s > 1073741823){
                  s = 1073741823;
               }
               else if ( s < -1073741824) {
                  s = -1073741824;
               }
            }
            y[i] = ( s + 0x800 ) >> 12;
            if (abs(y[i]) > 32767)
               y[i] = (y[i] & 0x80000000) ? -32768 : 32767;
         }
         return;
      }

   }
   return;
}


/*
 * agc
 *
 *
 * Parameters:
 *    st->past_gain     B: gain memory
 *    sig_in            I: Post_Filter input signal
 *    sig_out           B: Post_Filter output signal
 *    agc_fac           I: AGC factor
 *
 * Function:
 *    Scales the Post_Filter output on a subframe basis
 *
 * Returns:
 *    void
 */
static void agc( agcState *st, Word32 *sig_in, Word32 *sig_out, Word16 agc_fac )
{
   Word32 s, gain_in, gain_out, g0, gain;
   int exp, i;


   /* calculate gain_out with exponent */
   s = energy_new( sig_out );

   if ( s == 0 ) {
      st->past_gain = 0;
      return;
   }
   exp=0;
   i = s;
   while (!(i & 0x40000000))
   {
      exp++;
      i = i << 1;
   }
   exp -=1;
   if (exp & 0x80000000) {
      s >>= 1;
   }
   else {
      s <<= exp;
   }
   gain_out = ( s + 0x00008000L ) >> 16;

   /* calculate gain_in with exponent */
   s = energy_new( sig_in );

   if ( s == 0 ) {
      g0 = 0;
   }
   else {
      i=0;
   while (!(s & 0x40000000))
   {
      i++;
      s = s << 1;
   }
      s = s + 0x00008000L;

      if ( s >= 0 )
         gain_in = s >> 16;
      else
         gain_in = 32767;
      exp = ( exp - i );

      /*
       * g0 = (1-agc_fac) * sqrt(gain_in/gain_out);
       */
      /* s = gain_out / gain_in */
      s = ( gain_out << 15 ) / gain_in;
      exp = 7 - exp;

      if ( exp > 0 ){
         if (exp > 31)
         {
            if(s){
               s = 2147483647;
            }
         }
         else {
            s = s << exp ;
         }
      }
      else
         s = ( s >> ( -exp ) );
      if (s < 0)
         s = 2147483647;
      s = Inv_sqrt( s );
      i = ( ( s << 9 ) + 0x00008000L ) >> 16;
      if (i & 0xFFFF8000)
         i = 32767;

      /* g0 = i * (1-agc_fac) */
      g0 = ( i * ( 32767 - agc_fac ) ) >> 15;
   }

   /*
    * compute gain[n] = agc_fac * gain[n-1] + (1-agc_fac) * sqrt(gain_in/gain_out)
    * sig_out[n] = gain[n] * sig_out[n]
    */
   gain = st->past_gain;

   for ( i = 0; i < L_SUBFR; i++ ) {
      gain = ( gain * agc_fac ) >> 15;
      gain = gain + g0;
      sig_out[i] = ( sig_out[i] * gain ) >> 12;
      if (labs(sig_out[i]) > 32767)
         sig_out[i] = (sig_out[i] & 0x8000000) ? -32768 : 32767;
   }
   st->past_gain = gain;
   return;
}


/*
 * Post_Filter
 *
 *
 * Parameters:
 *    st                B: post filter states
 *    mode              I: AMR mode
 *    syn               B: synthesis speech
 *    Az_4              I: interpolated LPC parameters in all subfr.
 *
 * Function:
 *    Post_Filtering of synthesis speech.
 *
 *    inverse filtering of syn[] through A(z/0.7) to get res2[]
 *    tilt compensation filtering; 1 - MU*k*z^-1
 *    synthesis filtering through 1/A(z/0.75)
 *    adaptive gain control
 *
 * Returns:
 *    void
 */
static void Post_Filter( Post_FilterState *st, enum Mode mode, Word32 *syn,
      Word32 *Az_4 )
{
   Word32 h[22], Ap3[MP1], Ap4[MP1];   /* bandwidth expanded LP parameters */
   Word32 tmp, i_subfr, i, temp1, temp2, overflow = 0;
   Word32 *Az, *p1, *p2, *syn_work = &st->synth_buf[M];
   const Word32 *pgamma3 = &gamma3[0];
   const Word32 *pgamma4 = &gamma4_gamma3_MR122[0];


   /*
    * Post filtering
    */
   memcpy( syn_work, syn, L_FRAME <<2 );
   Az = Az_4;

   if ( ( mode == MR122 ) || ( mode == MR102 ) ) {
      pgamma3 = &gamma4_gamma3_MR122[0];
      pgamma4 = &gamma4_MR122[0];
   }

   for ( i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR ) {
      /* Find weighted filter coefficients Ap3[] and Ap[4] */
      Ap3[0] = Az[0];
      Ap4[0] = Az[0];

      for ( i = 1; i <= 10; i++ ) {
         Ap3[i] = ( Az[i] * pgamma3[i - 1] +0x4000 ) >> 15;
         Ap4[i] = ( Az[i] * pgamma4[i - 1] +0x4000 ) >> 15;
      }

      /* filtering of synthesis speech by A(z/0.7) to find res2[] */
      Residu40( Ap3, &syn_work[i_subfr], st->res2 );

      /* tilt compensation filter */
      /* impulse response of A(z/0.7)/A(z/0.75) */
      memcpy( h, Ap3, MP1 <<2 );
      memset( &h[M +1], 0, ( 22 - M - 1 )<<2 );
      Syn_filt( Ap4, h, h, 22, &h[M +1], 0 );

      /* 1st correlation of h[] */
      tmp = 16777216 + h[1] * h[1];

      for ( i = 2; i < 22; i++ ) {
         tmp += h[i] * h[i];
         if (tmp > 0x3FFF8000)
            break;
      }
      temp1 = tmp >> 15;
      if (temp1 & 0xFFFF8000)
         temp1 = 32767;

      tmp = h[0] * h[1];

      for ( i = 1; i < 21; i++ ) {
         tmp += h[i] * h[i + 1];
         if (abs(tmp) > 1073741823)
            tmp = 1073741823;
      }
      temp2 = tmp >> 15;

      if ( temp2 <= 0 ) {
         temp2 = 0;
      }
      else {
         tmp = temp2 * 26214;
         temp2 = ( tmp & 0xffff8000 ) / temp1;
      }

      /* preemphasis */
      p1 = st->res2 + 39;
      p2 = p1 - 1;
      tmp = *p1;

      do {
         *p1 = *p1 - ( ( temp2 * *p2-- ) >> 15 );
         if (abs(*p1) > 32767) {
            *p1 = (*p1 & 0x80000000) ? -32768 : 32767;
         }
         p1--;
         *p1 = *p1 - ( ( temp2 * *p2-- ) >> 15 );
         if (abs(*p1) > 32767) {
            *p1 = (*p1 & 0x80000000) ? -32768 : 32767;
         }
         p1--;
         *p1 = *p1 - ( ( temp2 * *p2-- ) >> 15 );
         if (abs(*p1) > 32767) {
            *p1 = (*p1 & 0x80000000) ? -32768 : 32767;
         }
         p1--;
      } while( p1 > st->res2 );
      *p1 = *p1 - ( ( temp2 * st->preemph_state_mem_pre ) >> 15 );
      if (abs(*p1) > 32767) {
         *p1 = (*p1 & 0x80000000) ? -32768 : 32767;
      }
      st->preemph_state_mem_pre = tmp;

      /* filtering through  1/A(z/0.75) */
      overflow = Syn_filt( Ap4, st->res2, &syn[i_subfr], L_SUBFR, st->mem_syn_pst, 0 );
      if (overflow){
         Syn_filt_overflow( Ap4, st->res2, &syn[i_subfr], L_SUBFR, st->mem_syn_pst, 1 );
         overflow = 0;
      }
      else {
         memcpy(st->mem_syn_pst, &syn[i_subfr + 30], 40);
      }

      /* scale output to input */
      agc( st->agc_state, &syn_work[i_subfr], &syn[i_subfr], AGC_FAC );
      Az += MP1;
   }

   /* update syn_work[] buffer */
   memcpy( &syn_work[- M], &syn_work[L_FRAME - M], M <<2 );
   return;
}


/*
 * Post_Process
 *
 *
 * Parameters:
 *    st                B: post filter states
 *    signal            B: signal
 *
 * Function:
 *    Postprocessing of input speech.
 *
 *    2nd order high pass filtering with cut off frequency at 60 Hz.
 *    Multiplication of output by two.
 *
 *
 * Returns:
 *    void
 */
 static void Post_Process( Post_ProcessState *st, Word32 signal[] )
 {
    Word32 x2, tmp, i = 0;
    Word32 mask = 0x40000000;

    do {
       x2 = st->x1;
       st->x1 = st->x0;
       st->x0 = signal[i];

       /*
       * y[i] = b[0]*x[i]*2 + b[1]*x[i-1]*2 + b140[2]*x[i-2]/2
       *                    + a[1]*y[i-1] + a[2] * y[i-2];
       */
       tmp = ( st->y1_hi * 15836) + ( ( ( st->y1_lo * 15836 ) & ( Word32 )0xffff8000 ) >> 15);
       tmp += (st->y2_hi * -7667) + ( ( ( st->y2_lo * ( -7667 ) ) & ( Word32 )0xffff8000 ) >> 15);
       tmp += st->x0 * 7699;
       tmp += st->x1 * -15398;
       if ( ( (tmp >> 1) ^ tmp ) & mask)
          tmp = (tmp & 0x80000000) ? -1073741824 : 1073741823;

       tmp += x2 * 7699;
       if ( ( (tmp >> 1) ^ tmp ) & mask)
          tmp = (tmp & 0x80000000) ? -1073741824 : 1073741823;

       tmp = tmp << 1;
       if ( ( (tmp >> 1) ^ tmp ) & mask)
          tmp = (tmp & 0x80000000) ? -1073741824 : 1073741823;

       tmp = tmp << 1;
       if ( ( (tmp >> 1) ^ tmp ) & mask)
          tmp = (tmp & 0x80000000) ? -1073741824 : 1073741823;

       if ( labs( tmp ) < 536862720 ) {
          signal[i++] = ( tmp + 0x00002000L ) >> 14;
       }
       else if ( tmp > 0 ) {
          signal[i++] = 32767;
       }
       else {
          signal[i++] = -32768;
       }
       st->y2_hi = st->y1_hi;
       st->y2_lo = st->y1_lo;
       st->y1_hi = tmp >> 15;
       st->y1_lo = ( ( tmp << 1 ) - ( st->y1_hi << 16 ) ) >> 1;
    } while( i < 160 );
    return;
}


/*
 * Speech_Decode_Frame
 *
 *
 * Parameters:
 *    st                B: decoder memory
 *    mode              I: AMR mode
 *    parm              I: speech parameters
 *    frame_type        I: Frame type
 *    synth             O: synthesis speech

 * Function:
 *    Decode one frame
 *
 * Returns:
 *    void
 */
void Speech_Decode_Frame( void *st, enum Mode mode, Word16 *parm, enum
      RXFrameType frame_type, Word16 *synth )
{
   Word32 Az_dec[AZ_SIZE];   /* Decoded Az for post-filter in 4 subframes*/
   Word32 synth_speech[L_FRAME];
   Word32 i;

   /* Synthesis */
   Decoder_amr( ( ( Speech_Decode_FrameState * ) st )->decoder_amrState, mode,
         parm, frame_type, synth_speech, Az_dec );
   Post_Filter( ( ( Speech_Decode_FrameState * ) st )->post_state, mode,
         synth_speech, Az_dec );

   /* post HP filter, and 15->16 bits */
   Post_Process( ( ( Speech_Decode_FrameState * ) st )->postHP_state,
         synth_speech );

for ( i = 0; i < L_FRAME; i++ ) {
#ifndef NO13BIT
      /* Truncate to 13 bits */
      synth[i] = ( Word16 )( synth_speech[i] & 0xfff8 );
#else
      synth[i] = ( Word16 )( synth_speech[i]);
#endif
   }


   return;
}


/*
 * Decoder_amr_exit
 *
 *
 * Parameters:
 *    state                I: state structure
 *
 * Function:
 *    The memory used for state memory is freed
 *
 * Returns:
 *    Void
 */
static void Decoder_amr_exit( Decoder_amrState **state )
{
   if ( state == NULL || *state == NULL )
      return;
   free( ( *state )->lsfState );
   free( ( *state )->ec_gain_p_st );
   free( ( *state )->ec_gain_c_st );
   free( ( *state )->pred_state );
   free( ( *state )->background_state );
   free( ( *state )->ph_disp_st );
   free( ( *state )->Cb_gain_averState );
   free( ( *state )->lsp_avg_st );
   free( ( *state )->dtxDecoderState );

   /* deallocate memory */
   free( *state );
   *state = NULL;
   return;
}


/*
 * Post_Filter_exit
 *
 *
 * Parameters:
 *    state                I: state structure
 *
 * Function:
 *    The memory used for state memory is freed
 *
 * Returns:
 *    Void
 */
static void Post_Filter_exit( Post_FilterState **state )
{
   if ( state == NULL || *state == NULL )
      return;
   free( ( *state )->agc_state );

   /* deallocate memory */
   free( *state );
   *state = NULL;
   return;
}


/*
 * Post_Process_reset
 *
 *
 * Parameters:
 *    state             B: state structure
 *
 * Function:
 *    Resets state memory
 *
 * Returns:
 *    -1 failure
 */
static int Post_Process_reset( Post_ProcessState *state )
{
   if ( ( Post_ProcessState * )state == NULL ) {
      //fprintf( stderr, "Post_Process_reset: invalid parameter\n" );
      return-1;
   }
   state->y2_hi = 0;
   state->y2_lo = 0;
   state->y1_hi = 0;
   state->y1_lo = 0;
   state->x0 = 0;
   state->x1 = 0;
   return 0;
}


/*
 * Post_Process_exit
 *
 *
 * Parameters:
 *    state                I: state structure
 *
 * Function:
 *    The memory used for state memory is freed
 *
 * Returns:
 *    Void
 */
static void Post_Process_exit( Post_ProcessState **state )
{
   if ( state == NULL || *state == NULL )
      return;

   /* deallocate memory */
   free( *state );
   *state = NULL;
   return;
}


/*
 * Decoder_amr_init
 *
 *
 * Parameters:
 *    state             O: state structure
 *
 * Function:
 *    Allocates state memory and initializes state memory
 *
 * Returns:
 *    success = 0
 */
static int Decoder_amr_init( Decoder_amrState **state )
{
   Decoder_amrState * s;

   if ( ( Decoder_amrState * )state == NULL ) {
      //fprintf( stderr, "Decoder_amr_init: invalid parameter\n" );
      return-1;
   }
   *state = NULL;

   /* allocate memory */
   if ( ( s = ( Decoder_amrState * ) malloc( sizeof( Decoder_amrState ) ) ) ==
         NULL ) {
      //fprintf( stderr, "Decoder_amr_init: can not malloc state structure\n" );
      return-1;
   }

   /* DPlsf_init */
   /* allocate memory */
   if ( ( s->lsfState = ( D_plsfState * ) malloc( sizeof( D_plsfState ) ) ) ==
         NULL ) {
      //fprintf( stderr, "DPlsf_init: can not malloc state structure\n" );
      return-1;
   }

   /* ecGainPitchInit */
   /* allocate memory */
   if ( ( s->ec_gain_p_st = ( ec_gain_pitchState * ) malloc( sizeof(
         ec_gain_pitchState ) ) ) == NULL ) {
      //fprintf( stderr, "ecGainPitchInit: can not malloc state structure\n" );
      return-1;
   }

   /* ecGainCodeInit */
   /* allocate memory */
   if ( ( s->ec_gain_c_st = ( ec_gain_codeState * ) malloc( sizeof(
         ec_gain_codeState ) ) ) == NULL ) {
      //fprintf( stderr, "ecGainCodeInit: can not malloc state structure\n" );
      return-1;
   }

   /* gcPredInit */
   /* allocate memory */
   if ( ( s->pred_state = ( gc_predState * ) malloc( sizeof( gc_predState ) ) )
         == NULL ) {
      //fprintf( stderr, "gcPredInit: can not malloc state structure\n" );
      return-1;
   }

   /* Cb_gain_averageInit */
   /* allocate memory */
   if ( ( s->Cb_gain_averState = ( Cb_gain_averageState * ) malloc( sizeof(
         Cb_gain_averageState ) ) ) == NULL ) {
      //fprintf( stderr, "Cb_gain_averageInit: can not malloc state structure\n" ) ;
      return-1;
   }
   memset( s->Cb_gain_averState->cbGainHistory, 0, L_CBGAINHIST <<2 );

   /* Initialize hangover handling */
   s->Cb_gain_averState->hangVar = 0;
   s->Cb_gain_averState->hangCount = 0;

   /* lsp_avgInit */
   /* allocate memory */
   if ( ( s->lsp_avg_st = ( lsp_avgState * ) malloc( sizeof( lsp_avgState ) ) )
         == NULL ) {
      //fprintf( stderr, "lsp_avgInit: can not malloc state structure\n" );
      return-1;
   }

   /* Bgn_scdInit */
   /* allocate memory */
   if ( ( s->background_state = ( Bgn_scdState * ) malloc( sizeof( Bgn_scdState
         ) ) ) == NULL ) {
      //fprintf( stderr, "Bgn_scdInit: can not malloc state structure\n" );
      return-1;
   }

   /* phDispInit */
   /* allocate memory */
   if ( ( s->ph_disp_st = ( ph_dispState * ) malloc( sizeof( ph_dispState ) ) )
         == NULL ) {
      //fprintf( stderr, "phDispInit: can not malloc state structure\n" );
      return-1;
   }

   /* dtxDecInit */
   /* allocate memory */
   if ( ( s->dtxDecoderState = ( dtx_decState * ) malloc( sizeof( dtx_decState )
         ) ) == NULL ) {
      //fprintf( stderr, "dtxDecInit: can not malloc state structure\n" );
      return-1;
   }
   Decoder_amr_reset( s, 0 );
   *state = s;
   return 0;
}


/*
 * Post_Filter_reset
 *
 *
 * Parameters:
 *    state             B: state structure
 *
 * Function:
 *    Resets state memory
 *
 * Returns:
 *    -1 failure
 */
static int Post_Filter_reset( Post_FilterState *state )
{
   if ( ( Post_FilterState * )state == NULL ) {
      //fprintf( stderr, "Post_Filter_reset: invalid parameter\n" );
      return-1;
   }
   state->preemph_state_mem_pre = 0;
   state->agc_state->past_gain = 4096;
   memset( state->mem_syn_pst, 0, M <<2 );
   memset( state->res2, 0, L_SUBFR <<2 );
   memset( state->synth_buf, 0, ( L_FRAME + M )<<2 );
   return 0;
}


/*
 * Post_Filter_init
 *
 *
 * Parameters:
 *    state             O: state structure
 *
 * Function:
 *    Allocates state memory and initializes state memory
 *
 * Returns:
 *    success = 0
 */
static int Post_Filter_init( Post_FilterState **state )
{
   Post_FilterState * s;

   if ( ( Post_FilterState * )state == NULL ) {
      //fprintf( stderr, "F057:invalid parameter\n" );
      return-1;
   }
   *state = NULL;

   /* allocate memory */
   if ( ( s = ( Post_FilterState * ) malloc( sizeof( Post_FilterState ) ) ) ==
         NULL ) {
      //fprintf( stderr, "F057:can not malloc filter structure\n" );
      return-1;
   }
   s->agc_state = NULL;

   /* allocate memory */
   if ( ( s->agc_state = ( agcState * ) malloc( sizeof( agcState ) ) ) == NULL )
   {
      //fprintf( stderr, "agcInit: can not malloc state structure\n" );
      return-1;
   }
   Post_Filter_reset( s );
   *state = s;
   return 0;
}


/*
 * Post_Process_init
 *
 *
 * Parameters:
 *    state             O: state structure
 *
 * Function:
 *    Allocates state memory and initializes state memory
 *
 * Returns:
 *    success = 0
 */
static int Post_Process_init( Post_ProcessState **state )
{
   Post_ProcessState * s;

   if ( ( Post_ProcessState * )state == NULL ) {
      //fprintf( stderr, "Post_Process_init: invalid parameter\n" );
      return-1;
   }
   *state = NULL;

   /* allocate memory */
   if ( ( s = ( Post_ProcessState * ) malloc( sizeof( Post_ProcessState ) ) ) ==
         NULL ) {
      //fprintf( stderr, "Post_Process_init: can not malloc state structure\n" );
      return-1;
   }
   Post_Process_reset( s );
   *state = s;
   return 0;
}


/*
 * Speech_Decode_Frame_exit
 *
 *
 * Parameters:
 *    state                I: state structure
 *
 * Function:
 *    The memory used for state memory is freed
 *
 * Returns:
 *    Void
 */
void Speech_Decode_Frame_exit( void **st )
{
   if ( (( Speech_Decode_FrameState * )( st )) == NULL )
      return;
   Decoder_amr_exit( &( ( ( Speech_Decode_FrameState * ) st )->decoder_amrState
         ) );
   Post_Filter_exit( &( ( ( Speech_Decode_FrameState * ) st )->post_state ) );
   Post_Process_exit( &( ( ( Speech_Decode_FrameState * ) st )->postHP_state ) )
   ;

   /* deallocate memory */
   free( (( Speech_Decode_FrameState * )st) );
   return;
}


/*
 * Speech_Decode_Frame_reset
 *
 *
 * Parameters:
 *    state             B: state structure
 *
 * Function:
 *    Resets state memory
 *
 * Returns:
 *    -1 = failure
 */
int Speech_Decode_Frame_reset( void **st )
{
   Speech_Decode_FrameState * state;

   if ( st == NULL || *st == NULL )
      return (-1);
   state = ( Speech_Decode_FrameState * )st;
   Decoder_amr_reset( state->decoder_amrState, ( enum Mode ) 0 );
   Post_Filter_reset( state->post_state );
   Post_Process_reset( state->postHP_state );
   return 0;
}


/*
 * Speech_Decode_Frame_init
 *
 *
 * Parameters:
 *    state             O: state structure
 *
 * Function:
 *    Allocates state memory and initializes state memory
 *
 * Returns:
 *    success = 0
 */
void * Speech_Decode_Frame_init( )
{
   Speech_Decode_FrameState * s;

   /* allocate memory */
   if ( ( s = ( Speech_Decode_FrameState * ) malloc( sizeof(
         Speech_Decode_FrameState ) ) ) == NULL ) {
      //fprintf( stderr, "Speech_Decode_Frame_init: can not malloc state structure\n" );
      return NULL;
   }
   s->decoder_amrState = NULL;
   s->post_state = NULL;
   s->postHP_state = NULL;

   if ( Decoder_amr_init( &s->decoder_amrState ) || Post_Filter_init( &s->
         post_state ) || Post_Process_init( &s->postHP_state ) ) {
      Speech_Decode_Frame_exit( ( void ** )( &s ) );
      return NULL;
   }
   return s;
}
