view libtwamr/dec_amr.c @ 478:936a08cc73ce

doc/AMR-library-API: describe the decoder
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 19 May 2024 21:32:31 +0000
parents 7bef001cd8b8
children
line wrap: on
line source

/*************************************************************************
*
*      GSM AMR-NB speech codec   R98   Version 7.6.0   December 12, 2001
*                                R99   Version 3.3.0                
*                                REL-4 Version 4.1.0                
*
*****************************************************************************
*
*      File             : dec_amr.c
*      Purpose          : Decoding of one speech frame using given codec mode
*
*****************************************************************************
*/

/*
*****************************************************************************
*                         MODULE INCLUDE FILE AND VERSION ID
*****************************************************************************
*/
#include "namespace.h"
#include "dec_amr.h"

#include "typedef.h"
#include "basic_op.h"
#include "no_count.h"
#include "cnst.h"
#include "memops.h"
#include "syn_filt.h"
#include "d_plsf.h"
#include "agc.h"
#include "int_lpc.h"
#include "dec_gain.h"
#include "dec_lag3.h"
#include "dec_lag6.h"
#include "d2_9pf.h"
#include "d2_11pf.h"
#include "d3_14pf.h"
#include "d4_17pf.h"
#include "d8_31pf.h"
#include "d1035pf.h"
#include "pred_lt.h"
#include "d_gain_p.h"
#include "d_gain_c.h"
#include "dec_gain.h"
#include "ec_gains.h"
#include "ph_disp.h"
#include "c_g_aver.h"
#include "int_lsf.h"
#include "lsp_lsf.h"
#include "lsp_avg.h"
#include "bgnscd.h"
#include "ex_ctrl.h"
#include "sqrt_l.h"

#include "lsp_tab.h"
#include "bitno.h"
#include "b_cn_cod.h"

/*
*****************************************************************************
*                         LOCAL VARIABLES AND TABLES
*****************************************************************************
*/
/*-----------------------------------------------------------------*
 *   Decoder constant parameters (defined in "cnst.h")             *
 *-----------------------------------------------------------------*
 *   L_FRAME       : Frame size.                                   *
 *   L_FRAME_BY2   : Half the frame size.                          *
 *   L_SUBFR       : Sub-frame size.                               *
 *   M             : LPC order.                                    *
 *   MP1           : LPC order+1                                   *
 *   PIT_MIN       : Minimum pitch lag.                            *
 *   PIT_MIN_MR122 : Minimum pitch lag for the MR122 mode.         *
 *   PIT_MAX       : Maximum pitch lag.                            *
 *   L_INTERPOL    : Length of filter for interpolation            *
 *   PRM_SIZE      : size of vector containing analysis parameters *
 *-----------------------------------------------------------------*/

/*
*****************************************************************************
*                         PUBLIC PROGRAM CODE
*****************************************************************************
*/

/*
**************************************************************************
*
*  Function    : Decoder_amr_reset
*  Purpose     : Resets state memory
*
**************************************************************************
*/
void Decoder_amr_reset (Decoder_amrState *state, Flag dtx_partial_reset)
{
  Word16 i;

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

  /* Static vectors to zero */
  Set_zero (state->old_exc, PIT_MAX + L_INTERPOL);

  if (!dtx_partial_reset)
     Set_zero (state->mem_syn, M);

  /* initialize pitch sharpening */
  state->sharp = SHARPMIN;
  state->old_T0 = 40;
     
  /* Initialize state->lsp_old [] */ 

  if (!dtx_partial_reset) {
      Copy(lsp_init_data, &state->lsp_old[0], M);
  }

  /* 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 (!dtx_partial_reset) {
      for (i=0;i<9;i++)
          state->excEnergyHist[i] = 0;
  }
  
  for (i = 0; i < 9; i++)
     state->ltpGainHistory[i] = 0;

  Cb_gain_average_reset(&state->Cb_gain_averState);
  if (!dtx_partial_reset)
     lsp_avg_reset(&state->lsp_avg_st);
  D_plsf_reset(&state->lsfState);
  ec_gain_pitch_reset(&state->ec_gain_p_st);
  ec_gain_code_reset(&state->ec_gain_c_st);

  if (!dtx_partial_reset)
     gc_pred_reset(&state->pred_state);

  Bgn_scd_reset(&state->background_state);
  state->nodataSeed = 21845;
  ph_disp_reset(&state->ph_disp_st);
  if (!dtx_partial_reset)
     dtx_dec_reset(&state->dtxDecoderState);
}

/*
**************************************************************************
*
*  Function    : Decoder_amr
*  Purpose     : Speech decoder routine.
*
**************************************************************************
*/
int Decoder_amr (
    Decoder_amrState *st,      /* i/o : State variables                   */
    enum Mode mode,            /* i   : AMR mode                          */
    Word16 parm[],             /* i   : vector of synthesis parameters
                                        (PRM_SIZE)                        */
    enum RXFrameType frame_type, /* i   : received frame type             */
    Word16 synth[],            /* o   : synthesis speech (L_FRAME)        */
    Word16 A_t[]               /* o   : decoded LP filter in 4 subframes
                                        (AZ_SIZE)                         */
)
{
    /* LPC coefficients */
   
    Word16 *Az;                /* Pointer on A_t */
    
    /* LSPs */

    Word16 lsp_new[M];
    Word16 lsp_mid[M];

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

    /* Algebraic codevector */

    Word16 code[L_SUBFR];

    /* excitation */

    Word16 excp[L_SUBFR];
    Word16 exc_enhanced[L_SUBFR];

    /* Scalars */

    Word16 i, i_subfr;
    Word16 T0, T0_frac, index, index_mr475 = 0;
    Word16 gain_pit, gain_code, gain_code_mix, pit_sharp, pit_flag, pitch_fac;
    Word16 t0_min, t0_max;
    Word16 delta_frc_low, delta_frc_range;
    Word16 tmp_shift;
    Word16 temp;
    Word32 L_temp;
    Word16 flag4;
    Word16 carefulFlag;
    Word16 excEnergy;
    Word16 subfrNr; 
    Word16 evenSubfr = 0;

    Word16 bfi = 0;   /* bad frame indication flag                          */
    Word16 pdfi = 0;  /* 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 (sub(newDTXState, SPEECH) != 0 )
    {
       Decoder_amr_reset (st, 1);

       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, M);
       lsp_avg(&st->lsp_avg_st, st->lsfState.past_lsf_q);
       goto the_end;
    }

    /* SPEECH action state machine  */
    if ((sub(frame_type, RX_SPEECH_BAD) == 0) || 
        (sub(frame_type, RX_NO_DATA) == 0) ||
        (sub(frame_type, RX_ONSET) == 0)) 
    {
       bfi = 1;
       if ((sub(frame_type, RX_NO_DATA) == 0) ||
           (sub(frame_type, RX_ONSET) == 0))
       {
	  build_CN_param(&st->nodataSeed,
			 prmno[mode],
			 bitno[mode],
			 parm);
       }       
    }
    else if (sub(frame_type, RX_SPEECH_DEGRADED) == 0)
    {
       pdfi = 1;
    }

    if (bfi != 0)
    {
        st->state = add (st->state, 1);
    }
    else if (sub (st->state, 6) == 0)
    {
        st->state = 5;                                   move16 ();
    }
    else
    {
        st->state = 0;                                   move16 ();
    }

    if (sub (st->state, 6) > 0)
    {
        st->state = 6;                                   move16 ();
    }

    /* 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 (sub(st->dtxDecoderState.dtxGlobalState, DTX) == 0)
    {
       st->state = 5;
       st->prev_bf = 0;
    }
    else if (test (), sub(st->dtxDecoderState.dtxGlobalState, DTX_MUTE) == 0)
    {
       st->state = 5;
       st->prev_bf = 1;
    }
    
    /* save old LSFs for CB gain smoothing */
    Copy (st->lsfState.past_lsf_q, prev_lsf, M);

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

       /* Advance synthesis parameters pointer */
       parm += 3;                  move16 ();
       
       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;                  move16 ();
       
       Int_lpc_1and3(st->lsp_old, lsp_mid, lsp_new, A_t);
    }
       
    /* update the LSPs for the next frame */
    for (i = 0; i < M; i++)
    {
       st->lsp_old[i] = lsp_new[i];        move16 (); 
    }

   /*------------------------------------------------------------------------*
    *          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;                                                       move16 (); 
    
    evenSubfr = 0;                                                  move16();
    subfrNr = -1;                                                   move16();
    for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)
    {
       subfrNr = add(subfrNr, 1);
       evenSubfr = sub(1, evenSubfr);

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

       test();
       if (sub (i_subfr, L_FRAME_BY2) == 0)
       {
          test(); test();
          if (sub(mode, MR475) != 0 && sub(mode, MR515) != 0) 
          {
             pit_flag = 0;             move16 ();
          }
       }
       
       /* pitch index */
       index = *parm++;                move16 ();

       /*-------------------------------------------------------*
        * - decode pitch lag and find adaptive codebook vector. *
        *-------------------------------------------------------*/
       
       test ();
       if (sub(mode, MR122) != 0)
       {
          /* flag4 indicates encoding with 4 bit resolution;     */
          /* this is needed for mode MR475, MR515, MR59 and MR67 */
          
          flag4 = 0;                                 move16 ();
          test (); test (); test (); test ();        
          if ((sub (mode, MR475) == 0) ||
              (sub (mode, MR515) == 0) ||
              (sub (mode, MR59) == 0) ||
              (sub (mode, MR67) == 0) ) {
             flag4 = 1;                              move16 ();
          }
          
          /*-------------------------------------------------------*
           * - get ranges for the t0_min and t0_max                *
           * - only needed in delta decoding                       *
           *-------------------------------------------------------*/

          delta_frc_low = 5;                      move16();
          delta_frc_range = 9;                    move16();

          test ();
          if ( sub(mode, MR795) == 0 )
          {
             delta_frc_low = 10;                  move16();
             delta_frc_range = 19;                move16();
          }
             
          t0_min = sub(st->old_T0, delta_frc_low);
          test ();
          if (sub(t0_min, PIT_MIN) < 0)
          {
             t0_min = PIT_MIN;                    move16();
          }
          t0_max = add(t0_min, delta_frc_range);
          test ();
          if (sub(t0_max, PIT_MAX) > 0)
          {
             t0_max = PIT_MAX;                    move16();
             t0_min = sub(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;                        move16 ();

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

             test (); test (); test (); test (); test ();
             if ( st->inBackgroundNoise != 0 && 
                  sub(st->voicedHangover, 4) > 0 &&
                  ((sub(mode, MR475) == 0 ) ||
                   (sub(mode, MR515) == 0 ) ||
                   (sub(mode, MR59) == 0) )
                  )
             {
                T0 = st->T0_lagBuff;                  move16 ();
             }
          }

          Pred_lt_3or6 (st->exc, T0, T0_frac, L_SUBFR, 1);
       }
       else
       {
          Dec_lag6 (index, PIT_MIN_MR122,
                    PIT_MAX, pit_flag, &T0, &T0_frac);

          test (); test (); test ();
          if ( bfi == 0 && (pit_flag == 0 || sub (index, 61) < 0))
          {
          }                
          else
          {
             st->T0_lagBuff = T0;                 move16 ();
             T0 = st->old_T0;                     move16 (); 
             T0_frac = 0;                         move16 (); 
          }

          Pred_lt_3or6 (st->exc, T0, T0_frac, L_SUBFR, 0);
       }
       
       /*-------------------------------------------------------*
        * - (MR122 only: Decode pitch gain.)                    *
        * - Decode innovative codebook.                         *
        * - set pitch sharpening factor                         *
        *-------------------------------------------------------*/

        if (sub (mode, MR475) == 0 || sub (mode, MR515) == 0)
        {   /* MR475, MR515 */
           index = *parm++;        /* index of position */ move16 ();
           i = *parm++;            /* signs             */ move16 ();

           decode_2i40_9bits (subfrNr, i, index, code);

           pit_sharp = shl (st->sharp, 1);
        }
        else if (sub (mode, MR59) == 0)
        {   /* MR59 */
           test (); 
           index = *parm++;        /* index of position */ move16 ();
           i = *parm++;            /* signs             */ move16 ();

           decode_2i40_11bits (i, index, code);

           pit_sharp = shl (st->sharp, 1);
        }
        else if (sub (mode, MR67) == 0)
        {   /* MR67 */
           test (); test ();
           index = *parm++;        /* index of position */ move16 ();
           i = *parm++;            /* signs             */ move16 ();
           
           decode_3i40_14bits (i, index, code);
            
           pit_sharp = shl (st->sharp, 1);
        }
        else if (sub (mode, MR795) <= 0)
        {   /* MR74, MR795 */
           test (); test (); test ();
           index = *parm++;        /* index of position */ move16 ();
           i = *parm++;            /* signs             */ move16 ();
           
           decode_4i40_17bits (i, index, code);
           
           pit_sharp = shl (st->sharp, 1);
        }
        else if (sub (mode, MR102) == 0)
        {  /* MR102 */
           test (); test (); test ();

           dec_8i40_31bits (parm, code);
           parm += 7;                                       move16 (); 

           pit_sharp = shl (st->sharp, 1);
        }
        else
        {  /* MR122 */
           test (); test (); test ();
           index = *parm++;                                move16 ();
           test();
           if (bfi != 0)
           {
              ec_gain_pitch (&st->ec_gain_p_st, st->state, &gain_pit);
           }
           else
           {
              gain_pit = d_gain_pitch (mode, index);        move16 ();
           }
           ec_gain_pitch_update (&st->ec_gain_p_st, bfi, st->prev_bf,
                                 &gain_pit);

           dec_10i40_35bits (parm, code);
           parm += 10;                                     move16 (); 

           /* pit_sharp = gain_pit;                   */
           /* if (pit_sharp > 1.0) pit_sharp = 1.0;   */
           
           pit_sharp = shl (gain_pit, 1);
        }
        
        /*-------------------------------------------------------*
         * - Add the pitch contribution to code[].               *
         *-------------------------------------------------------*/
        for (i = T0; i < L_SUBFR; i++)
        {
           temp = mult (code[i - T0], pit_sharp);
           code[i] = add (code[i], temp);
           move16 (); 
        }
        
        /*------------------------------------------------------------*
         * - Decode codebook gain (MR122) or both pitch               *
         *   gain and codebook gain (all others)                      *
         * - Update pitch sharpening "sharp" with quantized gain_pit  *
         *------------------------------------------------------------*/

        if (test(), sub (mode, MR475) == 0)
        {
           /* read and decode pitch and code gain */
           test();      
           if (evenSubfr != 0) 
           {
              index_mr475 = *parm++;        move16 (); /* index of gain(s) */
           }

           test();
           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;                                move16 ();
           test ();
           if (sub (pit_sharp, SHARPMAX) > 0) 
           {
               pit_sharp = SHARPMAX;                            move16 ();
           }

        }
        else if (test(), test(), (sub (mode, MR74) <= 0) || 
                 (sub (mode, MR102) == 0))
        {
            /* read and decode pitch and code gain */
            index = *parm++;                move16 (); /* index of gain(s) */
           
            test();
            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;                               move16 ();
            test ();
            if (sub (pit_sharp, SHARPMAX) > 0) 
            {
               pit_sharp = SHARPMAX;                           move16 ();
            }

            if (sub (mode, MR102) == 0)
            {
               if (sub (st->old_T0, add(L_SUBFR, 5)) > 0)
               {
                  pit_sharp = shr(pit_sharp, 2);
               }
            }
        }
        else
        {
           /* read and decode pitch gain */
           index = *parm++;                move16 (); /* index of gain(s) */
           
           test (); 
           if (sub (mode, MR795) == 0)
           {
              /* decode pitch gain */
              test();
              if (bfi != 0)
              {
                 ec_gain_pitch (&st->ec_gain_p_st, st->state, &gain_pit);
              }
              else
              {
                 gain_pit = d_gain_pitch (mode, index);       move16 ();
              }
              ec_gain_pitch_update (&st->ec_gain_p_st, bfi, st->prev_bf,
                                    &gain_pit);
              
              /* read and decode code gain */
              index = *parm++;                                move16 ();
              test();
              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;                               move16 ();
              test ();
              if (sub (pit_sharp, SHARPMAX) > 0)
              {
                 pit_sharp = SHARPMAX;                           move16 ();
              }
           }
           else 
           { /* MR122 */
              test();
              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;                                move16 ();
           }
        }
        
        /* 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 */
        test(); test();
        if (sub(mode, MR475) != 0 || evenSubfr == 0)
        {
            st->sharp = gain_pit;                                   move16 (); 
            test ();
            if (sub (st->sharp, SHARPMAX) > 0)
            {
                st->sharp = SHARPMAX;                                move16 ();
            }
        }

        pit_sharp = shl (pit_sharp, 1);
        test ();
        if (sub (pit_sharp, 16384) > 0)
        {
           for (i = 0; i < L_SUBFR; i++)
            {
               temp = mult (st->exc[i], pit_sharp);
               L_temp = L_mult (temp, gain_pit);
               test ();
               if (sub(mode, MR122)==0)
               {
                  L_temp = L_shr (L_temp, 1);
               }
               excp[i] = round (L_temp);                        move16 (); 
            }
        }
        
        /*-------------------------------------------------------*
         * - Store list of LTP gains needed in the source        *
         *   characteristic detector (SCD)                       *
         *-------------------------------------------------------*/
        test ();
        if ( bfi == 0 )
        {
           for (i = 0; i < 8; i++)
           {
              st->ltpGainHistory[i] = st->ltpGainHistory[i+1];     move16 ();
           }
           st->ltpGainHistory[8] = gain_pit;                       move16 ();
        }

        /*-------------------------------------------------------*
         * - Limit gain_pit if in background noise and BFI       *
         *   for MR475, MR515, MR59                              *
         *-------------------------------------------------------*/

        test (); test (); test (); test (); test (); test ();
        if ( (st->prev_bf != 0 || bfi != 0) && st->inBackgroundNoise != 0 &&
             ((sub(mode, MR475) == 0) ||
              (sub(mode, MR515) == 0) ||
              (sub(mode, MR59) == 0))
             )
        {
           test ();
           if ( sub (gain_pit, 12288) > 0)    /* if (gain_pit > 0.75) in Q14*/
              gain_pit = add( shr( sub(gain_pit, 12288), 1 ), 12288 );
              /* gain_pit = (gain_pit-0.75)/2.0 + 0.75; */

           test ();
           if ( sub (gain_pit, 14745) > 0)    /* if (gain_pit > 0.90) in Q14*/
           {
              gain_pit = 14745;                                 move16 ();
           }
        }

        /*-------------------------------------------------------*
         *  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);         move16 ();
        
        /* make sure that MR74, MR795, MR122 have original code_gain*/
        test();
        if ((sub(mode, MR67) > 0) && (sub(mode, MR102) != 0) ) 
           /* MR74, MR795, MR122 */
        {
           gain_code_mix = gain_code;                 move16 ();
        }
        
        /*-------------------------------------------------------*
         * - Find the total excitation.                          *
         * - Find synthesis speech corresponding to st->exc[].   *
         *-------------------------------------------------------*/
        test ();
        if (sub(mode, MR102) <= 0) /* MR475, MR515, MR59, MR67, MR74, MR795, MR102*/
        {
           pitch_fac = gain_pit;                                move16 ();
           tmp_shift = 1;                                       move16 ();
        }
        else       /* MR122 */
        {
           pitch_fac = shr (gain_pit, 1);                       move16 ();
           tmp_shift = 2;                                       move16 ();
        }

        /* copy unscaled LTP excitation to exc_enhanced (used in phase
         * dispersion below) and compute total excitation for LTP feedback
         */
        for (i = 0; i < L_SUBFR; i++)
        {
           exc_enhanced[i] = st->exc[i];                        move16 ();

           /* st->exc[i] = gain_pit*st->exc[i] + gain_code*code[i]; */
           L_temp = L_mult (st->exc[i], pitch_fac);
                                                      /* 12.2: Q0 * Q13 */
                                                      /*  7.4: Q0 * Q14 */
           L_temp = L_mac (L_temp, code[i], gain_code);
                                                      /* 12.2: Q12 * Q1 */
                                                      /*  7.4: Q13 * Q1 */
           L_temp = L_shl (L_temp, tmp_shift);                   /* Q16 */
           st->exc[i] = round (L_temp);                         move16 (); 
        }
        
        /*-------------------------------------------------------*
         * - Adaptive phase dispersion                           *
         *-------------------------------------------------------*/
        ph_disp_release(&st->ph_disp_st); /* free phase dispersion adaption */

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

        /* 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.      *
         *-------------------------------------------------------*/

        L_temp = 0;                                   move32 ();
        for (i = 0; i < L_SUBFR; i++)
        {
            L_temp = L_mac (L_temp, exc_enhanced[i], exc_enhanced[i] );
        }

        L_temp = L_shr (L_temp, 1);     /* excEnergy = sqrt(L_temp) in Q0 */
        L_temp = sqrt_l_exp(L_temp, &temp); move32 (); /* function result */
        L_temp = L_shr(L_temp, add( shr(temp, 1), 15));
        L_temp = L_shr(L_temp, 2);       /* To cope with 16-bit and  */
        excEnergy = extract_l(L_temp);   /* scaling in ex_ctrl()     */

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

           Ex_ctrl(exc_enhanced,     
                   excEnergy,
                   st->excEnergyHist,
                   st->voicedHangover,
                   st->prev_bf,
                   carefulFlag);
        }

        test (); test (); test (); test ();
        if ( st->inBackgroundNoise != 0 &&
             ( bfi != 0 || st->prev_bf != 0 ) &&
             sub(st->state, 4) < 0 )
        { 
           ; /* do nothing! */
        }
        else
        {
           /* Update energy history for all modes */
           for (i = 0; i < 8; i++)
           {
              st->excEnergyHist[i] = st->excEnergyHist[i+1]; move16 ();
           }
           st->excEnergyHist[8] = excEnergy;   move16 ();
        }
        /*-------------------------------------------------------*
         * Excitation control module end.                        *
         *-------------------------------------------------------*/
        
        test (); 
        if (sub (pit_sharp, 16384) > 0)
        {
           for (i = 0; i < L_SUBFR; i++)
           {
              excp[i] = add (excp[i], exc_enhanced[i]);              
              move16 (); 
           }
           agc2 (exc_enhanced, excp, L_SUBFR);
           Overflow = 0;                 move16 ();
           Syn_filt (Az, excp, &synth[i_subfr], L_SUBFR,
                     st->mem_syn, 0);
        }
        else
        {
           Overflow = 0;                 move16 ();
           Syn_filt (Az, exc_enhanced, &synth[i_subfr], L_SUBFR,
                     st->mem_syn, 0);
        }

        test ();
        if (Overflow != 0)    /* Test for overflow */
        {
           for (i = 0; i < PIT_MAX + L_INTERPOL + L_SUBFR; i++)
           {
              st->old_exc[i] = shr(st->old_exc[i], 2);       move16 ();
           }
           for (i = 0; i < L_SUBFR; i++)
           {
              exc_enhanced[i] = shr(exc_enhanced[i], 2);     move16 ();
           }
           Syn_filt(Az, exc_enhanced, &synth[i_subfr], L_SUBFR, st->mem_syn, 1);
        }
        else
        {
           Copy(&synth[i_subfr+L_SUBFR-M], st->mem_syn, M);
        }
        
        /*--------------------------------------------------*
         * Update signal for next frame.                    *
         * -> shift to the left by L_SUBFR  st->exc[]       *
         *--------------------------------------------------*/
        
        Copy (&st->old_exc[L_SUBFR], &st->old_exc[0], PIT_MAX + L_INTERPOL);

        /* interpolated LPC parameters for next subframe */
        Az += MP1;                      move16 ();
        
        /* store T0 for next subframe */ 
        st->old_T0 = T0;                move16 ();
    }
    
    /*-------------------------------------------------------*
     * 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;                  move16 (); 
    st->prev_pdf = pdfi;                move16 (); 
    
    /*--------------------------------------------------*
     * Calculate the LSF averages on the eight          *
     * previous frames                                  *
     *--------------------------------------------------*/
    
    lsp_avg(&st->lsp_avg_st, st->lsfState.past_lsf_q);

the_end:
    st->dtxDecoderState.dtxGlobalState = newDTXState;

    return 0;
}