changeset 601:c7c03231002d

libgsmhr1: integrate main body of speech decoder
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 04 Dec 2025 12:49:19 +0000
parents 5a7d04bf26f5
children 72cdae602d6e
files libgsmhr1/Makefile libgsmhr1/dec_func.c libgsmhr1/dec_func.h libgsmhr1/dec_state.h libgsmhr1/dtx_dec.c libgsmhr1/dtx_dec.h libgsmhr1/sp_dec.c
diffstat 7 files changed, 182 insertions(+), 3900 deletions(-) [+]
line wrap: on
line diff
--- a/libgsmhr1/Makefile	Thu Dec 04 10:24:06 2025 +0000
+++ b/libgsmhr1/Makefile	Thu Dec 04 12:49:19 2025 +0000
@@ -2,7 +2,8 @@
 	enc_out_order.o err_conc.o mathdp31.o mathhalf.o pack_frame.o \
 	paramval_cod.o paramval_common.o paramval_dec.o rtp_in.o \
 	rtp_in_direct.o rxfe.o rxfe_create.o sid_cw_params.o sid_detect.o \
-	sid_reset.o sp_rom.o tfo.o twts002_in.o twts002_out.o unpack_frame.o
+	sid_reset.o sp_dec.o sp_rom.o tfo.o twts002_in.o twts002_out.o \
+	unpack_frame.o
 HDRS=	dec_func.h dec_state.h dtx_const.h dtx_dec.h dtx_rxfe.h enc_out_order.h\
 	err_conc.h mathdp31.h mathhalf.h namespace.h rxfe.h sp_rom.h tw_gsmhr.h\
 	typedefs.h
--- a/libgsmhr1/dec_func.c	Thu Dec 04 10:24:06 2025 +0000
+++ b/libgsmhr1/dec_func.c	Thu Dec 04 12:49:19 2025 +0000
@@ -4305,7 +4305,7 @@
  *
  *************************************************************************/
 
-void   v_con(Shortword pswBVects[], Shortword pswOutVect[],
+void   v_con(const Shortword pswBVects[], Shortword pswOutVect[],
                     Shortword pswBitArray[], short int siNumBVctrs)
 {
 
--- a/libgsmhr1/dec_func.h	Thu Dec 04 10:24:06 2025 +0000
+++ b/libgsmhr1/dec_func.h	Thu Dec 04 12:49:19 2025 +0000
@@ -100,7 +100,7 @@
 
   Shortword sqroot(Longword L_SqrtIn);
 
-  void   v_con(Shortword pswBVects[], Shortword pswOutVect[],
+  void   v_con(const Shortword pswBVects[], Shortword pswOutVect[],
                       Shortword pswBitArray[], short int siNumBVctrs);
 
 #endif
--- a/libgsmhr1/dec_state.h	Thu Dec 04 10:24:06 2025 +0000
+++ b/libgsmhr1/dec_state.h	Thu Dec 04 12:49:19 2025 +0000
@@ -36,7 +36,6 @@
 	/* comfort noise interpolation */
 	Shortword swRxDTXState;
 	Shortword swR0OldCN;
-	Shortword swR0NewCN;
 	Longword pL_OldCorrSeq[NP + 1];
 	Longword pL_NewCorrSeq[NP + 1];
 	Longword pL_CorrSeq[NP + 1];
--- a/libgsmhr1/dtx_dec.c	Thu Dec 04 10:24:06 2025 +0000
+++ b/libgsmhr1/dtx_dec.c	Thu Dec 04 12:49:19 2025 +0000
@@ -54,10 +54,9 @@
  * or CNICONT.
  */
 void Init_CN_interpolation(struct gsmhr_decoder_state *st, Shortword deco_mode,
-			   Shortword new_R0, const Shortword *pswNewKs)
+			   const Shortword *pswNewKs)
 {
 	st->swR0OldCN = st->swOldR0Dec;
-	st->swR0NewCN = new_R0;
 	if (deco_mode == CNIFIRSTSID) {
 		rcToCorrDpL(ASHIFT, ASCALE, st->pswOldFrmKsDec,
 			    st->pL_OldCorrSeq);
@@ -72,10 +71,9 @@
  * This function is a fragment from original rxInterpR0Lpc():
  * interpolate R0 for CN output.
  */
-Shortword CN_Interpolate_R0(struct gsmhr_decoder_state *st)
+Shortword CN_Interpolate_R0(struct gsmhr_decoder_state *st, Shortword new_R0)
 {
-	return linInterpSidShort(st->swR0NewCN, st->swR0OldCN,
-				 st->swRxDTXState);
+	return linInterpSidShort(new_R0, st->swR0OldCN, st->swRxDTXState);
 }
 
 /*
--- a/libgsmhr1/dtx_dec.h	Thu Dec 04 10:24:06 2025 +0000
+++ b/libgsmhr1/dtx_dec.h	Thu Dec 04 12:49:19 2025 +0000
@@ -16,9 +16,9 @@
 			    Shortword swDtxState);
 
 void Init_CN_interpolation(struct gsmhr_decoder_state *st, Shortword deco_mode,
-			   Shortword new_R0, const Shortword *pswNewKs);
+			   const Shortword *pswNewKs);
 
-Shortword CN_Interpolate_R0(struct gsmhr_decoder_state *st);
+Shortword CN_Interpolate_R0(struct gsmhr_decoder_state *st, Shortword new_R0);
 
 void CN_Interpolate_LPC(struct gsmhr_decoder_state *st, Shortword *pswNewKs);
 
--- a/libgsmhr1/sp_dec.c	Thu Dec 04 10:24:06 2025 +0000
+++ b/libgsmhr1/sp_dec.c	Thu Dec 04 12:49:19 2025 +0000
@@ -73,12 +73,20 @@
  |_________________________________________________________________________|
 */
 
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
 #include "typedefs.h"
+#include "tw_gsmhr.h"
+#include "namespace.h"
 #include "mathhalf.h"
+#include "dec_func.h"
+#include "dec_state.h"
+#include "dtx_const.h"
+#include "dtx_dec.h"
+#include "err_conc.h"
+#include "rxfe.h"
 #include "sp_rom.h"
-#include "sp_dec.h"
-#include "err_conc.h"
-#include "dtx.h"
 
 
 /*_________________________________________________________________________
@@ -91,6 +99,9 @@
                          Shortword pswDirectFormCoefIn[],
                          Shortword pswDirectFormCoefOut[]);
 
+static Shortword lagDecode(Shortword swDeltaLag, Shortword *pswLastLag,
+			   Shortword subfrm);
+
   static short aToRc(Shortword swAshift, Shortword pswAin[],
                             Shortword pswRc[]);
 
@@ -98,8 +109,6 @@
                                   struct NormSw snsInSigEnergy,
                                   Shortword swEngyRShft);
 
-  static Shortword lagDecode(Shortword swDeltaLag);
-
   static void lookupVq(Shortword pswVqCodeWds[], Shortword pswRCOut[]);
 
   static void pitchPreFilt(Shortword pswExcite[],
@@ -111,9 +120,11 @@
                                   Shortword pswExciteOut[],
                                   Shortword pswPPreState[]);
 
-  static void spectralPostFilter(Shortword pswSPFIn[],
-                           Shortword pswNumCoef[], Shortword pswDenomCoef[],
-                                        Shortword pswSPFOut[]);
+static void spectralPostFilter(struct gsmhr_decoder_state *st,
+				Shortword swEngyRShift,
+				Shortword pswSPFIn[], Shortword pswNumCoef[],
+				Shortword pswDenomCoef[],
+				Shortword pswSPFOut[]);
 
 /*_________________________________________________________________________
  |                                                                         |
@@ -132,346 +143,13 @@
                                         * codeword */
 #define  MAXBITS      C_BITS_V         /* max number of bits in any VSELP
                                         * codeword */
-#define  LTP_LEN      147              /* 147==0x93 length of LTP history */
 #define  SQRT_ONEHALF 0x5a82           /* the 0.5 ** 0.5 */
 #define  LPC_ROUND    0x00000800L      /* 0x8000 >> ASHIFT */
 #define  AFSHIFT      2                /* number of right shifts to be
                                         * applied to the autocorrelation
                                         * sequence in aFlatRcDp     */
 
-/*_________________________________________________________________________
- |                                                                         |
- |                         State variables (globals)                       |
- |_________________________________________________________________________|
-*/
-
-  Shortword gswPostFiltAgcGain,
-         gpswPostFiltStateNum[NP],
-         gpswPostFiltStateDenom[NP],
-         swPostEmphasisState,
-         pswSynthFiltState[NP],
-         pswOldFrmKsDec[NP],
-         pswOldFrmAsDec[NP],
-         pswOldFrmPFNum[NP],
-         pswOldFrmPFDenom[NP],
-         swOldR0Dec,
-         pswLtpStateBaseDec[LTP_LEN + S_LEN],
-         pswPPreState[LTP_LEN + S_LEN];
-
-
-  Shortword swMuteFlagOld;             /* error concealment */
-
-
- /* DTX state variables */
- /* ------------------- */
-
-  Shortword swRxDTXState = CNINTPER - 1;        /* DTX State at the rx.
-                                                 * Modulo */
-
- /* counter [0,11].             */
-
-  Shortword swDecoMode = SPEECH;
-  Shortword swDtxMuting = 0;
-  Shortword swDtxBfiCnt = 0;
-
-  Shortword swOldR0IndexDec = 0;
-
-  Shortword swRxGsHistPtr = 0;
-  Longword pL_RxGsHist[(OVERHANG - 1) * N_SUB];
-
-
-/*_________________________________________________________________________
- |                                                                         |
- |                               Global Data                               |
- |                     (scope is global to this file)                      |
- |_________________________________________________________________________|
-*/
-
-  Shortword swR0Dec;
-
-  Shortword swVoicingMode,             /* MODE */
-         pswVq[3],                     /* LPC1, LPC2, LPC3 */
-         swSi,                         /* INT_LPC */
-         swEngyRShift;                 /* for use by spectral postfilter */
-
-
-  Shortword swR0NewCN;                 /* DTX mode */
-
-  extern LongwordRom ppLr_gsTable[4][32];       /* DTX mode */
-
-
-/***************************************************************************
- *
- *   FUNCTION NAME: aFlatRcDp
- *
- *   PURPOSE:
- *
- *     Given a Longword autocorrelation sequence, representing LPC
- *     information, aFlatRcDp converts the vector to one of NP
- *     Shortword reflection coefficients.
- *
- *   INPUT:
- *
- *
- *     pL_R[0:NP]    - An input Longword autocorrelation sequence, (pL_R[0] =
- *                     not necessarily 0x7fffffffL).  pL_R is altered in the
- *                     call, by being right shifted by global constant
- *                     AFSHIFT bits.
- *
- *                     The input array pL_R[] should be shifted left as much
- *                     as possible to improve precision.
- *
- *     AFSHIFT       - The number of right shifts to be applied to the
- *                     normalized autocorrelation sequence pL_R.
- *
- *   OUTPUT:
- *
- *     pswRc[0:NP-1] - A Shortword output vector of NP reflection
- *                     coefficients.
- *
- *   RETURN VALUE:
- *
- *     None
- *
- *   DESCRIPTION:
- *
- *     This routine transforms LPC information from one set of
- *     parameters to another.  It is better suited for fixed point
- *     implementations than the Levinson-Dubin recursion.
- *
- *     The function is called by a_sst(), and getNWCoefs().  In a_sst()
- *     direct form coefficients are converted to autocorrelations,
- *     and smoothed in that domain.  Conversion back to direct form
- *     coefficients is done by calling aFlatRc(), followed by rcToADp().
- *
- *     In getNwCoefs() again the conversion back to direct form
- *     coefficients is done by calling aFlatRc(), followed by rcToADp().
- *     In getNwCoefs() an autocorrelation sequence is generated from the
- *     impulse response of the weighting filters.
- *
- *     The fundamental recursion is derived from AFLAT, which is
- *     described in section 4.1.4.1.
- *
- *     Unlike in AFLAT where the reflection coefficients are known, here
- *     they are the unknowns.  PBar and VBar for j==0 are initially
- *     known, as is rSub1.  From this information the next set of P's
- *     and V's are generated.  At the end of the recursion the next,
- *     reflection coefficient rSubj (pswRc[j]) can be calcluated by
- *     dividing Vsubj by Psubj.
- *
- *     Precision is crucial in this routine.  At each stage, a
- *     normalization is performed prior to the reflection coefficient
- *     calculation.  In addition, to prevent overflow, the
- *     autocorrelation sequence is scaled down by ASHIFT (4) right
- *     shifts.
- *
- *
- *   REFERENCES: Sub_Clause 4.1.9 and 4.2.1  of GSM Recomendation 06.20
- *
- *   KEYWORDS: reflection coefficients, AFLAT, aflat, recursion, LPC
- *   KEYWORDS: autocorrelation
- *
- *************************************************************************/
-
-  void   aFlatRcDp(Longword *pL_R, Shortword *pswRc)
-{
-
-/*_________________________________________________________________________
- |                                                                         |
- |                            Automatic Variables                          |
- |_________________________________________________________________________|
-*/
-
-  Longword pL_pjNewSpace[NP];
-  Longword pL_pjOldSpace[NP];
-  Longword pL_vjNewSpace[2 * NP - 1];
-  Longword pL_vjOldSpace[2 * NP - 1];
-
-  Longword *pL_pjOld;
-  Longword *pL_pjNew;
-  Longword *pL_vjOld;
-  Longword *pL_vjNew;
-  Longword *pL_swap;
-
-  Longword L_temp;
-  Longword L_sum;
-  Shortword swRc,
-         swRcSq,
-         swTemp,
-         swTemp1,
-         swAbsTemp1,
-         swTemp2;
-  int    i,
-         j;
-
-
-/*_________________________________________________________________________
- |                                                                         |
- |                              Executable Code                            |
- |_________________________________________________________________________|
-*/
-
-  pL_pjOld = pL_pjOldSpace;
-  pL_pjNew = pL_pjNewSpace;
-  pL_vjOld = pL_vjOldSpace + NP - 1;
-  pL_vjNew = pL_vjNewSpace + NP - 1;
-
-
-  /* Extract the 0-th reflection coefficient */
-  /*-----------------------------------------*/
-
-  swTemp1 = round(pL_R[1]);
-  swTemp2 = round(pL_R[0]);
-  swAbsTemp1 = abs_s(swTemp1);
-  if (swTemp2 <= 0 || sub(swAbsTemp1, swTemp2) >= 0)
-  {
-    j = 0;
-    for (i = j; i < NP; i++)
-    {
-      pswRc[i] = 0;
-    }
-    return;
-  }
-
-  swRc = divide_s(swAbsTemp1, swTemp2);/* return division result */
-
-  if (sub(swTemp1, swAbsTemp1) == 0)
-    swRc = negate(swRc);               /* negate reflection Rc[j] */
-
-  pswRc[0] = swRc;                     /* copy into the output Rc array */
-
-  for (i = 0; i <= NP; i++)
-  {
-    pL_R[i] = L_shr(pL_R[i], AFSHIFT);
-  }
-
-  /* Initialize the pjOld and vjOld recursion arrays */
-  /*-------------------------------------------------*/
-
-  for (i = 0; i < NP; i++)
-  {
-    pL_pjOld[i] = pL_R[i];
-    pL_vjOld[i] = pL_R[i + 1];
-  }
-  for (i = -1; i > -NP; i--)
-    pL_vjOld[i] = pL_R[-(i + 1)];
-
-
-  /* Compute the square of the j=0 reflection coefficient */
-  /*------------------------------------------------------*/
-
-  swRcSq = mult_r(swRc, swRc);
-
-  /* Update pjNew and vjNew arrays for lattice stage j=1 */
-  /*-----------------------------------------------------*/
-
-  /* Updating pjNew: */
-  /*-------------------*/
-
-  for (i = 0; i <= NP - 2; i++)
-  {
-    L_temp = L_mpy_ls(pL_vjOld[i], swRc);
-    L_sum = L_add(L_temp, pL_pjOld[i]);
-    L_temp = L_mpy_ls(pL_pjOld[i], swRcSq);
-    L_sum = L_add(L_temp, L_sum);
-    L_temp = L_mpy_ls(pL_vjOld[-i], swRc);
-    pL_pjNew[i] = L_add(L_sum, L_temp);
-  }
-
-  /* Updating vjNew: */
-  /*-------------------*/
-
-  for (i = -NP + 2; i <= NP - 2; i++)
-  {
-    L_temp = L_mpy_ls(pL_vjOld[-i - 1], swRcSq);
-    L_sum = L_add(L_temp, pL_vjOld[i + 1]);
-    L_temp = L_mpy_ls(pL_pjOld[(((i + 1) >= 0) ? i + 1 : -(i + 1))], swRc);
-    L_temp = L_shl(L_temp, 1);
-    pL_vjNew[i] = L_add(L_temp, L_sum);
-  }
-
-
-
-  j = 0;
-
-  /* Compute reflection coefficients Rc[1],...,Rc[9] */
-  /*-------------------------------------------------*/
-
-  for (j = 1; j < NP; j++)
-  {
-
-    /* Swap pjNew and pjOld buffers */
-    /*------------------------------*/
-
-    pL_swap = pL_pjNew;
-    pL_pjNew = pL_pjOld;
-    pL_pjOld = pL_swap;
-
-    /* Swap vjNew and vjOld buffers */
-    /*------------------------------*/
-
-    pL_swap = pL_vjNew;
-    pL_vjNew = pL_vjOld;
-    pL_vjOld = pL_swap;
-
-    /* Compute the j-th reflection coefficient */
-    /*-----------------------------------------*/
-
-    swTemp = norm_l(pL_pjOld[0]);      /* get shift count */
-    swTemp1 = round(L_shl(pL_vjOld[0], swTemp));        /* normalize num.  */
-    swTemp2 = round(L_shl(pL_pjOld[0], swTemp));        /* normalize den.  */
-
-    /* Test for invalid divide conditions: a) devisor < 0 b) abs(divident) >
-     * abs(devisor) If either of these conditions is true, zero out
-     * reflection coefficients for i=j,...,NP-1 and return. */
-
-    swAbsTemp1 = abs_s(swTemp1);
-    if (swTemp2 <= 0 || sub(swAbsTemp1, swTemp2) >= 0)
-    {
-      i = j;
-      for (i = j; i < NP; i++)
-      {
-        pswRc[i] = 0;
-      }
-      return;
-    }
-
-    swRc = divide_s(swAbsTemp1, swTemp2);       /* return division result */
-    if (sub(swTemp1, swAbsTemp1) == 0)
-      swRc = negate(swRc);             /* negate reflection Rc[j] */
-    swRcSq = mult_r(swRc, swRc);       /* compute Rc^2 */
-    pswRc[j] = swRc;                   /* copy Rc[j] to output array */
-
-    /* Update pjNew and vjNew arrays for the next lattice stage if j < NP-1 */
-    /*---------------------------------------------------------------------*/
-
-    /* Updating pjNew: */
-    /*-----------------*/
-
-    for (i = 0; i <= NP - j - 2; i++)
-    {
-      L_temp = L_mpy_ls(pL_vjOld[i], swRc);
-      L_sum = L_add(L_temp, pL_pjOld[i]);
-      L_temp = L_mpy_ls(pL_pjOld[i], swRcSq);
-      L_sum = L_add(L_temp, L_sum);
-      L_temp = L_mpy_ls(pL_vjOld[-i], swRc);
-      pL_pjNew[i] = L_add(L_sum, L_temp);
-    }
-
-    /* Updating vjNew: */
-    /*-----------------*/
-
-    for (i = -NP + j + 2; i <= NP - j - 2; i++)
-    {
-      L_temp = L_mpy_ls(pL_vjOld[-i - 1], swRcSq);
-      L_sum = L_add(L_temp, pL_vjOld[i + 1]);
-      L_temp = L_mpy_ls(pL_pjOld[(((i + 1) >= 0) ? i + 1 : -(i + 1))], swRc);
-      L_temp = L_shl(L_temp, 1);
-      pL_vjNew[i] = L_add(L_temp, L_sum);
-    }
-  }
-  return;
-}
+#define  PCM_MASK     0xfff8           /* 16 to 13 bit linear PCM mask */
 
 /***************************************************************************
  *
@@ -730,7 +408,7 @@
  |_________________________________________________________________________|
 */
 
-  static ShortwordRom psrSST[NP + 1] = {0x7FFF,
+  static const ShortwordRom psrSST[NP + 1] = {0x7FFF,
     0x7F5C, 0x7D76, 0x7A5B, 0x7622, 0x70EC,
     0x6ADD, 0x641F, 0x5CDD, 0x5546, 0x4D86,
   };
@@ -928,955 +606,6 @@
 
 /***************************************************************************
  *
- *   FUNCTION NAME: b_con
- *
- *   PURPOSE:
- *     Expands codeword into an one dimensional array. The 0/1 input is
- *     changed to an element with magnitude +/- 0.5.
- *
- *     input  output
- *
- *       0    -0.5
- *       1    +0.5
- *
- *   INPUT:
- *
- *      swCodeWord
- *                     Input codeword, information in the LSB's
- *
- *      siNumBits
- *                     number of bits in the input codeword and number
- *                     of elements in output vector
- *
- *      pswVectOut[0:siNumBits]
- *
- *                     pointer to bit array
- *
- *   OUTPUT:
- *
- *      pswVectOut[0:siNumBits]
- *
- *                     signed bit array
- *
- *   RETURN:
- *
- *      none
- *
- *   REFERENCES: Sub_Clause 4.1.10 and 4.2.1 of GSM Recomendation 06.20
- *
- *   KEYWORDS: b_con, codeword, expansion
- *
- *************************************************************************/
-
-void   b_con(Shortword swCodeWord, short siNumBits,
-                    Shortword pswVectOut[])
-{
-
-/*_________________________________________________________________________
- |                                                                         |
- |                            Automatic Variables                          |
- |_________________________________________________________________________|
-*/
-
-  short int siLoopCnt;
-
-/*_________________________________________________________________________
- |                                                                         |
- |                              Executable Code                            |
- |_________________________________________________________________________|
-*/
-
-  for (siLoopCnt = 0; siLoopCnt < siNumBits; siLoopCnt++)
-  {
-
-    if (swCodeWord & 1)                /* temp accumulator get 0.5 */
-      pswVectOut[siLoopCnt] = (Shortword) 0x4000;
-    else                               /* temp accumulator gets -0.5 */
-      pswVectOut[siLoopCnt] = (Shortword) 0xc000;
-
-    swCodeWord = shr(swCodeWord, 1);
-  }
-}
-
-/***************************************************************************
- *
- *   FUNCTION NAME: fp_ex
- *
- *   PURPOSE:
- *
- *     Looks up a vector in the adaptive excitation codebook (long-term
- *     predictor).
- *
- *   INPUTS:
- *
- *     swOrigLagIn
- *
- *                     Extended resolution lag (lag * oversampling factor)
- *
- *     pswLTPState[-147:39]
- *
- *                     Adaptive codebook (with space at end for looked up
- *                     vector).  Indicies [-147:-1] are the history, [0:39]
- *                     are for the looked up vector.
- *
- *     psrPitchIntrpFirBase[0:59]
- *     ppsrPVecIntFilt[0:9][0:5] ([tap][phase])
- *
- *                     Interpolating FIR filter coefficients.
- *
- *   OUTPUTS:
- *
- *     pswLTPState[0:39]
- *
- *                     Array containing the contructed output vector
- *
- *   RETURN VALUE:
- *     none
- *
- *   DESCRIPTION:
- *
- *     The adaptive codebook consists of the history of the excitation.
- *     The vector is looked up by going back into this history
- *     by the amount of the input lag.  If the input lag is fractional,
- *     then the samples to be looked up are interpolated from the existing
- *     samples in the history.
- *
- *     If the lag is less than the length of the vector to be generated
- *     (i.e. less than the subframe length), then the lag is doubled
- *     after the first n samples have been looked up (n = input lag).
- *     In this way, the samples being generated are not part of the
- *     codebook.  This is described in section 4.1.8.
- *
- *   REFERENCES: Sub_Clause 4.1.8.5 and 4.2.1  of GSM Recomendation 06.20
- *
- *   Keywords: pitch, excitation vector, long term filter, history,
- *   Keywords: fractional lag, get_ipjj
- *
- *************************************************************************/
-
-
-
-void   fp_ex(Shortword swOrigLagIn,
-                    Shortword pswLTPState[])
-{
-
-/*_________________________________________________________________________
- |                                                                         |
- |                            Automatic Variables                          |
- |_________________________________________________________________________|
-*/
-
-  Longword L_Temp;
-  Shortword swIntLag,
-         swRemain,
-         swRunningLag;
-  short int siSampsSoFar,
-         siSampsThisPass,
-         i,
-         j;
-
-/*_________________________________________________________________________
- |                                                                         |
- |                              Executable Code                            |
- |_________________________________________________________________________|
-*/
-
-  /* Loop: execute until all samples in the vector have been looked up */
-  /*-------------------------------------------------------------------*/
-
-  swRunningLag = swOrigLagIn;
-  siSampsSoFar = 0;
-  while (siSampsSoFar < S_LEN)
-  {
-
-    /* Get integer lag and remainder.  These are used in addressing */
-    /* the LTP state and the interpolating filter, respectively     */
-    /*--------------------------------------------------------------*/
-
-    get_ipjj(swRunningLag, &swIntLag, &swRemain);
-
-
-    /* Get the number of samples to look up in this pass */
-    /*---------------------------------------------------*/
-
-    if (sub(swIntLag, S_LEN) < 0)
-      siSampsThisPass = swIntLag - siSampsSoFar;
-    else
-      siSampsThisPass = S_LEN - siSampsSoFar;
-
-    /* Look up samples by interpolating (fractional lag), or copying */
-    /* (integer lag).                                                */
-    /*---------------------------------------------------------------*/
-
-    if (swRemain == 0)
-    {
-
-      /* Integer lag: copy samples from history */
-      /*----------------------------------------*/
-
-      for (i = siSampsSoFar; i < siSampsSoFar + siSampsThisPass; i++)
-        pswLTPState[i] = pswLTPState[i - swIntLag];
-    }
-    else
-    {
-
-      /* Fractional lag: interpolate to get samples */
-      /*--------------------------------------------*/
-
-      for (i = siSampsSoFar; i < siSampsSoFar + siSampsThisPass; i++)
-      {
-
-        /* first tap with rounding offset */
-        /*--------------------------------*/
-        L_Temp = L_mac((long) 32768,
-                       pswLTPState[i - swIntLag - P_INT_MACS / 2],
-                       ppsrPVecIntFilt[0][swRemain]);
-
-        for (j = 1; j < P_INT_MACS - 1; j++)
-        {
-
-          L_Temp = L_mac(L_Temp,
-                         pswLTPState[i - swIntLag - P_INT_MACS / 2 + j],
-                         ppsrPVecIntFilt[j][swRemain]);
-
-        }
-
-        pswLTPState[i] = extract_h(L_mac(L_Temp,
-                             pswLTPState[i - swIntLag + P_INT_MACS / 2 - 1],
-                                ppsrPVecIntFilt[P_INT_MACS - 1][swRemain]));
-      }
-    }
-
-    /* Done with this pass: update loop controls */
-    /*-------------------------------------------*/
-
-    siSampsSoFar += siSampsThisPass;
-    swRunningLag = add(swRunningLag, swOrigLagIn);
-  }
-}
-
-/***************************************************************************
- *
- *    FUNCTION NAME: g_corr1 (no scaling)
- *
- *    PURPOSE:
- *
- *     Calculates energy in subframe vector.  Differs from g_corr1s,
- *     in that there the estimate of the maximum possible
- *     energy is < 1.0
- *
- *
- *    INPUT:
- *
- *       pswIn[0:39]
- *                     A subframe vector.
- *
- *
- *    OUTPUT:
- *
- *       *pL_out
- *                     A Longword containing the normalized energy
- *                     in the input vector.
- *
- *    RETURN:
- *
- *       swOut
- *                     Number of right shifts which the accumulator was
- *                     shifted to normalize it.  Negative number implies
- *                     a left shift, and therefore an energy larger than
- *                     1.0.
- *
- *    REFERENCES: Sub_Clause 4.1.10.2 and 4.2.1 of GSM Recomendation 06.20
- *
- *    KEYWORDS: energy, autocorrelation, correlation, g_corr1
- *
- *
- *************************************************************************/
-
-Shortword g_corr1(Shortword *pswIn, Longword *pL_out)
-{
-
-
-/*_________________________________________________________________________
- |                                                                         |
- |                            Automatic Variables                          |
- |_________________________________________________________________________|
-*/
-
-  Longword L_sum;
-  Shortword swEngyLShft;
-  int    i;
-
-
-/*_________________________________________________________________________
- |                                                                         |
- |                              Executable Code                            |
- |_________________________________________________________________________|
-*/
-
-
-  /* Calculate energy in subframe vector (40 samples) */
-  /*--------------------------------------------------*/
-
-  L_sum = L_mult(pswIn[0], pswIn[0]);
-  for (i = 1; i < S_LEN; i++)
-  {
-    L_sum = L_mac(L_sum, pswIn[i], pswIn[i]);
-  }
-
-
-
-  if (L_sum != 0)
-  {
-
-    /* Normalize the energy in the output Longword */
-    /*---------------------------------------------*/
-
-    swEngyLShft = norm_l(L_sum);
-    *pL_out = L_shl(L_sum, swEngyLShft);        /* normalize output
-                                                 * Longword */
-  }
-  else
-  {
-
-    /* Special case: energy is zero */
-    /*------------------------------*/
-
-    *pL_out = L_sum;
-    swEngyLShft = 0;
-  }
-
-  return (swEngyLShft);
-}
-
-/***************************************************************************
- *
- *    FUNCTION NAME: g_corr1s (g_corr1 with scaling)
- *
- *    PURPOSE:
- *
- *     Calculates energy in subframe vector.  Differs from g_corr1,
- *     in that there is an estimate of the maximum possible energy in the
- *     vector.
- *
- *    INPUT:
- *
- *       pswIn[0:39]
- *                     A subframe vector.
- *
- *       swEngyRShft
- *
- *                     Number of right shifts to apply to the vectors energy
- *                     to ensure that it remains less than 1.0
- *                     (swEngyRShft is always positive or zero)
- *
- *    OUTPUT:
- *
- *       *pL_out
- *                     A Longword containing the normalized energy
- *                     in the input vector.
- *
- *    RETURN:
- *
- *       swOut
- *                     Number of right shifts which the accumulator was
- *                     shifted to normalize it.  Negative number implies
- *                     a left shift, and therefore an energy larger than
- *                     1.0.
- *
- *    REFERENCES: Sub-Clause 4.1.8, 4.2.1, 4.2.2, and 4.2.4
- *                of GSM Recomendation 06.20
- *
- *    keywords: energy, autocorrelation, correlation, g_corr1
- *
- *
- *************************************************************************/
-
-Shortword g_corr1s(Shortword pswIn[], Shortword swEngyRShft,
-                          Longword *pL_out)
-{
-
-
-/*_________________________________________________________________________
- |                                                                         |
- |                            Automatic Variables                          |
- |_________________________________________________________________________|
-*/
-
-  Longword L_sum;
-  Shortword swTemp,
-         swEngyLShft;
-  Shortword swInputRShft;
-
-  int    i;
-
-
-/*_________________________________________________________________________
- |                                                                         |
- |                              Executable Code                            |
- |_________________________________________________________________________|
-*/
-
-
-  /* Calculate energy in subframe vector (40 samples) */
-  /*--------------------------------------------------*/
-
-  if (sub(swEngyRShft, 1) <= 0)
-  {
-
-    /* use the energy shift factor, although it is an odd shift count */
-    /*----------------------------------------------------------------*/
-
-    swTemp = shr(pswIn[0], swEngyRShft);
-    L_sum = L_mult(pswIn[0], swTemp);
-    for (i = 1; i < S_LEN; i++)
-    {
-      swTemp = shr(pswIn[i], swEngyRShft);
-      L_sum = L_mac(L_sum, pswIn[i], swTemp);
-    }
-
-  }
-  else
-  {
-
-    /* convert energy shift factor to an input shift factor */
-    /*------------------------------------------------------*/
-
-    swInputRShft = shift_r(swEngyRShft, -1);
-    swEngyRShft = shl(swInputRShft, 1);
-
-    swTemp = shr(pswIn[0], swInputRShft);
-    L_sum = L_mult(swTemp, swTemp);
-    for (i = 1; i < S_LEN; i++)
-    {
-      swTemp = shr(pswIn[i], swInputRShft);
-      L_sum = L_mac(L_sum, swTemp, swTemp);
-    }
-  }
-
-  if (L_sum != 0)
-  {
-
-    /* Normalize the energy in the output Longword */
-    /*---------------------------------------------*/
-
-    swTemp = norm_l(L_sum);
-    *pL_out = L_shl(L_sum, swTemp);    /* normalize output Longword */
-    swEngyLShft = sub(swTemp, swEngyRShft);
-  }
-  else
-  {
-
-    /* Special case: energy is zero */
-    /*------------------------------*/
-
-    *pL_out = L_sum;
-    swEngyLShft = 0;
-  }
-
-  return (swEngyLShft);
-}
-
-/***************************************************************************
- *
- *   FUNCTION NAME: getSfrmLpc
- *
- *   PURPOSE:
- *
- *     Given frame information from past and present frame, interpolate
- *     (or copy) the frame based LPC coefficients into subframe
- *     lpc coeffs, i.e. the ones which will be used by the subframe
- *     as opposed to those coded and transmitted.
- *
- *   INPUTS:
- *
- *     siSoftInterpolation
- *
- *                     interpolate 1/0, a coded parameter.
- *
- *     swPrevR0,swNewR0
- *
- *                     Rq0 for the last frame and for this frame.
- *                     These are the decoded values, not the codewords.
- *
- *     Previous lpc coefficients from the previous frame:
- *       in all filters below array[0] is the t=-1 element array[9]
- *       t=-10 element.
- *
- *     pswPrevFrmKs[0:9]
- *
- *                     decoded version of the rc's tx'd last frame
- *
- *     pswPrevFrmAs[0:9]
- *
- *                     the above K's converted to A's.  i.e. direct
- *                     form coefficients.
- *
- *     pswPrevFrmPFNum[0:9], pswPrevFrmPFDenom[0:9]
- *
- *                     numerator and denominator coefficients used in the
- *                     postfilter
- *
- *     Current lpc coefficients from the current frame:
- *
- *     pswNewFrmKs[0:9], pswNewFrmAs[0:9],
- *     pswNewFrmPFNum[0:9], pswNewFrmPFDenom[0:9] same as above.
- *
- *   OUTPUTS:
- *
- *     psnsSqrtRs[0:3]
- *
- *                      a normalized number (struct NormSw)
- *                      containing an estimate of RS for each subframe.
- *                      (number and a shift)
- *
- *     ppswSynthAs[0:3][0:9]
- *
- *                      filter coefficients used by the synthesis filter.
- *
- *     ppswPFNumAs[0:3][0:9]
- *
- *                      filter coefficients used by the postfilters
- *                      numerator.
- *
- *     ppswPFDenomAs[0:3][0:9]
- *
- *                      filter coefficients used by postfilters denominator.
- *
- *   RETURN VALUE:
- *
- *     None
- *
- *   DESCRIPTION:
- *
- *     For interpolated subframes, the direct form coefficients
- *     are converted to reflection coeffiecients to check for
- *     filter stability. If unstable, the uninterpolated coef.
- *     are used for that subframe.
- *
- *     Interpolation is described in section 4.1.6, "Soft Interpolation
- *     of the Spectral Parameters"
- *
- *    REFERENCES: Sub_clause 4.2.1 of GSM Recomendation 06.20
- *
- *   KEYWORDS: soft interpolation, int_lpc, interpolate, atorc,res_eng,i_mov
- *
- *************************************************************************/
-
-void   getSfrmLpc(short int siSoftInterpolation,
-                         Shortword swPrevR0, Shortword swNewR0,
-          /* last frm */ Shortword pswPrevFrmKs[], Shortword pswPrevFrmAs[],
-                         Shortword pswPrevFrmPFNum[],
-                         Shortword pswPrevFrmPFDenom[],
-
-            /* this frm */ Shortword pswNewFrmKs[], Shortword pswNewFrmAs[],
-                         Shortword pswNewFrmPFNum[],
-                         Shortword pswNewFrmPFDenom[],
-
-                   /* output */ struct NormSw *psnsSqrtRs,
-                         Shortword *ppswSynthAs[], Shortword *ppswPFNumAs[],
-                         Shortword *ppswPFDenomAs[])
-{
-
-/*_________________________________________________________________________
- |                                                                         |
- |                           Local Static Variables                        |
- |_________________________________________________________________________|
-*/
-
-
-/*_________________________________________________________________________
- |                                                                         |
- |                            Automatic Variables                          |
- |_________________________________________________________________________|
-*/
-
-  short int siSfrm,
-         siStable,
-         i;
-
-  Longword L_Temp1,
-         L_Temp2;
-
-/*_________________________________________________________________________
- |                                                                         |
- |                              Executable Code                            |
- |_________________________________________________________________________|
-*/
-
-  if (siSoftInterpolation)
-  {
-    /* yes, interpolating */
-    /* ------------------ */
-
-    siSfrm = 0;
-
-    siStable = interpolateCheck(pswPrevFrmKs, pswPrevFrmAs,
-                                pswPrevFrmAs, pswNewFrmAs,
-                                psrOldCont[siSfrm], psrNewCont[siSfrm],
-                                swPrevR0,
-                                &psnsSqrtRs[siSfrm],
-                                ppswSynthAs[siSfrm]);
-    if (siStable)
-    {
-
-      /* interpolate between direct form coefficient sets */
-      /* for both numerator and denominator coefficients  */
-      /* assume output will be stable                     */
-      /* ------------------------------------------------ */
-
-      for (i = 0; i < NP; i++)
-      {
-        L_Temp1 = L_mult(pswNewFrmPFNum[i], psrNewCont[siSfrm]);
-        ppswPFNumAs[siSfrm][i] = mac_r(L_Temp1, pswPrevFrmPFNum[i],
-                                       psrOldCont[siSfrm]);
-        L_Temp2 = L_mult(pswNewFrmPFDenom[i], psrNewCont[siSfrm]);
-        ppswPFDenomAs[siSfrm][i] = mac_r(L_Temp2, pswPrevFrmPFDenom[i],
-                                         psrOldCont[siSfrm]);
-      }
-    }
-    else
-    {
-      /* this subframe is unstable */
-      /* ------------------------- */
-      for (i = 0; i < NP; i++)
-      {
-        ppswPFNumAs[siSfrm][i] = pswPrevFrmPFNum[i];
-        ppswPFDenomAs[siSfrm][i] = pswPrevFrmPFDenom[i];
-      }
-    }
-    for (siSfrm = 1; siSfrm < N_SUB - 1; siSfrm++)
-    {
-
-      siStable = interpolateCheck(pswNewFrmKs, pswNewFrmAs,
-                                  pswPrevFrmAs, pswNewFrmAs,
-                                  psrOldCont[siSfrm], psrNewCont[siSfrm],
-                                  swNewR0,
-                                  &psnsSqrtRs[siSfrm],
-                                  ppswSynthAs[siSfrm]);
-      if (siStable)
-      {
-
-        /* interpolate between direct form coefficient sets */
-        /* for both numerator and denominator coefficients  */
-        /* assume output will be stable                     */
-        /* ------------------------------------------------ */
-
-        for (i = 0; i < NP; i++)
-        {
-          L_Temp1 = L_mult(pswNewFrmPFNum[i], psrNewCont[siSfrm]);
-          ppswPFNumAs[siSfrm][i] = mac_r(L_Temp1, pswPrevFrmPFNum[i],
-                                         psrOldCont[siSfrm]);
-          L_Temp2 = L_mult(pswNewFrmPFDenom[i], psrNewCont[siSfrm]);
-          ppswPFDenomAs[siSfrm][i] = mac_r(L_Temp2, pswPrevFrmPFDenom[i],
-                                           psrOldCont[siSfrm]);
-        }
-      }
-      else
-      {
-        /* this subframe has unstable filter coeffs, would like to
-         * interpolate but can not  */
-        /* -------------------------------------- */
-        for (i = 0; i < NP; i++)
-        {
-          ppswPFNumAs[siSfrm][i] = pswNewFrmPFNum[i];
-          ppswPFDenomAs[siSfrm][i] = pswNewFrmPFDenom[i];
-        }
-      }
-    }
-    /* the last subframe never interpolate */
-    /* ----------------------------------- */
-    siSfrm = 3;
-    for (i = 0; i < NP; i++)
-    {
-      ppswPFNumAs[siSfrm][i] = pswNewFrmPFNum[i];
-      ppswPFDenomAs[siSfrm][i] = pswNewFrmPFDenom[i];
-      ppswSynthAs[siSfrm][i] = pswNewFrmAs[i];
-    }
-
-    res_eng(pswNewFrmKs, swNewR0, &psnsSqrtRs[siSfrm]);
-
-  }
-  /* SoftInterpolation == 0  - no interpolation */
-  /* ------------------------------------------ */
-  else
-  {
-    siSfrm = 0;
-    for (i = 0; i < NP; i++)
-    {
-      ppswPFNumAs[siSfrm][i] = pswPrevFrmPFNum[i];
-      ppswPFDenomAs[siSfrm][i] = pswPrevFrmPFDenom[i];
-      ppswSynthAs[siSfrm][i] = pswPrevFrmAs[i];
-    }
-
-    res_eng(pswPrevFrmKs, swPrevR0, &psnsSqrtRs[siSfrm]);
-
-    /* for subframe 1 and all subsequent sfrms, use result from new frm */
-    /* ---------------------------------------------------------------- */
-
-
-    res_eng(pswNewFrmKs, swNewR0, &psnsSqrtRs[1]);
-
-    for (siSfrm = 1; siSfrm < N_SUB; siSfrm++)
-    {
-
-
-      psnsSqrtRs[siSfrm].man = psnsSqrtRs[1].man;
-      psnsSqrtRs[siSfrm].sh = psnsSqrtRs[1].sh;
-
-      for (i = 0; i < NP; i++)
-      {
-        ppswPFNumAs[siSfrm][i] = pswNewFrmPFNum[i];
-        ppswPFDenomAs[siSfrm][i] = pswNewFrmPFDenom[i];
-        ppswSynthAs[siSfrm][i] = pswNewFrmAs[i];
-      }
-    }
-  }
-}
-
-/***************************************************************************
- *
- *   FUNCTION NAME: get_ipjj
- *
- *   PURPOSE:
- *
- *     This subroutine calculates IP, the single-resolution lag rounded
- *     down to the nearest integer, and JJ, the remainder when the
- *     extended resolution lag is divided by the oversampling factor
- *
- *   INPUTS:
- *
- *     swLagIn
- *                     extended resolution lag as an integer, i.e.
- *                     fractional lag x oversampling factor
- *
- *   OUTPUTS:
- *
- *     *pswIp
- *                     fractional lag rounded down to nearest integer, IP
- *
- *     *pswJj
- *                     the remainder JJ
- *
- *   RETURN VALUE:
- *
- *     none
- *
- *   DESCRIPTION:
- *
- *     ip = integer[lag/OS_FCTR]
- *     jj = integer_round[((lag/OS_FCTR)-ip)*(OS_FCTR)]
- *          if the rounding caused an 'overflow'
- *            set remainder jj to 0 and add 'carry' to ip
- *
- *     This routine is involved in the mechanics of fractional and
- *     integer LTP searchs.  The LTP is described in section 5.
- *
- *   REFERENCES: Sub-clause 4.1.8 and 4.2.2 of GSM Recomendation 06.20
- *
- *   KEYWORDS: lag, fractional, remainder, ip, jj, get_ipjj
- *
- *************************************************************************/
-
-void   get_ipjj(Shortword swLagIn,
-                       Shortword *pswIp, Shortword *pswJj)
-{
-
-/*_________________________________________________________________________
- |                                                                         |
- |                              Local Constants                            |
- |_________________________________________________________________________|
-*/
-
-#define  OS_FCTR_INV  (Shortword)0x1555/* SW_MAX/OS_FCTR */
-
-/*_________________________________________________________________________
- |                                                                         |
- |                            Automatic Variables                          |
- |_________________________________________________________________________|
-*/
-
-  Longword L_Temp;
-
-  Shortword swTemp,
-         swTempIp,
-         swTempJj;
-
-/*_________________________________________________________________________
- |                                                                         |
- |                              Executable Code                            |
- |_________________________________________________________________________|
-*/
-
-  /* calculate ip */
-  /* ------------ */
-
-  L_Temp = L_mult(OS_FCTR_INV, swLagIn);        /* lag/OS_FCTR */
-  swTempIp = extract_h(L_Temp);
-
-  /* calculate jj */
-  /* ------------ */
-
-  swTemp = extract_l(L_Temp);          /* loose ip */
-  swTemp = shr(swTemp, 1);             /* isolate jj fraction */
-  swTemp = swTemp & SW_MAX;
-  L_Temp = L_mult(swTemp, OS_FCTR);    /* ((lag/OS_FCTR)-ip))*(OS_FCTR) */
-  swTemp = round(L_Temp);              /* round and pick-off jj */
-  if (sub(swTemp, OS_FCTR) == 0)
-  {                                    /* if 'overflow ' */
-    swTempJj = 0;                      /* set remainder,jj to 0 */
-    swTempIp = add(swTempIp, 1);       /* 'carry' overflow into ip */
-  }
-  else
-  {
-    swTempJj = swTemp;                 /* read-off remainder,jj */
-  }
-
-  /* return ip and jj */
-  /* ---------------- */
-
-  *pswIp = swTempIp;
-  *pswJj = swTempJj;
-}
-
-/***************************************************************************
- *
- *   FUNCTION NAME: interpolateCheck
- *
- *   PURPOSE:
- *
- *     Interpolates between direct form coefficient sets.
- *     Before releasing the interpolated coefficients, they are checked.
- *     If unstable, the "old" parameters are used.
- *
- *   INPUTS:
- *
- *     pswRefKs[0:9]
- *                     decoded version of the rc's tx'd last frame
- *
- *     pswRefCoefsA[0:9]
- *                     above K's converted to direct form coefficients
- *
- *     pswOldCoefsA[0:9]
- *                     array of old Coefseters
- *
- *     pswNewCoefsA[0:9]
- *                     array of new Coefseters
- *
- *     swOldPer
- *                     amount old coefs supply to the output
- *
- *     swNewPer
- *                     amount new coefs supply to the output
- *
- *     ASHIFT
- *                     shift for reflection coef. conversion
- *
- *     swRq
- *                     quantized energy to use for subframe
- * *
- *   OUTPUTS:
- *
- *     psnsSqrtRsOut
- *                     output pointer to sqrt(RS) normalized
- *
- *     pswCoefOutA[0:9]
- *                     output coefficients
- *
- *   RETURN VALUE:
- *
- *     siInterp_flg
- *                     temporary subframe interpolation flag
- *                     0 - coef. interpolated, 1 -coef. not interpolated
- *
- *   DESCRIPTION:
- *
- *     For interpolated subframes, the direct form coefficients
- *     are converted to reflection coefficients to check for
- *     filter stability. If unstable, the uninterpolated coef.
- *     are used for that subframe.  Section 4.1.6 describes
- *     interpolation.
- *
- *   REFERENCES: Sub-clause 4.1.6 and 4.2.3 of GSM Recomendation 06.20
- *
- *   KEYWORDS: soft interpolation, int_lpc, interpolate, atorc,res_eng,i_mov
- *
- *************************************************************************/
-
-short int interpolateCheck(Shortword pswRefKs[],
-                                  Shortword pswRefCoefsA[],
-                         Shortword pswOldCoefsA[], Shortword pswNewCoefsA[],
-                                  Shortword swOldPer, Shortword swNewPer,
-                                  Shortword swRq,
-                                  struct NormSw *psnsSqrtRsOut,
-                                  Shortword pswCoefOutA[])
-{
-
-/*_________________________________________________________________________
- |                                                                         |
- |                            Automatic Variables                          |
- |_________________________________________________________________________|
-*/
-
-  Shortword pswRcTemp[NP];
-
-  Longword L_Temp;
-
-  short int siInterp_flg,
-         i;
-
-/*_________________________________________________________________________
- |                                                                         |
- |                              Executable Code                            |
- |_________________________________________________________________________|
-*/
-
-  /* Interpolation loop, NP is order of LPC filter */
-  /* --------------------------------------------- */
-
-  for (i = 0; i < NP; i++)
-  {
-    L_Temp = L_mult(pswNewCoefsA[i], swNewPer);
-    pswCoefOutA[i] = mac_r(L_Temp, pswOldCoefsA[i], swOldPer);
-  }
-
-  /* Convert to reflection coefficients and check stability */
-  /* ------------------------------------------------------ */
-
-  if (aToRc(ASHIFT, pswCoefOutA, pswRcTemp) != 0)
-  {
-
-    /* Unstable, use uninterpolated parameters and compute RS update the
-     * state with the frame data closest to this subfrm */
-    /* --------------------------------------------------------- */
-
-    res_eng(pswRefKs, swRq, psnsSqrtRsOut);
-
-    for (i = 0; i < NP; i++)
-    {
-      pswCoefOutA[i] = pswRefCoefsA[i];
-    }
-    siInterp_flg = 0;
-  }
-  else
-  {
-
-    /* Stable, compute RS */
-    /* ------------------ */
-    res_eng(pswRcTemp, swRq, psnsSqrtRsOut);
-
-    /* Set temporary subframe interpolation flag */
-    /* ----------------------------------------- */
-    siInterp_flg = 1;
-  }
-
-  /* Return subframe interpolation flag */
-  /* ---------------------------------- */
-  return (siInterp_flg);
-}
-
-/***************************************************************************
- *
  *   FUNCTION NAME: lagDecode
  *
  *   PURPOSE:
@@ -1928,7 +657,8 @@
  *
  *************************************************************************/
 
-static Shortword lagDecode(Shortword swDeltaLag)
+static Shortword lagDecode(Shortword swDeltaLag, Shortword *pswLastLag,
+			   Shortword subfrm)
 {
 
 /*_________________________________________________________________________
@@ -1943,14 +673,6 @@
 
 /*_________________________________________________________________________
  |                                                                         |
- |                           Local Static Variables                        |
- |_________________________________________________________________________|
-*/
-
-  static Shortword swLastLag;
-
-/*_________________________________________________________________________
- |                                                                         |
  |                            Automatic Variables                          |
  |_________________________________________________________________________|
 */
@@ -1966,9 +688,9 @@
   /* first sub-frame */
   /* --------------- */
 
-  if (giSfrmCnt == 0)
+  if (subfrm == 0)
   {
-    swLastLag = swDeltaLag;
+    *pswLastLag = swDeltaLag;
   }
 
   /* remaining sub-frames */
@@ -1985,29 +707,29 @@
     /* get real lag relative to last */
     /* ----------------------------- */
 
-    swLag = add(swLag, swLastLag);
+    swLag = add(swLag, *pswLastLag);
 
     /* clip to max or min */
     /* ------------------ */
 
     if (sub(swLag, MAX_LAG) > 0)
     {
-      swLastLag = MAX_LAG;
+      *pswLastLag = MAX_LAG;
     }
     else if (sub(swLag, MIN_LAG) < 0)
     {
-      swLastLag = MIN_LAG;
+      *pswLastLag = MIN_LAG;
     }
     else
     {
-      swLastLag = swLag;
+      *pswLastLag = swLag;
     }
   }
 
   /* return lag after look up */
   /* ------------------------ */
 
-  swLag = psrLagTbl[swLastLag];
+  swLag = psrLagTbl[*pswLastLag];
   return (swLag);
 }
 
@@ -2071,7 +793,7 @@
          siVector2,
          siWordPtr;
 
-  ShortwordRom *psrQTable;
+  const ShortwordRom *psrQTable;
 
 /*_________________________________________________________________________
  |                                                                         |
@@ -2157,957 +879,6 @@
   }
 }
 
-/***************************************************************************
- *
- *   FUNCTION NAME: lpcFir
- *
- *   PURPOSE:
- *
- *     The purpose of this function is to perform direct form fir filtering
- *     assuming a NP order filter and given state, coefficients, and input.
- *
- *   INPUTS:
- *
- *     NP
- *                     order of the lpc filter
- *
- *     S_LEN
- *                     number of samples to filter
- *
- *     pswInput[0:S_LEN-1]
- *
- *                     input array of points to be filtered.
- *                     pswInput[0] is the oldest point (first to be filtered)
- *                     pswInput[siLen-1] is the last point filtered (newest)
- *
- *     pswCoef[0:NP-1]
- *
- *                     array of direct form coefficients
- *                     pswCoef[0] = coeff for delay n = -1
- *                     pswCoef[NP-1] = coeff for delay n = -NP
- *
- *     ASHIFT
- *                     number of shifts input A's have been shifted down by
- *
- *     LPC_ROUND
- *                     rounding constant
- *
- *     pswState[0:NP-1]
- *
- *                     array of the filter state following form of pswCoef
- *                     pswState[0] = state of filter for delay n = -1
- *                     pswState[NP-1] = state of filter for delay n = -NP
- *
- *   OUTPUTS:
- *
- *     pswState[0:NP-1]
- *
- *                     updated filter state, ready to filter
- *                     pswInput[siLen], i.e. the next point
- *
- *     pswFiltOut[0:S_LEN-1]
- *
- *                     the filtered output
- *                     same format as pswInput, pswFiltOut[0] is oldest point
- *
- *   RETURN VALUE:
- *
- *     none
- *
- *   DESCRIPTION:
- *
- *     because of the default sign of the coefficients the
- *     formula for the filter is :
- *     i=0, i < S_LEN
- *        out[i] = rounded(state[i]*coef[0])
- *        j=1, j < NP
- *           out[i] += state[j]*coef[j] (state is taken from either input
- *                                       state[] or input in[] arrays)
- *        rescale(out[i])
- *        out[i] += in[i]
- *     update final state array using in[]
- *
- *   REFERENCES: Sub-clause 4.1.7 and 4.2.4 of GSM Recomendation 06.20
- *
- *   KEYWORDS: lpc, directform, fir, lpcFir, inversefilter, lpcFilt
- *   KEYWORDS: dirForm, dir_mod, dir_clr, dir_neg, dir_set, i_dir_mod
- *
- *************************************************************************/
-
-void   lpcFir(Shortword pswInput[], Shortword pswCoef[],
-                     Shortword pswState[], Shortword pswFiltOut[])
-{
-
-/*_________________________________________________________________________
- |                                                                         |
- |                            Automatic Variables                          |
- |_________________________________________________________________________|
-*/
-
-  Longword L_Sum;
-  short int siStage,
-         siSmp;
-
-/*_________________________________________________________________________
- |                                                                         |
- |                              Executable Code                            |
- |_________________________________________________________________________|
-*/
-
-  /* filter 1st sample */
-  /* ----------------- */
-
-  /* sum past state outputs */
-  /* ---------------------- */
-  /* 0th coef, with rounding */
-  L_Sum = L_mac(LPC_ROUND, pswState[0], pswCoef[0]);
-
-  for (siStage = 1; siStage < NP; siStage++)
-  {                                    /* remaining coefs */
-    L_Sum = L_mac(L_Sum, pswState[siStage], pswCoef[siStage]);
-  }
-
-  /* add input to partial output */
-  /* --------------------------- */
-
-  L_Sum = L_shl(L_Sum, ASHIFT);
-  L_Sum = L_msu(L_Sum, pswInput[0], 0x8000);
-
-  /* save 1st output sample */
-  /* ---------------------- */
-
-  pswFiltOut[0] = extract_h(L_Sum);
-
-  /* filter remaining samples */
-  /* ------------------------ */
-
-  for (siSmp = 1; siSmp < S_LEN; siSmp++)
-  {
-
-    /* sum past outputs */
-    /* ---------------- */
-    /* 0th coef, with rounding */
-    L_Sum = L_mac(LPC_ROUND, pswInput[siSmp - 1], pswCoef[0]);
-    /* remaining coefs */
-    for (siStage = 1; ((0 < (siSmp - siStage)) && siStage < NP); siStage++)
-    {
-      L_Sum = L_mac(L_Sum, pswInput[siSmp - siStage - 1], pswCoef[siStage]);
-    }
-
-    /* sum past states, if any */
-    /* ----------------------- */
-
-    for (siStage = siSmp; siStage < NP; siStage++)
-    {
-      L_Sum = L_mac(L_Sum, pswState[siStage - siSmp], pswCoef[siStage]);
-    }
-
-    /* add input to partial output */
-    /* --------------------------- */
-
-    L_Sum = L_shl(L_Sum, ASHIFT);
-    L_Sum = L_msu(L_Sum, pswInput[siSmp], 0x8000);
-
-    /* save current output sample */
-    /* -------------------------- */
-
-    pswFiltOut[siSmp] = extract_h(L_Sum);
-  }
-
-  /* save final state */
-  /* ---------------- */
-
-  for (siStage = 0; siStage < NP; siStage++)
-  {
-    pswState[siStage] = pswInput[S_LEN - siStage - 1];
-  }
-
-}
-
-/***************************************************************************
- *
- *   FUNCTION NAME: lpcIir
- *
- *   PURPOSE:
- *
- *     The purpose of this function is to perform direct form IIR filtering
- *     assuming a NP order filter and given state, coefficients, and input
- *
- *   INPUTS:
- *
- *     NP
- *                     order of the lpc filter
- *
- *     S_LEN
- *                     number of samples to filter
- *
- *     pswInput[0:S_LEN-1]
- *
- *                     input array of points to be filtered
- *                     pswInput[0] is the oldest point (first to be filtered)
- *                     pswInput[siLen-1] is the last point filtered (newest)
- *
- *     pswCoef[0:NP-1]
- *                     array of direct form coefficients
- *                     pswCoef[0] = coeff for delay n = -1
- *                     pswCoef[NP-1] = coeff for delay n = -NP
- *
- *     ASHIFT
- *                     number of shifts input A's have been shifted down by
- *
- *     LPC_ROUND
- *                     rounding constant
- *
- *     pswState[0:NP-1]
- *
- *                     array of the filter state following form of pswCoef
- *                     pswState[0] = state of filter for delay n = -1
- *                     pswState[NP-1] = state of filter for delay n = -NP
- *
- *   OUTPUTS:
- *
- *     pswState[0:NP-1]
- *
- *                     updated filter state, ready to filter
- *                     pswInput[siLen], i.e. the next point
- *
- *     pswFiltOut[0:S_LEN-1]
- *
- *                     the filtered output
- *                     same format as pswInput, pswFiltOut[0] is oldest point
- *
- *   RETURN VALUE:
- *
- *     none
- *
- *   DESCRIPTION:
- *
- *     because of the default sign of the coefficients the
- *     formula for the filter is :
- *     i=0, i < S_LEN
- *        out[i] = rounded(state[i]*coef[0])
- *        j=1, j < NP
- *           out[i] -= state[j]*coef[j] (state is taken from either input
- *                                       state[] or prior out[] arrays)
- *        rescale(out[i])
- *        out[i] += in[i]
- *     update final state array using out[]
- *
- *   REFERENCES: Sub-clause 4.1.7 and 4.2.4 of GSM Recomendation 06.20
- *
- *   KEYWORDS: lpc, directform, iir, synthesisfilter, lpcFilt
- *   KEYWORDS: dirForm, dir_mod, dir_clr, dir_neg, dir_set
- *
- *************************************************************************/
-
-void   lpcIir(Shortword pswInput[], Shortword pswCoef[],
-                     Shortword pswState[], Shortword pswFiltOut[])
-{
-
-/*_________________________________________________________________________
- |                                                                         |
- |                            Automatic Variables                          |
- |_________________________________________________________________________|
-*/
-
-  Longword L_Sum;
-  short int siStage,
-         siSmp;
-
-/*_________________________________________________________________________
- |                                                                         |
- |                              Executable Code                            |
- |_________________________________________________________________________|
-*/
-
-  /* filter 1st sample */
-  /* ----------------- */
-
-  /* sum past state outputs */
-  /* ---------------------- */
-  /* 0th coef, with rounding */
-  L_Sum = L_msu(LPC_ROUND, pswState[0], pswCoef[0]);
-
-  for (siStage = 1; siStage < NP; siStage++)
-  {                                    /* remaining coefs */
-    L_Sum = L_msu(L_Sum, pswState[siStage], pswCoef[siStage]);
-  }
-
-  /* add input to partial output */
-  /* --------------------------- */
-
-  L_Sum = L_shl(L_Sum, ASHIFT);
-  L_Sum = L_msu(L_Sum, pswInput[0], 0x8000);
-
-  /* save 1st output sample */
-  /* ---------------------- */
-
-  pswFiltOut[0] = extract_h(L_Sum);
-
-  /* filter remaining samples */
-  /* ------------------------ */
-
-  for (siSmp = 1; siSmp < S_LEN; siSmp++)
-  {
-
-    /* sum past outputs */
-    /* ---------------- */
-    /* 0th coef, with rounding */
-    L_Sum = L_msu(LPC_ROUND, pswFiltOut[siSmp - 1], pswCoef[0]);
-    /* remaining coefs */
-    for (siStage = 1; ((0 < (siSmp - siStage)) && siStage < NP); siStage++)
-    {
-      L_Sum = L_msu(L_Sum, pswFiltOut[siSmp - siStage - 1],
-                    pswCoef[siStage]);
-    }
-
-    /* sum past states, if any */
-    /* ----------------------- */
-
-    for (siStage = siSmp; siStage < NP; siStage++)
-    {
-      L_Sum = L_msu(L_Sum, pswState[siStage - siSmp], pswCoef[siStage]);
-    }
-
-    /* add input to partial output */
-    /* --------------------------- */
-
-    L_Sum = L_shl(L_Sum, ASHIFT);
-    L_Sum = L_msu(L_Sum, pswInput[siSmp], 0x8000);
-
-    /* save current output sample */
-    /* -------------------------- */
-
-    pswFiltOut[siSmp] = extract_h(L_Sum);
-  }
-
-  /* save final state */
-  /* ---------------- */
-
-  for (siStage = 0; siStage < NP; siStage++)
-  {
-    pswState[siStage] = pswFiltOut[S_LEN - siStage - 1];
-  }
-}
-
-/***************************************************************************
- *
- *   FUNCTION NAME: lpcIrZsIir
- *
- *   PURPOSE:
- *
- *     The purpose of this function is to calculate the impulse response
- *     via direct form IIR filtering with zero state assuming a NP order
- *     filter and given coefficients
- *
- *   INPUTS:
- *
- *     NP
- *                     order of the lpc filter
- *
- *     S_LEN
- *                     number of samples to filter
- *
- *     pswCoef[0:NP-1]
- *                     array of direct form coefficients
- *                     pswCoef[0] = coeff for delay n = -1
- *                     pswCoef[NP-1] = coeff for delay n = -NP
- *
- *     ASHIFT
- *                     number of shifts input A's have been shifted down by
- *
- *     LPC_ROUND
- *                     rounding constant
- *
- *   OUTPUTS:
- *
- *     pswFiltOut[0:S_LEN-1]
- *
- *                     the filtered output
- *                     same format as pswInput, pswFiltOut[0] is oldest point
- *
- *   RETURN VALUE:
- *
- *     none
- *
- *   DESCRIPTION:
- *
- *     This routine is called by getNWCoefs().
- *
- *     Because of the default sign of the coefficients the
- *     formula for the filter is :
- *     i=0, i < S_LEN
- *        out[i] = rounded(state[i]*coef[0])
- *        j=1, j < NP
- *           out[i] -= state[j]*coef[j] (state taken from prior output[])
- *        rescale(out[i])
- *
- *   REFERENCES: Sub-clause 4.1.8 of GSM Recomendation 06.20
- *
- *   KEYWORDS: lpc, directform, iir, synthesisfilter, lpcFilt
- *   KEYWORDS: dirForm, dir_mod, dir_clr, dir_neg, dir_set
- *
- *************************************************************************/
-
-void   lpcIrZsIir(Shortword pswCoef[], Shortword pswFiltOut[])
-{
-
-/*_________________________________________________________________________
- |                                                                         |
- |                            Automatic Variables                          |
- |_________________________________________________________________________|
-*/
-
-  Longword L_Sum;
-  short int siStage,
-         siSmp;
-
-/*_________________________________________________________________________
- |                                                                         |
- |                              Executable Code                            |
- |_________________________________________________________________________|
-*/
-
-  /* output 1st sample */
-  /* ----------------- */
-
-  pswFiltOut[0] = 0x0400;
-
-  /* filter remaining samples */
-  /* ------------------------ */
-
-  for (siSmp = 1; siSmp < S_LEN; siSmp++)
-  {
-
-    /* sum past outputs */
-    /* ---------------- */
-    /* 0th coef, with rounding */
-    L_Sum = L_msu(LPC_ROUND, pswFiltOut[siSmp - 1], pswCoef[0]);
-    /* remaining coefs */
-    for (siStage = 1; ((0 < (siSmp - siStage)) && siStage < NP); siStage++)
-    {
-      L_Sum = L_msu(L_Sum, pswFiltOut[siSmp - siStage - 1],
-                    pswCoef[siStage]);
-    }
-
-    /* scale output */
-    /* ------------ */
-
-    L_Sum = L_shl(L_Sum, ASHIFT);
-
-    /* save current output sample */
-    /* -------------------------- */
-
-    pswFiltOut[siSmp] = extract_h(L_Sum);
-  }
-}
-
-/***************************************************************************
- *
- *   FUNCTION NAME: lpcZiIir
- *
- *   PURPOSE:
- *     The purpose of this function is to perform direct form iir filtering
- *     with zero input assuming a NP order filter, and given state and
- *     coefficients
- *
- *   INPUTS:
- *
- *     NP
- *                     order of the lpc filter
- *
- *     S_LEN
- *                     number of samples to filter MUST be <= MAX_ZIS
- *
- *     pswCoef[0:NP-1]
- *
- *                     array of direct form coefficients.
- *                     pswCoef[0] = coeff for delay n = -1
- *                     pswCoef[NP-1] = coeff for delay n = -NP
- *
- *     ASHIFT
- *                     number of shifts input A's have been shifted down by
- *
- *     LPC_ROUND
- *                     rounding constant
- *
- *     pswState[0:NP-1]
- *
- *                     array of the filter state following form of pswCoef
- *                     pswState[0] = state of filter for delay n = -1
- *                     pswState[NP-1] = state of filter for delay n = -NP
- *
- *   OUTPUTS:
- *
- *     pswFiltOut[0:S_LEN-1]
- *
- *                     the filtered output
- *                     same format as pswIn, pswFiltOut[0] is oldest point
- *
- *   RETURN VALUE:
- *
- *     none
- *
- *   DESCRIPTION:
- *
- *     The routine is called from sfrmAnalysis, and is used to let the
- *     LPC filters ring out.
- *
- *     because of the default sign of the coefficients the
- *     formula for the filter is :
- *     i=0, i < S_LEN
- *        out[i] = rounded(state[i]*coef[0])
- *        j=1, j < NP
- *           out[i] -= state[j]*coef[j] (state is taken from either input
- *                                       state[] or prior output[] arrays)
- *        rescale(out[i])
- *
- *   REFERENCES: Sub-clause 4.1.7 of GSM Recomendation 06.20
- *
- *   KEYWORDS: lpc, directform, iir, synthesisfilter, lpcFilt
- *   KEYWORDS: dirForm, dir_mod, dir_clr, dir_neg, dir_set
- *
- *************************************************************************/
-
-void   lpcZiIir(Shortword pswCoef[], Shortword pswState[],
-                       Shortword pswFiltOut[])
-{
-
-/*_________________________________________________________________________
- |                                                                         |
- |                            Automatic Variables                          |
- |_________________________________________________________________________|
-*/
-
-  Longword L_Sum;
-  short int siStage,
-         siSmp;
-
-/*_________________________________________________________________________
- |                                                                         |
- |                              Executable Code                            |
- |_________________________________________________________________________|
-*/
-
-  /* filter 1st sample */
-  /* ----------------- */
-
-  /* sum past state outputs */
-  /* ---------------------- */
-  /* 0th coef, with rounding */
-  L_Sum = L_msu(LPC_ROUND, pswState[0], pswCoef[0]);
-
-  for (siStage = 1; siStage < NP; siStage++)
-  {                                    /* remaining coefs */
-    L_Sum = L_msu(L_Sum, pswState[siStage], pswCoef[siStage]);
-  }
-
-  /* scale output */
-  /* ------------ */
-
-  L_Sum = L_shl(L_Sum, ASHIFT);
-
-  /* save 1st output sample */
-  /* ---------------------- */
-
-  pswFiltOut[0] = extract_h(L_Sum);
-
-  /* filter remaining samples */
-  /* ------------------------ */
-
-  for (siSmp = 1; siSmp < S_LEN; siSmp++)
-  {
-
-    /* sum past outputs */
-    /* ---------------- */
-    /* 0th coef, with rounding */
-    L_Sum = L_msu(LPC_ROUND, pswFiltOut[siSmp - 1], pswCoef[0]);
-    /* remaining coefs */
-    for (siStage = 1; ((0 < (siSmp - siStage)) && siStage < NP); siStage++)
-    {
-      L_Sum = L_msu(L_Sum, pswFiltOut[siSmp - siStage - 1],
-                    pswCoef[siStage]);
-    }
-
-    /* sum past states, if any */
-    /* ----------------------- */
-
-    for (siStage = siSmp; siStage < NP; siStage++)
-    {
-      L_Sum = L_msu(L_Sum, pswState[siStage - siSmp], pswCoef[siStage]);
-    }
-
-    /* scale output */
-    /* ------------ */
-
-    L_Sum = L_shl(L_Sum, ASHIFT);
-
-    /* save current output sample */
-    /* -------------------------- */
-
-    pswFiltOut[siSmp] = extract_h(L_Sum);
-  }
-}
-
-/***************************************************************************
- *
- *   FUNCTION NAME: lpcZsFir
- *
- *   PURPOSE:
- *     The purpose of this function is to perform direct form fir filtering
- *     with zero state, assuming a NP order filter and given coefficients
- *     and non-zero input.
- *
- *   INPUTS:
- *
- *     NP
- *                     order of the lpc filter
- *
- *     S_LEN
- *                     number of samples to filter
- *
- *     pswInput[0:S_LEN-1]
- *
- *                     input array of points to be filtered.
- *                     pswInput[0] is the oldest point (first to be filtered)
- *                     pswInput[siLen-1] is the last point filtered (newest)
- *
- *     pswCoef[0:NP-1]
- *
- *                     array of direct form coefficients
- *                     pswCoef[0] = coeff for delay n = -1
- *                     pswCoef[NP-1] = coeff for delay n = -NP
- *
- *     ASHIFT
- *                     number of shifts input A's have been shifted down by
- *
- *     LPC_ROUND
- *                     rounding constant
- *
- *   OUTPUTS:
- *
- *     pswFiltOut[0:S_LEN-1]
- *
- *                     the filtered output
- *                     same format as pswInput, pswFiltOut[0] is oldest point
- *
- *   RETURN VALUE:
- *
- *     none
- *
- *   DESCRIPTION:
- *
- *     This routine is used in getNWCoefs().  See section 4.1.7.
- *
- *     because of the default sign of the coefficients the
- *     formula for the filter is :
- *     i=0, i < S_LEN
- *        out[i] = rounded(state[i]*coef[0])
- *        j=1, j < NP
- *           out[i] += state[j]*coef[j] (state taken from in[])
- *        rescale(out[i])
- *        out[i] += in[i]
- *
- *   REFERENCES: Sub-clause 4.1.7 of GSM Recomendation 06.20
- *
- *   KEYWORDS: lpc, directform, fir, lpcFir, inversefilter, lpcFilt
- *   KEYWORDS: dirForm, dir_mod, dir_clr, dir_neg, dir_set, i_dir_mod
- *
- *************************************************************************/
-
-void   lpcZsFir(Shortword pswInput[], Shortword pswCoef[],
-                       Shortword pswFiltOut[])
-{
-
-/*_________________________________________________________________________
- |                                                                         |
- |                            Automatic Variables                          |
- |_________________________________________________________________________|
-*/
-
-  Longword L_Sum;
-  short int siStage,
-         siSmp;
-
-/*_________________________________________________________________________
- |                                                                         |
- |                              Executable Code                            |
- |_________________________________________________________________________|
-*/
-
-  /* output 1st sample */
-  /* ----------------- */
-
-  pswFiltOut[0] = pswInput[0];
-
-  /* filter remaining samples */
-  /* ------------------------ */
-
-  for (siSmp = 1; siSmp < S_LEN; siSmp++)
-  {
-
-    /* sum past outputs */
-    /* ---------------- */
-    /* 0th coef, with rounding */
-    L_Sum = L_mac(LPC_ROUND, pswInput[siSmp - 1], pswCoef[0]);
-    /* remaining coefs */
-    for (siStage = 1; ((0 < (siSmp - siStage)) && siStage < NP); siStage++)
-    {
-      L_Sum = L_mac(L_Sum, pswInput[siSmp - siStage - 1],
-                    pswCoef[siStage]);
-    }
-
-    /* add input to partial output */
-    /* --------------------------- */
-
-    L_Sum = L_shl(L_Sum, ASHIFT);
-    L_Sum = L_msu(L_Sum, pswInput[siSmp], 0x8000);
-
-    /* save current output sample */
-    /* -------------------------- */
-
-    pswFiltOut[siSmp] = extract_h(L_Sum);
-  }
-}
-
-/***************************************************************************
- *
- *   FUNCTION NAME: lpcZsIir
- *
- *   PURPOSE:
- *
- *     The purpose of this function is to perform direct form IIR filtering
- *     with zero state, assuming a NP order filter and given coefficients
- *     and non-zero input.
- *
- *   INPUTS:
- *
- *     NP
- *                     order of the lpc filter
- *
- *     S_LEN
- *                     number of samples to filter
- *
- *     pswInput[0:S_LEN-1]
- *
- *                     input array of points to be filtered
- *                     pswInput[0] is the oldest point (first to be filtered)
- *                     pswInput[siLen-1] is the last point filtered (newest)
- *
- *     pswCoef[0:NP-1]
- *                     array of direct form coefficients
- *                     pswCoef[0] = coeff for delay n = -1
- *                     pswCoef[NP-1] = coeff for delay n = -NP
- *
- *     ASHIFT
- *                     number of shifts input A's have been shifted down by
- *
- *     LPC_ROUND
- *                     rounding constant
- *
- *   OUTPUTS:
- *
- *     pswFiltOut[0:S_LEN-1]
- *
- *                     the filtered output
- *                     same format as pswInput, pswFiltOut[0] is oldest point
- *
- *   RETURN VALUE:
- *
- *     none
- *
- *   DESCRIPTION:
- *
- *     This routine is used in the subframe analysis process.  It is
- *     called by sfrmAnalysis() and fnClosedLoop().  It is this function
- *     which performs the weighting of the excitation vectors.
- *
- *     because of the default sign of the coefficients the
- *     formula for the filter is :
- *     i=0, i < S_LEN
- *        out[i] = rounded(state[i]*coef[0])
- *        j=1, j < NP
- *           out[i] -= state[j]*coef[j] (state taken from prior out[])
- *        rescale(out[i])
- *        out[i] += in[i]
- *
- *   REFERENCES: Sub-clause 4.1.8.5 of GSM Recomendation 06.20
- *
- *   KEYWORDS: lpc, directform, iir, synthesisfilter, lpcFilt
- *   KEYWORDS: dirForm, dir_mod, dir_clr, dir_neg, dir_set
- *
- *************************************************************************/
-
-void   lpcZsIir(Shortword pswInput[], Shortword pswCoef[],
-                       Shortword pswFiltOut[])
-{
-
-/*_________________________________________________________________________
- |                                                                         |
- |                            Automatic Variables                          |
- |_________________________________________________________________________|
-*/
-
-  Longword L_Sum;
-  short int siStage,
-         siSmp;
-
-/*_________________________________________________________________________
- |                                                                         |
- |                              Executable Code                            |
- |_________________________________________________________________________|
-*/
-
-  /* output 1st sample */
-  /* ----------------- */
-
-  pswFiltOut[0] = pswInput[0];
-
-  /* filter remaining samples */
-  /* ------------------------ */
-
-  for (siSmp = 1; siSmp < S_LEN; siSmp++)
-  {
-
-    /* sum past outputs */
-    /* ---------------- */
-    /* 0th coef, with rounding */
-    L_Sum = L_msu(LPC_ROUND, pswFiltOut[siSmp - 1], pswCoef[0]);
-    /* remaining coefs */
-    for (siStage = 1; ((0 < (siSmp - siStage)) && siStage < NP); siStage++)
-    {
-      L_Sum = L_msu(L_Sum, pswFiltOut[siSmp - siStage - 1],
-                    pswCoef[siStage]);
-    }
-
-    /* add input to partial output */
-    /* --------------------------- */
-
-    L_Sum = L_shl(L_Sum, ASHIFT);
-    L_Sum = L_msu(L_Sum, pswInput[siSmp], 0x8000);
-
-    /* save current output sample */
-    /* -------------------------- */
-
-    pswFiltOut[siSmp] = extract_h(L_Sum);
-  }
-}
-
-/***************************************************************************
- *
- *   FUNCTION NAME: lpcZsIirP
- *
- *   PURPOSE:
- *
- *     The purpose of this function is to perform direct form iir filtering
- *     with zero state, assuming a NP order filter and given coefficients
- *     and input
- *
- *   INPUTS:
- *
- *     NP
- *                     order of the lpc filter
- *
- *     S_LEN
- *                     number of samples to filter
- *
- *     pswCommonIO[0:S_LEN-1]
- *
- *                     input array of points to be filtered
- *                     pswCommonIO[0] is oldest point (first to be filtered)
- *                     pswCommonIO[siLen-1] is last point filtered (newest)
- *
- *     pswCoef[0:NP-1]
- *                     array of direct form coefficients
- *                     pswCoef[0] = coeff for delay n = -1
- *                     pswCoef[NP-1] = coeff for delay n = -NP
- *
- *     ASHIFT
- *                     number of shifts input A's have been shifted down by
- *
- *     LPC_ROUND
- *                     rounding constant
- *
- *   OUTPUTS:
- *
- *     pswCommonIO[0:S_LEN-1]
- *
- *                     the filtered output
- *                     pswCommonIO[0] is oldest point
- *
- *   RETURN VALUE:
- *
- *     none
- *
- *   DESCRIPTION:
- *
- *     This function is called by geNWCoefs().  See section 4.1.7.
- *
- *     because of the default sign of the coefficients the
- *     formula for the filter is :
- *     i=0, i < S_LEN
- *        out[i] = rounded(state[i]*coef[0])
- *        j=1, j < NP
- *           out[i] += state[j]*coef[j] (state taken from prior out[])
- *        rescale(out[i])
- *        out[i] += in[i]
- *
- *   REFERENCES: Sub-clause 4.1.7 of GSM Recomendation 06.20
- *
- *   KEYWORDS: lpc, directform, iir, synthesisfilter, lpcFilt
- *   KEYWORDS: dirForm, dir_mod, dir_clr, dir_neg, dir_set
- *
- *************************************************************************/
-
-void   lpcZsIirP(Shortword pswCommonIO[], Shortword pswCoef[])
-{
-
-/*_________________________________________________________________________
- |                                                                         |
- |                            Automatic Variables                          |
- |_________________________________________________________________________|
-*/
-
-  Longword L_Sum;
-  short int siStage,
-         siSmp;
-
-/*_________________________________________________________________________
- |                                                                         |
- |                              Executable Code                            |
- |_________________________________________________________________________|
-*/
-
-  /* filter remaining samples */
-  /* ------------------------ */
-
-  for (siSmp = 1; siSmp < S_LEN; siSmp++)
-  {
-
-    /* sum past outputs */
-    /* ---------------- */
-    /* 0th coef, with rounding */
-    L_Sum = L_mac(LPC_ROUND, pswCommonIO[siSmp - 1], pswCoef[0]);
-    /* remaining coefs */
-    for (siStage = 1; ((0 < (siSmp - siStage)) && siStage < NP); siStage++)
-    {
-      L_Sum = L_mac(L_Sum, pswCommonIO[siSmp - siStage - 1],
-                    pswCoef[siStage]);
-    }
-
-    /* add input to partial output */
-    /* --------------------------- */
-
-    L_Sum = L_shl(L_Sum, ASHIFT);
-    L_Sum = L_msu(L_Sum, pswCommonIO[siSmp], 0x8000);
-
-    /* save current output sample */
-    /* -------------------------- */
-
-    pswCommonIO[siSmp] = extract_h(L_Sum);
-  }
-}
-
 /**************************************************************************
  *
  *   FUNCTION NAME: pitchPreFilt
@@ -3402,903 +1173,6 @@
 
 /***************************************************************************
  *
- *   FUNCTION NAME: r0BasedEnergyShft
- *
- *   PURPOSE:
- *
- *     Given an R0 voicing level, find the number of shifts to be
- *     performed on the energy to ensure that the subframe energy does
- *     not overflow.  example if energy can maximally take the value
- *     4.0, then 2 shifts are required.
- *
- *   INPUTS:
- *
- *     swR0Index
- *                     R0 codeword (0-0x1f)
- *
- *   OUTPUTS:
- *
- *     none
- *
- *   RETURN VALUE:
- *
- *     swShiftDownSignal
- *
- *                    number of right shifts to apply to energy (0..6)
- *
- *   DESCRIPTION:
- *
- *     Based on the R0, the average frame energy, we can get an
- *     upper bound on the energy any one subframe can take on.
- *     Using this upper bound we can calculate what right shift is
- *     needed to ensure an unsaturated output out of a subframe
- *     energy calculation (g_corr).
- *
- *   REFERENCES: Sub-clause 4.1.9 and 4.2.1 of GSM Recomendation 06.20
- *
- *   KEYWORDS: spectral postfilter
- *
- *************************************************************************/
-
-Shortword r0BasedEnergyShft(Shortword swR0Index)
-{
-
-/*_________________________________________________________________________
- |                                                                         |
- |                            Automatic Variables                          |
- |_________________________________________________________________________|
-*/
-
-  Shortword swShiftDownSignal;
-
-/*_________________________________________________________________________
- |                                                                         |
- |                              Executable Code                            |
- |_________________________________________________________________________|
-*/
-
-  if (sub(swR0Index, 26) <= 0)
-  {
-    if (sub(swR0Index, 23) <= 0)
-    {
-      if (sub(swR0Index, 21) <= 0)
-        swShiftDownSignal = 0;         /* r0  [0,  21] */
-      else
-        swShiftDownSignal = 1;         /* r0  [22, 23] */
-    }
-    else
-    {
-      if (sub(swR0Index, 24) <= 0)
-        swShiftDownSignal = 2;         /* r0  [23, 24] */
-      else
-        swShiftDownSignal = 3;         /* r0  [24, 26] */
-    }
-  }
-  else
-  {                                    /* r0 index > 26 */
-    if (sub(swR0Index, 28) <= 0)
-    {
-      swShiftDownSignal = 4;           /* r0  [26, 28] */
-    }
-    else
-    {
-      if (sub(swR0Index, 29) <= 0)
-        swShiftDownSignal = 5;         /* r0  [28, 29] */
-      else
-        swShiftDownSignal = 6;         /* r0  [29, 31] */
-    }
-  }
-  if (sub(swR0Index, 18) > 0)
-    swShiftDownSignal = add(swShiftDownSignal, 2);
-
-  return (swShiftDownSignal);
-}
-
-/***************************************************************************
- *
- *   FUNCTION NAME: rcToADp
- *
- *   PURPOSE:
- *
- *     This subroutine computes a vector of direct form LPC filter
- *     coefficients, given an input vector of reflection coefficients.
- *     Double precision is used internally, but 16 bit direct form
- *     filter coefficients are returned.
- *
- *   INPUTS:
- *
- *     NP
- *                     order of the LPC filter (global constant)
- *
- *     swAscale
- *                     The multiplier which scales down the direct form
- *                     filter coefficients.
- *
- *     pswRc[0:NP-1]
- *                     The input vector of reflection coefficients.
- *
- *   OUTPUTS:
- *
- *     pswA[0:NP-1]
- *                     Array containing the scaled down direct form LPC
- *                     filter coefficients.
- *
- *   RETURN VALUE:
- *
- *     siLimit
- *                     1 if limiting occured in computation, 0 otherwise.
- *
- *   DESCRIPTION:
- *
- *     This function performs the conversion from reflection coefficients
- *     to direct form LPC filter coefficients. The direct form coefficients
- *     are scaled by multiplication by swAscale. NP, the filter order is 10.
- *     The a's and rc's each have NP elements in them. Double precision
- *     calculations are used internally.
- *
- *        The equations are:
- *        for i = 0 to NP-1{
- *
- *          a(i)(i) = rc(i)              (scaling by swAscale occurs here)
- *
- *          for j = 0 to i-1
- *             a(i)(j) = a(i-1)(j) + rc(i)*a(i-1)(i-j-1)
- *       }
- *
- *     See page 443, of
- *     "Digital Processing of Speech Signals" by L.R. Rabiner and R.W.
- *     Schafer; Prentice-Hall; Englewood Cliffs, NJ (USA).  1978.
- *
- *   REFERENCES: Sub-clause 4.1.7 and 4.2.3 of GSM Recomendation 06.20
- *
- *  KEYWORDS: reflectioncoefficients, parcors, conversion, rctoadp, ks, as
- *  KEYWORDS: parcorcoefficients, lpc, flat, vectorquantization
- *
- *************************************************************************/
-
-short  rcToADp(Shortword swAscale, Shortword pswRc[],
-                      Shortword pswA[])
-{
-
-/*_________________________________________________________________________
- |                                                                         |
- |                            Automatic Variables                          |
- |_________________________________________________________________________|
-*/
-
-  Longword pL_ASpace[NP],
-         pL_tmpSpace[NP],
-         L_temp,
-        *pL_A,
-        *pL_tmp,
-        *pL_swap;
-
-  short int i,
-         j,                            /* loop counters */
-         siLimit;
-
-/*_________________________________________________________________________
- |                                                                         |
- |                              Executable Code                            |
- |_________________________________________________________________________|
-*/
-
-  /* Initialize starting addresses for temporary buffers */
-  /*-----------------------------------------------------*/
-
-  pL_A = pL_ASpace;
-  pL_tmp = pL_tmpSpace;
-
-  /* Initialize the flag for checking if limiting has occured */
-  /*----------------------------------------------------------*/
-
-  siLimit = 0;
-
-  /* Compute direct form filter coefficients, pswA[0],...,pswA[9] */
-  /*-------------------------------------------------------------------*/
-
-  for (i = 0; i < NP; i++)
-  {
-
-    pL_tmp[i] = L_mult(swAscale, pswRc[i]);
-    for (j = 0; j <= i - 1; j++)
-    {
-      L_temp = L_mpy_ls(pL_A[i - j - 1], pswRc[i]);
-      pL_tmp[j] = L_add(L_temp, pL_A[j]);
-      siLimit |= isLwLimit(pL_tmp[j]);
-    }
-    if (i != NP - 1)
-    {
-      /* Swap swA and swTmp buffers */
-
-      pL_swap = pL_tmp;
-      pL_tmp = pL_A;
-      pL_A = pL_swap;
-    }
-  }
-
-  for (i = 0; i < NP; i++)
-  {
-    pswA[i] = round(pL_tmp[i]);
-    siLimit |= isSwLimit(pswA[i]);
-  }
-  return (siLimit);
-}
-
-/***************************************************************************
- *
- *   FUNCTION NAME: rcToCorrDpL
- *
- *   PURPOSE:
- *
- *     This subroutine computes an autocorrelation vector, given a vector
- *     of reflection coefficients as an input. Double precision calculations
- *     are used internally, and a double precision (Longword)
- *     autocorrelation sequence is returned.
- *
- *   INPUTS:
- *
- *     NP
- *                     LPC filter order passed in as a global constant.
- *
- *     swAshift
- *                     Number of right shifts to be applied to the
- *                     direct form filter coefficients being computed
- *                     as an intermediate step to generating the
- *                     autocorrelation sequence.
- *
- *     swAscale
- *                     A multiplicative scale factor corresponding to
- *                     swAshift; i.e. swAscale = 2 ^(-swAshift).
- *
- *     pswRc[0:NP-1]
- *                     An input vector of reflection coefficients.
- *
- *   OUTPUTS:
- *
- *     pL_R[0:NP]
- *                     An output Longword array containing the
- *                     autocorrelation vector where
- *                     pL_R[0] = 0x7fffffff; (i.e., ~1.0).
- *
- *   RETURN VALUE:
- *
- *     none
- *
- *   DESCRIPTION:
- *
- *     The algorithm used for computing the correlation sequence is
- *     described on page 232 of the book "Linear Prediction of Speech",
- *     by J.D.  Markel and A.H. Gray, Jr.; Springer-Verlag, Berlin,
- *     Heidelberg, New York, 1976.
- *
- *   REFERENCES: Sub_Clause 4.1.4 and 4.2.1  of GSM Recomendation 06.20
- *
- *   KEYWORDS: normalized autocorrelation, reflection coefficients
- *   KEYWORDS: conversion
- *
- **************************************************************************/
-
-void   rcToCorrDpL(Shortword swAshift, Shortword swAscale,
-                          Shortword pswRc[], Longword pL_R[])
-{
-
-/*_________________________________________________________________________
- |                                                                         |
- |                            Automatic Variables                          |
- |_________________________________________________________________________|
-*/
-
-  Longword pL_ASpace[NP],
-         pL_tmpSpace[NP],
-         L_temp,
-         L_sum,
-        *pL_A,
-        *pL_tmp,
-        *pL_swap;
-
-  short int i,
-         j;                            /* loop control variables */
-
-/*_________________________________________________________________________
- |                                                                         |
- |                              Executable Code                            |
- |_________________________________________________________________________|
-*/
-
-  /* Set R[0] = 0x7fffffff, (i.e., R[0] = 1.0) */
-  /*-------------------------------------------*/
-
-  pL_R[0] = LW_MAX;
-
-  /* Assign an address onto each of the two temporary buffers */
-  /*----------------------------------------------------------*/
-
-  pL_A = pL_ASpace;
-  pL_tmp = pL_tmpSpace;
-
-  /* Compute correlations R[1],...,R[10] */
-  /*------------------------------------*/
-
-  for (i = 0; i < NP; i++)
-  {
-
-    /* Compute, as an intermediate step, the filter coefficients for */
-    /* for an i-th order direct form filter (pL_tmp[j],j=0,i)        */
-    /*---------------------------------------------------------------*/
-
-    pL_tmp[i] = L_mult(swAscale, pswRc[i]);
-    for (j = 0; j <= i - 1; j++)
-    {
-      L_temp = L_mpy_ls(pL_A[i - j - 1], pswRc[i]);
-      pL_tmp[j] = L_add(L_temp, pL_A[j]);
-    }
-
-    /* Swap pL_A and pL_tmp buffers */
-    /*------------------------------*/
-
-    pL_swap = pL_A;
-    pL_A = pL_tmp;
-    pL_tmp = pL_swap;
-
-    /* Given the direct form filter coefficients for an i-th order filter  */
-    /* and the autocorrelation vector computed up to and including stage i */
-    /* compute the autocorrelation coefficient R[i+1]                      */
-    /*---------------------------------------------------------------------*/
-
-    L_temp = L_mpy_ll(pL_A[0], pL_R[i]);
-    L_sum = L_negate(L_temp);
-
-    for (j = 1; j <= i; j++)
-    {
-      L_temp = L_mpy_ll(pL_A[j], pL_R[i - j]);
-      L_sum = L_sub(L_sum, L_temp);
-    }
-    pL_R[i + 1] = L_shl(L_sum, swAshift);
-
-  }
-}
-
-/***************************************************************************
- *
- *   FUNCTION NAME: res_eng
- *
- *   PURPOSE:
- *
- *     Calculates square root of subframe residual energy estimate:
- *
- *                     sqrt( R(0)(1-k1**2)...(1-k10**2) )
- *
- *   INPUTS:
- *
- *     pswReflecCoefIn[0:9]
- *
- *                     Array of reflection coeffcients.
- *
- *     swRq
- *
- *                     Subframe energy = sqrt(frame_energy * S_LEN/2**S_SH)
- *                     (quantized).
- *
- *   OUTPUTS:
- *
- *     psnsSqrtRsOut
- *
- *                     (Pointer to) the output residual energy estimate.
- *
- *   RETURN VALUE:
- *
- *     The shift count of the normalized residual energy estimate, as int.
- *
- *   DESCRIPTION:
- *
- *     First, the canonic product of the (1-ki**2) terms is calculated
- *     (normalizations are done to maintain precision).  Also, a factor of
- *     2**S_SH is applied to the product to offset this same factor in the
- *     quantized square root of the subframe energy.
- *
- *     Then the product is square-rooted, and multiplied by the quantized
- *     square root of the subframe energy.  This combined product is put
- *     out as a normalized fraction and shift count (mantissa and exponent).
- *
- *   REFERENCES: Sub-clause 4.1.7 and 4.2.1 of GSM Recomendation 06.20
- *
- *   KEYWORDS: residualenergy, res_eng, rs
- *
- *************************************************************************/
-
-void   res_eng(Shortword pswReflecCoefIn[], Shortword swRq,
-                      struct NormSw *psnsSqrtRsOut)
-{
-/*_________________________________________________________________________
- |                                                                         |
- |                              Local Constants                            |
- |_________________________________________________________________________|
-*/
-
-#define  S_SH          6               /* ceiling(log2(S_LEN)) */
-#define  MINUS_S_SH    -S_SH
-
-
-/*_________________________________________________________________________
- |                                                                         |
- |                            Automatic Variables                          |
- |_________________________________________________________________________|
-*/
-
-  Longword L_Product,
-         L_Shift,
-         L_SqrtResEng;
-
-  Shortword swPartialProduct,
-         swPartialProductShift,
-         swTerm,
-         swShift,
-         swSqrtPP,
-         swSqrtPPShift,
-         swSqrtResEng,
-         swSqrtResEngShift;
-
-  short int i;
-
-/*_________________________________________________________________________
- |                                                                         |
- |                              Executable Code                            |
- |_________________________________________________________________________|
-*/
-
-  /* Form canonic product, maintain precision and shift count */
-  /*----------------------------------------------------------*/
-
-  /* (Start off with unity product (actually -1), and shift offset) */
-  /*----------------------------------------------------------------*/
-  swPartialProduct = SW_MIN;
-  swPartialProductShift = MINUS_S_SH;
-
-  for (i = 0; i < NP; i++)
-  {
-
-    /* Get next (-1 + k**2) term, form partial canonic product */
-    /*---------------------------------------------------------*/
-
-
-    swTerm = mac_r(LW_MIN, pswReflecCoefIn[i], pswReflecCoefIn[i]);
-
-    L_Product = L_mult(swTerm, swPartialProduct);
-
-    /* Normalize partial product, round */
-    /*----------------------------------*/
-
-    swShift = norm_s(extract_h(L_Product));
-    swPartialProduct = round(L_shl(L_Product, swShift));
-    swPartialProductShift = add(swPartialProductShift, swShift);
-  }
-
-  /* Correct sign of product, take square root */
-  /*-------------------------------------------*/
-
-  swPartialProduct = abs_s(swPartialProduct);
-
-  swSqrtPP = sqroot(L_deposit_h(swPartialProduct));
-
-  L_Shift = L_shr(L_deposit_h(swPartialProductShift), 1);
-
-  swSqrtPPShift = extract_h(L_Shift);
-
-  if (extract_l(L_Shift) != 0)
-  {
-
-    /* Odd exponent: shr above needs to be compensated by multiplying */
-    /* mantissa by sqrt(0.5)                                          */
-    /*----------------------------------------------------------------*/
-
-    swSqrtPP = mult_r(swSqrtPP, SQRT_ONEHALF);
-  }
-
-  /* Form final product, the residual energy estimate, and do final */
-  /* normalization                                                  */
-  /*----------------------------------------------------------------*/
-
-  L_SqrtResEng = L_mult(swRq, swSqrtPP);
-
-  swShift = norm_l(L_SqrtResEng);
-  swSqrtResEng = round(L_shl(L_SqrtResEng, swShift));
-  swSqrtResEngShift = add(swSqrtPPShift, swShift);
-
-  /* Return */
-  /*--------*/
-  psnsSqrtRsOut->man = swSqrtResEng;
-  psnsSqrtRsOut->sh = swSqrtResEngShift;
-
-  return;
-}
-
-/***************************************************************************
- *
- *   FUNCTION NAME: rs_rr
- *
- *   PURPOSE:
- *
- *     Calculates sqrt(RS/R(x,x)) using floating point format,
- *     where RS is the approximate residual energy in a given
- *     subframe and R(x,x) is the power in each long term
- *     predictor vector or in each codevector.
- *     Used in the joint optimization of the gain and the long
- *     term predictor coefficient.
- *
- *   INPUTS:
- *
- *     pswExcitation[0:39] - excitation signal array
- *     snsSqrtRs - structure sqrt(RS) normalized with mantissa and shift
- *
- *   OUTPUTS:
- *
- *     snsSqrtRsRr - structure sqrt(RS/R(x,x)) with mantissa and shift
- *
- *   RETURN VALUE:
- *
- *     None
- *
- *   DESCRIPTION:
- *
- *     Implemented as sqrt(RS)/sqrt(R(x,x)) where both sqrts
- *     are stored normalized (0.5<=x<1.0) and the associated
- *     shift.  See section 4.1.11.1 for details
- *
- *   REFERENCES: Sub-clause 4.1.11.1 and 4.2.1 of GSM
- *               Recomendation 06.20
- *
- *   KEYWORDS: rs_rr, sqroot
- *
- *************************************************************************/
-
-void   rs_rr(Shortword pswExcitation[], struct NormSw snsSqrtRs,
-                    struct NormSw *snsSqrtRsRr)
-{
-
-/*_________________________________________________________________________
- |                                                                         |
- |                            Automatic Variables                          |
- |_________________________________________________________________________|
-*/
-  Longword L_Temp;
-  Shortword swTemp,
-         swTemp2,
-         swEnergy,
-         swNormShift,
-         swShift;
-
-/*_________________________________________________________________________
- |                                                                         |
- |                              Executable Code                            |
- |_________________________________________________________________________|
-*/
-
-  swEnergy = sub(shl(snsSqrtRs.sh, 1), 3);      /* shift*2 + margin ==
-                                                 * energy. */
-
-
-  if (swEnergy < 0)
-  {
-
-    /* High-energy residual: scale input vector during energy */
-    /* calculation. The shift count of the energy of the      */
-    /* residual estimate is used as an estimate of the shift  */
-    /* count needed for the excitation energy                 */
-    /*--------------------------------------------------------*/
-
-    swNormShift = g_corr1s(pswExcitation, negate(swEnergy), &L_Temp);
-
-  }
-  else
-  {
-
-    /* Lower-energy residual: no overflow protection needed */
-    /*------------------------------------------------------*/
-
-    swNormShift = g_corr1(pswExcitation, &L_Temp);
-  }
-
-  /* Compute single precision square root of energy sqrt(R(x,x)) */
-  /* ----------------------------------------------------------- */
-  swTemp = sqroot(L_Temp);
-
-  /* If odd no. of shifts compensate by sqrt(0.5) */
-  /* -------------------------------------------- */
-  if (swNormShift & 1)
-  {
-
-    /* Decrement no. of shifts in accordance with sqrt(0.5) */
-    /* ---------------------------------------------------- */
-    swNormShift = sub(swNormShift, 1);
-
-    /* sqrt(R(x,x) = sqrt(R(x,x)) * sqrt(0.5) */
-    /* -------------------------------------- */
-    L_Temp = L_mult(0x5a82, swTemp);
-  }
-  else
-  {
-    L_Temp = L_deposit_h(swTemp);
-  }
-
-  /* Normalize again and update shifts */
-  /* --------------------------------- */
-  swShift = norm_l(L_Temp);
-  swNormShift = add(shr(swNormShift, 1), swShift);
-  L_Temp = L_shl(L_Temp, swShift);
-
-  /* Shift sqrt(RS) to make sure less than divisor */
-  /* --------------------------------------------- */
-  swTemp = shr(snsSqrtRs.man, 1);
-
-  /* Divide sqrt(RS)/sqrt(R(x,x)) */
-  /* ---------------------------- */
-  swTemp2 = divide_s(swTemp, round(L_Temp));
-
-  /* Calculate shift for division, compensate for shift before division */
-  /* ------------------------------------------------------------------ */
-  swNormShift = sub(snsSqrtRs.sh, swNormShift);
-  swNormShift = sub(swNormShift, 1);
-
-  /* Normalize and get no. of shifts */
-  /* ------------------------------- */
-  swShift = norm_s(swTemp2);
-  snsSqrtRsRr->sh = add(swNormShift, swShift);
-  snsSqrtRsRr->man = shl(swTemp2, swShift);
-
-}
-
-/***************************************************************************
- *
- *   FUNCTION NAME: rs_rrNs
- *
- *   PURPOSE:
- *
- *     Calculates sqrt(RS/R(x,x)) using floating point format,
- *     where RS is the approximate residual energy in a given
- *     subframe and R(x,x) is the power in each long term
- *     predictor vector or in each codevector.
- *
- *     Used in the joint optimization of the gain and the long
- *     term predictor coefficient.
- *
- *   INPUTS:
- *
- *     pswExcitation[0:39] - excitation signal array
- *     snsSqrtRs - structure sqrt(RS) normalized with mantissa and shift
- *
- *   OUTPUTS:
- *
- *     snsSqrtRsRr - structure sqrt(RS/R(x,x)) with mantissa and shift
- *
- *   RETURN VALUE:
- *
- *     None
- *
- *   DESCRIPTION:
- *
- *     Implemented as sqrt(RS)/sqrt(R(x,x)) where both sqrts
- *     are stored normalized (0.5<=x<1.0) and the associated
- *     shift.
- *
- *   REFERENCES: Sub-clause 4.1.11.1 and 4.2.1 of GSM
- *               Recomendation 06.20
- *
- *   KEYWORDS: rs_rr, sqroot
- *
- *************************************************************************/
-
-void   rs_rrNs(Shortword pswExcitation[], struct NormSw snsSqrtRs,
-                      struct NormSw *snsSqrtRsRr)
-{
-
-/*_________________________________________________________________________
- |                                                                         |
- |                            Automatic Variables                          |
- |_________________________________________________________________________|
-*/
-  Longword L_Temp;
-  Shortword swTemp,
-         swTemp2,
-         swNormShift,
-         swShift;
-
-/*_________________________________________________________________________
- |                                                                         |
- |                              Executable Code                            |
- |_________________________________________________________________________|
-*/
-
-  /* Lower-energy residual: no overflow protection needed */
-  /*------------------------------------------------------*/
-
-  swNormShift = g_corr1(pswExcitation, &L_Temp);
-
-
-  /* Compute single precision square root of energy sqrt(R(x,x)) */
-  /* ----------------------------------------------------------- */
-  swTemp = sqroot(L_Temp);
-
-  /* If odd no. of shifts compensate by sqrt(0.5) */
-  /* -------------------------------------------- */
-  if (swNormShift & 1)
-  {
-
-    /* Decrement no. of shifts in accordance with sqrt(0.5) */
-    /* ---------------------------------------------------- */
-    swNormShift = sub(swNormShift, 1);
-
-    /* sqrt(R(x,x) = sqrt(R(x,x)) * sqrt(0.5) */
-    /* -------------------------------------- */
-    L_Temp = L_mult(0x5a82, swTemp);
-  }
-  else
-  {
-    L_Temp = L_deposit_h(swTemp);
-  }
-
-  /* Normalize again and update shifts */
-  /* --------------------------------- */
-
-  swShift = norm_l(L_Temp);
-  swNormShift = add(shr(swNormShift, 1), swShift);
-  L_Temp = L_shl(L_Temp, swShift);
-
-  /* Shift sqrt(RS) to make sure less than divisor */
-  /* --------------------------------------------- */
-  swTemp = shr(snsSqrtRs.man, 1);
-
-  /* Divide sqrt(RS)/sqrt(R(x,x)) */
-  /* ---------------------------- */
-  swTemp2 = divide_s(swTemp, round(L_Temp));
-
-  /* Calculate shift for division, compensate for shift before division */
-  /* ------------------------------------------------------------------ */
-  swNormShift = sub(snsSqrtRs.sh, swNormShift);
-  swNormShift = sub(swNormShift, 1);
-
-  /* Normalize and get no. of shifts */
-  /* ------------------------------- */
-  swShift = norm_s(swTemp2);
-  snsSqrtRsRr->sh = add(swNormShift, swShift);
-  snsSqrtRsRr->man = shl(swTemp2, swShift);
-
-}
-
-
-/***************************************************************************
- *
- *   FUNCTION NAME: scaleExcite
- *
- *   PURPOSE:
- *
- *     Scale an arbitrary excitation vector (codevector or
- *     pitch vector)
- *
- *   INPUTS:
- *
- *     pswVect[0:39] - the unscaled vector.
- *     iGsp0Scale - an positive offset to compensate for the fact
- *                  that GSP0 table is scaled down.
- *     swErrTerm - rather than a gain being passed in, (beta, gamma)
- *                 it is calculated from this error term - either
- *                 Gsp0[][][0] error term A or Gsp0[][][1] error
- *                 term B. Beta is calculated from error term A,
- *                 gamma from error term B.
- *     snsRS - the RS_xx appropriate to pswVect.
- *
- *   OUTPUTS:
- *
- *      pswScldVect[0:39] - the output, scaled excitation vector.
- *
- *   RETURN VALUE:
- *
- *     swGain - One of two things.  Either a clamped value of 0x7fff if the
- *              gain's shift was > 0 or the rounded vector gain otherwise.
- *
- *   DESCRIPTION:
- *
- *     If gain > 1.0 then
- *         (do not shift gain up yet)
- *         partially scale vector element THEN shift and round save
- *      else
- *         shift gain correctly
- *         scale vector element and round save
- *         update state array
- *
- *   REFERENCES: Sub-clause 4.1.10.2 and 4.2.1 of GSM
- *               Recomendation 06.20
- *
- *   KEYWORDS: excite_vl, sc_ex, excitevl, scaleexcite, codevector, p_vec,
- *   KEYWORDS: x_vec, pitchvector, gain, gsp0
- *
- *************************************************************************/
-
-Shortword scaleExcite(Shortword pswVect[],
-                             Shortword swErrTerm, struct NormSw snsRS,
-                             Shortword pswScldVect[])
-{
-
-/*_________________________________________________________________________
- |                                                                         |
- |                            Automatic Variables                          |
- |_________________________________________________________________________|
-*/
-  Longword L_GainUs,
-         L_scaled,
-         L_Round_off;
-  Shortword swGain,
-         swGainUs,
-         swGainShift,
-         i,
-         swGainUsShft;
-
-/*_________________________________________________________________________
- |                                                                         |
- |                              Executable Code                            |
- |_________________________________________________________________________|
-*/
-
-
-  L_GainUs = L_mult(swErrTerm, snsRS.man);
-  swGainUsShft = norm_s(extract_h(L_GainUs));
-  L_GainUs = L_shl(L_GainUs, swGainUsShft);
-
-  swGainShift = add(swGainUsShft, snsRS.sh);
-  swGainShift = sub(swGainShift, GSP0_SCALE);
-
-
-  /* gain > 1.0 */
-  /* ---------- */
-
-  if (swGainShift < 0)
-  {
-    swGainUs = round(L_GainUs);
-
-    L_Round_off = L_shl((long) 32768, swGainShift);
-
-    for (i = 0; i < S_LEN; i++)
-    {
-      L_scaled = L_mac(L_Round_off, swGainUs, pswVect[i]);
-      L_scaled = L_shr(L_scaled, swGainShift);
-      pswScldVect[i] = extract_h(L_scaled);
-    }
-
-    if (swGainShift == 0)
-      swGain = swGainUs;
-    else
-      swGain = 0x7fff;
-  }
-
-  /* gain < 1.0 */
-  /* ---------- */
-
-  else
-  {
-
-    /* shift down or not at all */
-    /* ------------------------ */
-    if (swGainShift > 0)
-      L_GainUs = L_shr(L_GainUs, swGainShift);
-
-    /* the rounded actual vector gain */
-    /* ------------------------------ */
-    swGain = round(L_GainUs);
-
-    /* now scale the vector (with rounding) */
-    /* ------------------------------------ */
-
-    for (i = 0; i < S_LEN; i++)
-    {
-      L_scaled = L_mac((long) 32768, swGain, pswVect[i]);
-      pswScldVect[i] = extract_h(L_scaled);
-    }
-  }
-  return (swGain);
-}
-
-/***************************************************************************
- *
  *   FUNCTION NAME: spectralPostFilter
  *
  *   PURPOSE:
@@ -4371,9 +1245,11 @@
  *
  *************************************************************************/
 
-static void spectralPostFilter(Shortword pswSPFIn[],
-                                      Shortword pswNumCoef[],
-                            Shortword pswDenomCoef[], Shortword pswSPFOut[])
+static void spectralPostFilter(struct gsmhr_decoder_state *st,
+				Shortword swEngyRShift,
+				Shortword pswSPFIn[], Shortword pswNumCoef[],
+				Shortword pswDenomCoef[],
+				Shortword pswSPFOut[])
 {
 /*_________________________________________________________________________
  |                                                                         |
@@ -4418,21 +1294,21 @@
   /* numerator of the postfilter */
   /*-----------------------------*/
 
-  lpcFir(pswSPFIn, pswNumCoef, gpswPostFiltStateNum, pswSPFOut);
+  lpcFir(pswSPFIn, pswNumCoef, st->gpswPostFiltStateNum, pswSPFOut);
 
   /* denominator of the postfilter */
   /*-------------------------------*/
 
-  lpcIir(pswSPFOut, pswDenomCoef, gpswPostFiltStateDenom, pswSPFOut);
+  lpcIir(pswSPFOut, pswDenomCoef, st->gpswPostFiltStateDenom, pswSPFOut);
 
   /* postemphasis section of postfilter */
   /*------------------------------------*/
 
   for (i = 0; i < S_LEN; i++)
   {
-    swTemp = msu_r(L_deposit_h(pswSPFOut[i]), swPostEmphasisState,
+    swTemp = msu_r(L_deposit_h(pswSPFOut[i]), st->swPostEmphasisState,
                    POST_EMPHASIS);
-    swPostEmphasisState = pswSPFOut[i];
+    st->swPostEmphasisState = pswSPFOut[i];
     pswSPFOut[i] = swTemp;
   }
 
@@ -4441,8 +1317,8 @@
   /* scale the speech vector */
   /*-----------------------------*/
 
-  swRunningGain = gswPostFiltAgcGain;
-  L_runningGain = L_deposit_h(gswPostFiltAgcGain);
+  swRunningGain = st->gswPostFiltAgcGain;
+  L_runningGain = L_deposit_h(st->gswPostFiltAgcGain);
   for (i = 0; i < S_LEN; i++)
   {
     L_runningGain = L_msu(L_runningGain, swRunningGain, AGC_COEF);
@@ -4454,213 +1330,48 @@
     L_Output = L_mult(swRunningGain, pswSPFOut[i]);
     pswSPFOut[i] = extract_h(L_shl(L_Output, 2));
   }
-  gswPostFiltAgcGain = swRunningGain;
+  st->gswPostFiltAgcGain = swRunningGain;
 
 }
 
-/***************************************************************************
- *
- *   FUNCTION NAME: speechDecoder
- *
- *   PURPOSE:
- *     The purpose of this function is to call all speech decoder
- *     subroutines.  This is the top level routine for the speech
- *     decoder.
- *
- *   INPUTS:
- *
- *     pswParameters[0:21]
- *
- *        pointer to this frame's parameters.  See below for input
- *        data format.
- *
- *   OUTPUTS:
- *
- *     pswDecodedSpeechFrame[0:159]
- *
- *        this frame's decoded 16 bit linear pcm frame
- *
- *   RETURN VALUE:
- *
- *     none
- *
- *   DESCRIPTION:
- *
- *     The sequence of events in the decoder, and therefore this routine
- *     follow a simple plan.  First, the frame based parameters are
- *     decoded.  Second, on a subframe basis, the subframe based
- *     parameters are decoded and the excitation is generated.  Third,
- *     on a subframe basis, the combined and scaled excitation is
- *     passed through the synthesis filter, and then the pitch and
- *     spectral postfilters.
- *
- *     The in-line comments for the routine speechDecoder, are very
- *     detailed.  Here in a more consolidated form, are the main
- *     points.
- *
- *     The R0 parameter is decoded using the lookup table
- *     psrR0DecTbl[].  The LPC codewords are looked up using lookupVQ().
- *     The decoded parameters are reflection coefficients
- *     (pswFrmKs[]).
- *
- *     The decoder does not use reflection coefficients directly.
- *     Instead it converts them to direct form coeficients.  This is
- *     done using rcToADp().  If this conversion results in invalid
- *     results, the previous frames parameters are used.
- *
- *     The direct form coeficients are used to derive the spectal
- *     postfilter's numerator and denominator coeficients.  The
- *     denominators coefficients are widened, and the numerators
- *     coefficients are a spectrally smoothed version of the
- *     denominator.  The smoothing is done with a_sst().
- *
- *     The frame based LPC coefficients are either used directly as the
- *     subframe coefficients, or are derived through interpolation.
- *     The subframe based coeffiecients are calculated in getSfrmLpc().
- *
- *     Based on voicing mode, the decoder will construct and scale the
- *     excitation in one of two ways.  For the voiced mode the lag is
- *     decoded using lagDecode().  The fractional pitch LTP lookup is
- *     done by the function fp_ex().  In both voiced and unvoiced
- *     mode, the VSELP codewords are decoded into excitation vectors
- *     using b_con() and v_con().
- *
- *     rs_rr(), rs_rrNs(), and scaleExcite() are used to calculate
- *     the gamma's, codevector gains, as well as beta, the LTP vector
- *     gain.  Description of this can be found in section 4.1.11.  Once
- *     the vectors have been scaled and combined, the excitation is
- *     stored in the LTP history.
- *
- *     The excitation, pswExcite[], passes through the pitch pre-filter
- *     (pitchPreFilt()).  Then the harmonically enhanced excitation
- *     passes through the synthesis filter, lpcIir(), and finally the
- *     reconstructed speech passes through the spectral post-filter
- *     (spectalPostFilter()).  The final output speech is passed back in
- *     the array pswDecodedSpeechFrame[].
- *
- *   INPUT DATA FORMAT:
- *
- *      The format/content of the input parameters is the so called
- *      bit alloc format.
- *
- *     voiced mode bit alloc format:
- *     -----------------------------
- *     index    number of bits  parameter name
- *     0        5               R0
- *     1        11              k1Tok3
- *     2        9               k4Tok6
- *     3        8               k7Tok10
- *     4        1               softInterpolation
- *     5        2               voicingDecision
- *     6        8               frameLag
- *     7        9               code_1
- *     8        5               gsp0_1
- *     9        4               deltaLag_2
- *     10       9               code_2
- *     11       5               gsp0_2
- *     12       4               deltaLag_3
- *     13       9               code_3
- *     14       5               gsp0_3
- *     15       4               deltaLag_4
- *     16       9               code_4
- *     17       5               gsp0_4
- *
- *     18       1               BFI
- *     19       1               UFI
- *     20       2               SID
- *     21       1               TAF
- *
- *
- *     unvoiced mode bit alloc format:
- *     -------------------------------
- *
- *     index    number of bits  parameter name
- *     0        5               R0
- *     1        11              k1Tok3
- *     2        9               k4Tok6
- *     3        8               k7Tok10
- *     4        1               softInterpolation
- *     5        2               voicingDecision
- *     6        7               code1_1
- *     7        7               code2_1
- *     8        5               gsp0_1
- *     9        7               code1_2
- *     10       7               code2_2
- *     11       5               gsp0_2
- *     12       7               code1_3
- *     13       7               code2_3
- *     14       5               gsp0_3
- *     15       7               code1_4
- *     16       7               code2_4
- *     17       5               gsp0_4
- *
- *     18       1               BFI
- *     19       1               UFI
- *     20       2               SID
- *     21       1               TAF
- *
- *
- *   REFERENCES: Sub_Clause 4.2 of GSM Recomendation 06.20
- *
- *   KEYWORDS: synthesis, speechdecoder, decoding
- *   KEYWORDS: codewords, lag, codevectors, gsp0
- *
- *************************************************************************/
+void gsmhr_decode_frame(struct gsmhr_decoder_state *st,
+			const int16_t *param_in, int16_t *pcm_out)
+{
+  int16_t param_preened[GSMHR_NUM_PARAMS];
 
-void   speechDecoder(Shortword pswParameters[],
-                            Shortword pswDecodedSpeechFrame[])
-{
+  Shortword *pswLtpStateOut = &st->pswLtpStateBaseDec[LTP_LEN];
+  Shortword pswSythAsSpace[NP * N_SUB];
+  Shortword pswPFNumAsSpace[NP * N_SUB];
+  Shortword pswPFDenomAsSpace[NP * N_SUB];
 
-/*_________________________________________________________________________
- |                                                                         |
- |                           Local Static Variables                        |
- |_________________________________________________________________________|
-*/
-
-  static Shortword
-        *pswLtpStateOut = &pswLtpStateBaseDec[LTP_LEN],
-         pswSythAsSpace[NP * N_SUB],
-         pswPFNumAsSpace[NP * N_SUB],
-         pswPFDenomAsSpace[NP * N_SUB],
-        *ppswSynthAs[N_SUB] = {
+  Shortword *ppswSynthAs[N_SUB] = {
     &pswSythAsSpace[0],
     &pswSythAsSpace[10],
     &pswSythAsSpace[20],
     &pswSythAsSpace[30],
-  },
+  };
 
-        *ppswPFNumAs[N_SUB] = {
+  Shortword *ppswPFNumAs[N_SUB] = {
     &pswPFNumAsSpace[0],
     &pswPFNumAsSpace[10],
     &pswPFNumAsSpace[20],
     &pswPFNumAsSpace[30],
-  },
-        *ppswPFDenomAs[N_SUB] = {
+  };
+
+  Shortword *ppswPFDenomAs[N_SUB] = {
     &pswPFDenomAsSpace[0],
     &pswPFDenomAsSpace[10],
     &pswPFDenomAsSpace[20],
     &pswPFDenomAsSpace[30],
   };
 
-  static ShortwordRom
-         psrSPFDenomWidenCf[NP] = {
+  static const ShortwordRom psrSPFDenomWidenCf[NP] = {
     0x6000, 0x4800, 0x3600, 0x2880, 0x1E60,
     0x16C8, 0x1116, 0x0CD0, 0x099C, 0x0735,
   };
 
-
-  static Longword L_RxPNSeed;          /* DTX mode */
-  static Shortword swRxDtxGsIndex;     /* DTX mode */
-
-
-/*_________________________________________________________________________
- |                                                                         |
- |                            Automatic Variables                          |
- |_________________________________________________________________________|
-*/
-
-  short int i,
-         j,
+  short int i, j,
+         giSfrmCnt,
          siLagCode,
          siGsp0Code,
          psiVselpCw[2],
@@ -4677,8 +1388,11 @@
          pswExcite[S_LEN],
          pswPPFExcit[S_LEN],
          pswSynthFiltOut[S_LEN],
+         swDecoMode,
          swR0Index,
+         swR0Dec,
          swLag,
+         swLastLag,
          swSemiBeta,
          pswBitArray[MAXBITS];
 
@@ -4687,284 +1401,86 @@
          snsRs11,
          snsRs22;
 
-
   Shortword swMutePermit,
          swLevelMean,
          swLevelMax,                   /* error concealment */
          swMuteFlag;                   /* error concealment */
 
+  Shortword swVoicingMode,             /* MODE */
+         swSi,                         /* INT_LPC */
+         swEngyRShift;                 /* for use by spectral postfilter */
 
-  Shortword swTAF,
-         swSID,
-         swBfiDtx;                     /* DTX mode */
-  Shortword swFrameType;               /* DTX mode */
-
-  Longword L_RxDTXGs;                  /* DTX mode */
+  /* initial home state processing must be done first */
+  if (st->is_homed) {
+    /*
+     * If we got a BFI, there is no point in taking the decoder out of the
+     * initial state.  Emit all zeros and stay homed.  Most forms of
+     * invalid SID will also be caught here.
+     */
+    if (param_in[18]) {
+      memset(pcm_out, 0, sizeof(int16_t) * F_LEN);
+      return;
+    }
+    /*
+     * Do the spec-mandated check for partial DHF.  Note how we check for
+     * non-SID, after having weeded out BFI above.
+     */
+    if (param_in[20] == 0 &&
+        memcmp(param_in, gsmhr_dhf_params, sizeof(int16_t) * 9) == 0) {
+      /* EHF output */
+      for (i = 0; i < F_LEN; i++)
+        pcm_out[i] = 0x0008;
+      return;
+    }
+  }
 
-/*_________________________________________________________________________
- |                                                                         |
- |                              Executable Code                            |
- |_________________________________________________________________________|
-*/
+  /* integration with factored-out RxFE - different from ETSI original code */
+  rxfe_main(&st->rxfe, param_in, param_preened, 0, &swDecoMode, &swMutePermit,
+            NULL);
+  swR0Index = param_preened[0];      /* R0 Index */
+  swR0Dec = psrR0DecTbl[swR0Index * 2];       /* R0 */
+  if (swDecoMode != CNIBFI)
+    lookupVq(param_preened + 1, pswFrmKs);
+  swSi = param_preened[4];           /* INT_LPC */
+  swVoicingMode = param_preened[5];  /* MODE */
 
-  /* -------------------------------------------------------------------- */
-  /* do bad frame handling (error concealment) and comfort noise          */
-  /* insertion                                                            */
-  /* -------------------------------------------------------------------- */
+  switch (swDecoMode) {
+  case SPEECH:
+    st->swRxDTXState = CNINTPER - 1;
+    break;
+  case CNIFIRSTSID:
+    st->swRxDTXState = CNINTPER - 1;
+    Init_CN_interpolation(st, swDecoMode, pswFrmKs);
+    swR0Dec = CN_Interpolate_R0(st, swR0Dec);
+    CN_Interpolate_LPC(st, pswFrmKs);
+    break;
+  case CNICONT:
+    st->swRxDTXState = 0;
+    Init_CN_interpolation(st, swDecoMode, pswFrmKs);
+    swR0Dec = CN_Interpolate_R0(st, swR0Dec);
+    CN_Interpolate_LPC(st, pswFrmKs);
+    break;
+  case CNIBFI:
+    if (st->swRxDTXState < (CNINTPER - 1))
+      st->swRxDTXState++;
+    swR0Dec = CN_Interpolate_R0(st, swR0Dec);
+    CN_Interpolate_LPC(st, pswFrmKs);
+    break;
+  }
 
+  /* ------------------- */
+  /* do frame processing */
+  /* ------------------- */
 
   /* This flag indicates whether muting is performed in the actual frame */
   /* ------------------------------------------------------------------- */
   swMuteFlag = 0;
 
-
-  /* This flag indicates whether muting is allowed in the actual frame */
-  /* ----------------------------------------------------------------- */
-  swMutePermit = 0;
-
-
-  /* frame classification */
-  /* -------------------- */
-
-  swSID = pswParameters[20];
-  swTAF = pswParameters[21];
-
-  swBfiDtx = pswParameters[18] | pswParameters[19];     /* BFI | UFI */
-
-  if ((swSID == 2) && (swBfiDtx == 0))
-    swFrameType = VALIDSID;
-  else if ((swSID == 0) && (swBfiDtx == 0))
-    swFrameType = GOODSPEECH;
-  else if ((swSID == 0) && (swBfiDtx != 0))
-    swFrameType = UNUSABLE;
-  else
-    swFrameType = INVALIDSID;
-
-
-  /* update of decoder state */
-  /* ----------------------- */
-
-  if (swDecoMode == SPEECH)
-  {
-    /* speech decoding mode */
-    /* -------------------- */
-
-    if (swFrameType == VALIDSID)
-      swDecoMode = CNIFIRSTSID;
-    else if (swFrameType == INVALIDSID)
-      swDecoMode = CNIFIRSTSID;
-    else if (swFrameType == UNUSABLE)
-      swDecoMode = SPEECH;
-    else if (swFrameType == GOODSPEECH)
-      swDecoMode = SPEECH;
-  }
-  else
-  {
-    /* comfort noise insertion mode */
-    /* ---------------------------- */
-
-    if (swFrameType == VALIDSID)
-      swDecoMode = CNICONT;
-    else if (swFrameType == INVALIDSID)
-      swDecoMode = CNICONT;
-    else if (swFrameType == UNUSABLE)
-      swDecoMode = CNIBFI;
-    else if (swFrameType == GOODSPEECH)
-      swDecoMode = SPEECH;
-  }
-
-
-  if (swDecoMode == SPEECH)
-  {
-    /* speech decoding mode */
-    /* -------------------- */
-
-    /* Perform parameter concealment, depending on BFI (pswParameters[18]) */
-    /* or UFI (pswParameters[19])                                          */
-    /* ------------------------------------------------------------------- */
-    para_conceal_speech_decoder(&pswParameters[18],
-                                pswParameters, &swMutePermit);
-
-
-    /* copy the frame rate parameters */
-    /* ------------------------------ */
-
-    swR0Index = pswParameters[0];      /* R0 Index */
-    pswVq[0] = pswParameters[1];       /* LPC1 */
-    pswVq[1] = pswParameters[2];       /* LPC2 */
-    pswVq[2] = pswParameters[3];       /* LPC3 */
-    swSi = pswParameters[4];           /* INT_LPC */
-    swVoicingMode = pswParameters[5];  /* MODE */
-
-
-    /* lookup R0 and VQ parameters */
-    /* --------------------------- */
-
-    swR0Dec = psrR0DecTbl[swR0Index * 2];       /* R0 */
-    lookupVq(pswVq, pswFrmKs);
-
-
-    /* save this frames GS values */
-    /* -------------------------- */
-
-    for (i = 0; i < N_SUB; i++)
-    {
-      pL_RxGsHist[swRxGsHistPtr] =
-              ppLr_gsTable[swVoicingMode][pswParameters[(i * 3) + 8]];
-      swRxGsHistPtr++;
-      if (swRxGsHistPtr > ((OVERHANG - 1) * N_SUB) - 1)
-        swRxGsHistPtr = 0;
-    }
-
-
-    /* DTX variables */
-    /* ------------- */
-
-    swDtxBfiCnt = 0;
-    swDtxMuting = 0;
-    swRxDTXState = CNINTPER - 1;
-
-  }
-  else
-  {
-    /* comfort noise insertion mode */
-    /*----------------------------- */
-
-    /* copy the frame rate parameters */
-    /* ------------------------------ */
-
-    swR0Index = pswParameters[0];      /* R0 Index */
-    pswVq[0] = pswParameters[1];       /* LPC1 */
-    pswVq[1] = pswParameters[2];       /* LPC2 */
-    pswVq[2] = pswParameters[3];       /* LPC3 */
-    swSi = 1;                          /* INT_LPC */
-    swVoicingMode = 0;                 /* MODE */
-
-
-    /* bad frame handling in comfort noise insertion mode */
-    /* -------------------------------------------------- */
-
-    if (swDecoMode == CNIFIRSTSID)     /* first SID frame */
-    {
-      swDtxBfiCnt = 0;
-      swDtxMuting = 0;
-      swRxDTXState = CNINTPER - 1;
-
-      if (swFrameType == VALIDSID)     /* valid SID frame */
-      {
-        swR0NewCN = psrR0DecTbl[swR0Index * 2];
-        lookupVq(pswVq, pswFrmKs);
-      }
-      else if (swFrameType == INVALIDSID)       /* invalid SID frame */
-      {
-        swR0NewCN = psrR0DecTbl[swOldR0IndexDec * 2];
-        swR0Index = swOldR0IndexDec;
-        for (i = 0; i < NP; i++)
-          pswFrmKs[i] = pswOldFrmKsDec[i];
-      }
-
-    }
-    else if (swDecoMode == CNICONT)    /* SID frame detected, but */
-    {                                  /* not the first SID       */
-      swDtxBfiCnt = 0;
-      swDtxMuting = 0;
-
-      if (swFrameType == VALIDSID)     /* valid SID frame */
-      {
-        swRxDTXState = 0;
-        swR0NewCN = psrR0DecTbl[swR0Index * 2];
-        lookupVq(pswVq, pswFrmKs);
-      }
-      else if (swFrameType == INVALIDSID)       /* invalid SID frame */
-      {
-        if (swRxDTXState < (CNINTPER - 1))
-          swRxDTXState = add(swRxDTXState, 1);
-        swR0Index = swOldR0IndexDec;
-      }
-
-    }
-    else if (swDecoMode == CNIBFI)     /* bad frame received in */
-    {                                  /* CNI mode              */
-      if (swRxDTXState < (CNINTPER - 1))
-        swRxDTXState = add(swRxDTXState, 1);
-      swR0Index = swOldR0IndexDec;
-
-      if (swDtxMuting == 1)
-      {
-        swOldR0IndexDec = sub(swOldR0IndexDec, 2);      /* attenuate
-                                                         * by 4 dB */
-        if (swOldR0IndexDec < 0)
-          swOldR0IndexDec = 0;
-
-        swR0Index = swOldR0IndexDec;
-
-        swR0NewCN = psrR0DecTbl[swOldR0IndexDec * 2];   /* R0 */
-
-      }
-
-      swDtxBfiCnt = add(swDtxBfiCnt, 1);
-      if ((swTAF == 1) && (swDtxBfiCnt >= (2 * CNINTPER + 1)))  /* 25 */
-        swDtxMuting = 1;
-
-    }
-
-
-    if (swDecoMode == CNIFIRSTSID)
-    {
-
-      /* the first SID frame is received */
-      /* ------------------------------- */
-
-      /* initialize the decoders pn-generator */
-      /* ------------------------------------ */
-
-      L_RxPNSeed = PN_INIT_SEED;
-
-
-      /* using the stored rx history, generate averaged GS */
-      /* ------------------------------------------------- */
-
-      avgGsHistQntz(pL_RxGsHist, &L_RxDTXGs);
-      swRxDtxGsIndex = gsQuant(L_RxDTXGs, 0);
-
-    }
-
-
-    /* Replace the "transmitted" subframe parameters with */
-    /* synthetic ones                                     */
-    /* -------------------------------------------------- */
-
-    for (i = 0; i < 4; i++)
-    {
-      /* initialize the GSP0 parameter */
-      pswParameters[(i * 3) + 8] = swRxDtxGsIndex;
-
-      /* CODE1 */
-      pswParameters[(i * 3) + 6] = getPnBits(7, &L_RxPNSeed);
-      /* CODE2 */
-      pswParameters[(i * 3) + 7] = getPnBits(7, &L_RxPNSeed);
-    }
-
-
-    /* Interpolation of CN parameters */
-    /* ------------------------------ */
-
-    rxInterpR0Lpc(pswOldFrmKsDec, pswFrmKs, swRxDTXState,
-                  swDecoMode, swFrameType);
-
-  }
-
-
-  /* ------------------- */
-  /* do frame processing */
-  /* ------------------- */
-
   /* generate the direct form coefs */
   /* ------------------------------ */
 
   if (!rcToADp(ASCALE, pswFrmKs, pswFrmAs))
   {
-
     /* widen direct form coefficients using the widening coefs */
     /* ------------------------------------------------------- */
 
@@ -4977,22 +1493,21 @@
   }
   else
   {
-
-
     for (i = 0; i < NP; i++)
     {
-      pswFrmKs[i] = pswOldFrmKsDec[i];
-      pswFrmAs[i] = pswOldFrmAsDec[i];
-      pswFrmPFDenom[i] = pswOldFrmPFDenom[i];
-      pswFrmPFNum[i] = pswOldFrmPFNum[i];
+      pswFrmKs[i] = st->pswOldFrmKsDec[i];
+      pswFrmAs[i] = st->pswOldFrmAsDec[i];
+      pswFrmPFDenom[i] = st->pswOldFrmPFDenom[i];
+      pswFrmPFNum[i] = st->pswOldFrmPFNum[i];
     }
   }
 
   /* interpolate, or otherwise get sfrm reflection coefs */
   /* --------------------------------------------------- */
 
-  getSfrmLpc(swSi, swOldR0Dec, swR0Dec, pswOldFrmKsDec, pswOldFrmAsDec,
-             pswOldFrmPFNum, pswOldFrmPFDenom, pswFrmKs, pswFrmAs,
+  getSfrmLpc(swSi, st->swOldR0Dec, swR0Dec, st->pswOldFrmKsDec,
+             st->pswOldFrmAsDec, st->pswOldFrmPFNum, st->pswOldFrmPFDenom,
+             pswFrmKs, pswFrmAs,
              pswFrmPFNum, pswFrmPFDenom, psnsSqrtRs, ppswSynthAs,
              ppswPFNumAs, ppswPFDenomAs);
 
@@ -5012,17 +1527,17 @@
     /* copy this sub-frame's parameters */
     /* -------------------------------- */
 
-    if (sub(swVoicingMode, 0) == 0)
+    if (swVoicingMode == 0)
     {                                  /* unvoiced */
-      psiVselpCw[0] = pswParameters[(giSfrmCnt * 3) + 6];       /* CODE_1 */
-      psiVselpCw[1] = pswParameters[(giSfrmCnt * 3) + 7];       /* CODE_2 */
-      siGsp0Code = pswParameters[(giSfrmCnt * 3) + 8];  /* GSP0 */
+      psiVselpCw[0] = param_preened[(giSfrmCnt * 3) + 6];       /* CODE_1 */
+      psiVselpCw[1] = param_preened[(giSfrmCnt * 3) + 7];       /* CODE_2 */
+      siGsp0Code = param_preened[(giSfrmCnt * 3) + 8];  /* GSP0 */
     }
     else
     {                                  /* voiced */
-      siLagCode = pswParameters[(giSfrmCnt * 3) + 6];   /* LAG */
-      psiVselpCw[0] = pswParameters[(giSfrmCnt * 3) + 7];       /* CODE */
-      siGsp0Code = pswParameters[(giSfrmCnt * 3) + 8];  /* GSP0 */
+      siLagCode = param_preened[(giSfrmCnt * 3) + 6];   /* LAG */
+      psiVselpCw[0] = param_preened[(giSfrmCnt * 3) + 7];       /* CODE */
+      siGsp0Code = param_preened[(giSfrmCnt * 3) + 8];  /* GSP0 */
     }
 
     /* for voiced mode, reconstruct the pitch vector */
@@ -5034,7 +1549,7 @@
       /* convert delta lag to lag and convert to fractional lag */
       /* ------------------------------------------------------ */
 
-      swLag = lagDecode(siLagCode);
+      swLag = lagDecode(siLagCode, &swLastLag, giSfrmCnt);
 
       /* state followed by out */
       /* --------------------- */
@@ -5155,7 +1670,7 @@
 
     for (i = 0; i < LTP_LEN; i++)
     {
-      pswLtpStateBaseDec[i] = pswLtpStateBaseDec[i + S_LEN];
+      st->pswLtpStateBaseDec[i] = st->pswLtpStateBaseDec[i + S_LEN];
     }
 
     /* add the current sub-frames data to the state */
@@ -5171,301 +1686,70 @@
 
     pitchPreFilt(pswExcite, siGsp0Code, swLag,
                  swVoicingMode, swSemiBeta, psnsSqrtRs[giSfrmCnt],
-                 pswPPFExcit, pswPPreState);
+                 pswPPFExcit, st->pswPPreState);
 
 
     /* Concealment on subframe signal level: */
     /* ------------------------------------- */
-    level_estimator(0, &swLevelMean, &swLevelMax,
-                    &pswDecodedSpeechFrame[giSfrmCnt * S_LEN]);
+    level_estimator_det(st, &swLevelMean, &swLevelMax);
 
-    signal_conceal_sub(pswPPFExcit, ppswSynthAs[giSfrmCnt], pswSynthFiltState,
-                    &pswLtpStateOut[-S_LEN], &pswPPreState[LTP_LEN - S_LEN],
+    signal_conceal_sub(pswPPFExcit, ppswSynthAs[giSfrmCnt],
+                       st->pswSynthFiltState, &pswLtpStateOut[-S_LEN],
+                       &st->pswPPreState[LTP_LEN - S_LEN],
                        swLevelMean, swLevelMax,
-                       pswParameters[19], swMuteFlagOld,
+                       param_in[19], st->swMuteFlagOld,
                        &swMuteFlag, swMutePermit);
 
 
     /* synthesize the speech through the synthesis filter */
     /* -------------------------------------------------- */
 
-    lpcIir(pswPPFExcit, ppswSynthAs[giSfrmCnt], pswSynthFiltState,
+    lpcIir(pswPPFExcit, ppswSynthAs[giSfrmCnt], st->pswSynthFiltState,
            pswSynthFiltOut);
 
     /* pass reconstructed speech through adaptive spectral postfilter */
     /* -------------------------------------------------------------- */
 
-    spectralPostFilter(pswSynthFiltOut, ppswPFNumAs[giSfrmCnt],
+    spectralPostFilter(st, swEngyRShift,
+                       pswSynthFiltOut, ppswPFNumAs[giSfrmCnt],
                        ppswPFDenomAs[giSfrmCnt],
-                       &pswDecodedSpeechFrame[giSfrmCnt * S_LEN]);
+                       &pcm_out[giSfrmCnt * S_LEN]);
 
-    level_estimator(1, &swLevelMean, &swLevelMax,
-                    &pswDecodedSpeechFrame[giSfrmCnt * S_LEN]);
+    level_estimator_upd(st, &pcm_out[giSfrmCnt * S_LEN]);
 
   }
 
+  /* truncate the 16 bit linear pcm to 13 bits */
+  /* ----------------------------------------- */
+
+  for (i = 0; i < F_LEN; i++)
+  {
+    pcm_out[i] &= PCM_MASK;
+  }
+
+  /* Nothing but state updates left - do homing logic here. */
+  if (param_in[18] == 0 && param_in[20] == 0 &&
+      memcmp(param_in, gsmhr_dhf_params, sizeof(int16_t) * 18) == 0) {
+	gsmhr_decoder_reset(st);
+	return;
+  }
+  st->is_homed = 0;
+
   /* Save muting information for next frame */
   /* -------------------------------------- */
-  swMuteFlagOld = swMuteFlag;
+  st->swMuteFlagOld = swMuteFlag;
 
   /* end of frame processing - save this frame's frame energy,  */
   /* reflection coefs, direct form coefs, and post filter coefs */
   /* ---------------------------------------------------------- */
 
-  swOldR0Dec = swR0Dec;
-  swOldR0IndexDec = swR0Index;         /* DTX mode */
+  st->swOldR0Dec = swR0Dec;
 
   for (i = 0; i < NP; i++)
   {
-    pswOldFrmKsDec[i] = pswFrmKs[i];
-    pswOldFrmAsDec[i] = pswFrmAs[i];
-    pswOldFrmPFNum[i] = pswFrmPFNum[i];
-    pswOldFrmPFDenom[i] = pswFrmPFDenom[i];
+    st->pswOldFrmKsDec[i] = pswFrmKs[i];
+    st->pswOldFrmAsDec[i] = pswFrmAs[i];
+    st->pswOldFrmPFNum[i] = pswFrmPFNum[i];
+    st->pswOldFrmPFDenom[i] = pswFrmPFDenom[i];
   }
 }
-
-
-/***************************************************************************
- *
- *   FUNCTION NAME: sqroot
- *
- *   PURPOSE:
- *
- *     The purpose of this function is to perform a single precision square
- *     root function on a Longword
- *
- *   INPUTS:
- *
- *     L_SqrtIn
- *                     input to square root function
- *
- *   OUTPUTS:
- *
- *     none
- *
- *   RETURN VALUE:
- *
- *     swSqrtOut
- *                     output to square root function
- *
- *   DESCRIPTION:
- *
- *      Input assumed to be normalized
- *
- *      The algorithm is based around a six term Taylor expansion :
- *
- *        y^0.5 = (1+x)^0.5
- *             ~= 1 + (x/2) - 0.5*((x/2)^2) + 0.5*((x/2)^3)
- *                - 0.625*((x/2)^4) + 0.875*((x/2)^5)
- *
- *      Max error less than 0.08 % for normalized input ( 0.5 <= x < 1 )
- *
- *   REFERENCES: Sub-clause 4.1.4.1, 4.1.7, 4.1.11.1, 4.2.1,
- *               4.2.2, 4.2.3 and 4.2.4 of GSM Recomendation 06.20
- *
- *   KEYWORDS: sqrt, squareroot, sqrt016
- *
- *************************************************************************/
-
-Shortword sqroot(Longword L_SqrtIn)
-{
-
-/*_________________________________________________________________________
- |                                                                         |
- |                              Local Constants                            |
- |_________________________________________________________________________|
-*/
-
-#define    PLUS_HALF          0x40000000L       /* 0.5 */
-#define    MINUS_ONE          0x80000000L       /* -1 */
-#define    TERM5_MULTIPLER    0x5000   /* 0.625 */
-#define    TERM6_MULTIPLER    0x7000   /* 0.875 */
-
-/*_________________________________________________________________________
- |                                                                         |
- |                            Automatic Variables                          |
- |_________________________________________________________________________|
-*/
-
-  Longword L_Temp0,
-         L_Temp1;
-
-  Shortword swTemp,
-         swTemp2,
-         swTemp3,
-         swTemp4,
-         swSqrtOut;
-
-/*_________________________________________________________________________
- |                                                                         |
- |                              Executable Code                            |
- |_________________________________________________________________________|
-*/
-
-  /* determine 2nd term x/2 = (y-1)/2 */
-  /* -------------------------------- */
-
-  L_Temp1 = L_shr(L_SqrtIn, 1);        /* L_Temp1 = y/2 */
-  L_Temp1 = L_sub(L_Temp1, PLUS_HALF); /* L_Temp1 = (y-1)/2 */
-  swTemp = extract_h(L_Temp1);         /* swTemp = x/2 */
-
-  /* add contribution of 2nd term */
-  /* ---------------------------- */
-
-  L_Temp1 = L_sub(L_Temp1, MINUS_ONE); /* L_Temp1 = 1 + x/2 */
-
-  /* determine 3rd term */
-  /* ------------------ */
-
-  L_Temp0 = L_msu(0L, swTemp, swTemp); /* L_Temp0 = -(x/2)^2 */
-  swTemp2 = extract_h(L_Temp0);        /* swTemp2 = -(x/2)^2 */
-  L_Temp0 = L_shr(L_Temp0, 1);         /* L_Temp0 = -0.5*(x/2)^2 */
-
-  /* add contribution of 3rd term */
-  /* ---------------------------- */
-
-  L_Temp0 = L_add(L_Temp1, L_Temp0);   /* L_Temp0 = 1 + x/2 - 0.5*(x/2)^2 */
-
-  /* determine 4rd term */
-  /* ------------------ */
-
-  L_Temp1 = L_msu(0L, swTemp, swTemp2);/* L_Temp1 = (x/2)^3 */
-  swTemp3 = extract_h(L_Temp1);        /* swTemp3 = (x/2)^3 */
-  L_Temp1 = L_shr(L_Temp1, 1);         /* L_Temp1 = 0.5*(x/2)^3 */
-
-  /* add contribution of 4rd term */
-  /* ---------------------------- */
-
-  /* L_Temp1 = 1 + x/2 - 0.5*(x/2)^2 + 0.5*(x/2)^3 */
-
-  L_Temp1 = L_add(L_Temp0, L_Temp1);
-
-  /* determine partial 5th term */
-  /* -------------------------- */
-
-  L_Temp0 = L_mult(swTemp, swTemp3);   /* L_Temp0 = (x/2)^4 */
-  swTemp4 = round(L_Temp0);            /* swTemp4 = (x/2)^4 */
-
-  /* determine partial 6th term */
-  /* -------------------------- */
-
-  L_Temp0 = L_msu(0L, swTemp2, swTemp3);        /* L_Temp0 = (x/2)^5 */
-  swTemp2 = round(L_Temp0);            /* swTemp2 = (x/2)^5 */
-
-  /* determine 5th term and add its contribution */
-  /* ------------------------------------------- */
-
-  /* L_Temp0 = -0.625*(x/2)^4 */
-
-  L_Temp0 = L_msu(0L, TERM5_MULTIPLER, swTemp4);
-
-  /* L_Temp1 = 1 + x/2 - 0.5*(x/2)^2 + 0.5*(x/2)^3 - 0.625*(x/2)^4 */
-
-  L_Temp1 = L_add(L_Temp0, L_Temp1);
-
-  /* determine 6th term and add its contribution */
-  /* ------------------------------------------- */
-
-  /* swSqrtOut = 1 + x/2 - 0.5*(x/2)^2 + 0.5*(x/2)^3 */
-  /* - 0.625*(x/2)^4 + 0.875*(x/2)^5     */
-
-  swSqrtOut = mac_r(L_Temp1, TERM6_MULTIPLER, swTemp2);
-
-  /* return output */
-  /* ------------- */
-
-  return (swSqrtOut);
-}
-
-/***************************************************************************
- *
- *   FUNCTION NAME: v_con
- *
- *   PURPOSE:
- *
- *     This subroutine constructs a codebook excitation
- *     vector from basis vectors
- *
- *   INPUTS:
- *
- *     pswBVects[0:siNumBVctrs*S_LEN-1]
- *
- *                     Array containing a set of basis vectors.
- *
- *     pswBitArray[0:siNumBVctrs-1]
- *
- *                     Bit array dictating the polarity of the
- *                     basis vectors in the output vector.
- *                     Each element of the bit array is either -0.5 or +0.5
- *
- *     siNumBVctrs
- *                     Number of bits in codeword
- *
- *   OUTPUTS:
- *
- *     pswOutVect[0:39]
- *
- *                     Array containing the contructed output vector
- *
- *   RETURN VALUE:
- *
- *     none
- *
- *   DESCRIPTION:
- *
- *     The array pswBitArray is used to multiply each of the siNumBVctrs
- *     basis vectors.  The input pswBitArray[] is an array whose
- *     elements are +/-0.5.  These multiply the VSELP basis vectors and
- *     when summed produce a VSELP codevector.  b_con() is the function
- *     used to translate a VSELP codeword into pswBitArray[].
- *
- *
- *   REFERENCES: Sub-clause 4.1.10 and 4.2.1 of GSM Recomendation 06.20
- *
- *   KEYWORDS: v_con, codeword, reconstruct, basis vector, excitation
- *
- *************************************************************************/
-
-void   v_con(Shortword pswBVects[], Shortword pswOutVect[],
-                    Shortword pswBitArray[], short int siNumBVctrs)
-{
-
-/*_________________________________________________________________________
- |                                                                         |
- |                            Automatic Variables                          |
- |_________________________________________________________________________|
-*/
-
-  Longword L_Temp;
-
-  short int siSampleCnt,
-         siCVectCnt;
-
-/*_________________________________________________________________________
- |                                                                         |
- |                              Executable Code                            |
- |_________________________________________________________________________|
-*/
-
-  /* Sample loop  */
-  /*--------------*/
-  for (siSampleCnt = 0; siSampleCnt < S_LEN; siSampleCnt++)
-  {
-
-    /* First element of output vector */
-    L_Temp = L_mult(pswBitArray[0], pswBVects[0 * S_LEN + siSampleCnt]);
-
-    /* Construct output vector */
-    /*-------------------------*/
-    for (siCVectCnt = 1; siCVectCnt < siNumBVctrs; siCVectCnt++)
-    {
-      L_Temp = L_mac(L_Temp, pswBitArray[siCVectCnt],
-                     pswBVects[siCVectCnt * S_LEN + siSampleCnt]);
-    }
-
-    /* store the output vector sample */
-    /*--------------------------------*/
-    L_Temp = L_shl(L_Temp, 1);
-    pswOutVect[siSampleCnt] = extract_h(L_Temp);
-  }
-}