changeset 53:49dd1ac8e75b

libgsmefr: import most *.c files from ETSI source
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 25 Nov 2022 16:18:21 +0000
parents 988fd7ff514f
children 7b11cbe99a0e
files libgsmefr/agc.c libgsmefr/autocorr.c libgsmefr/az_lsp.c libgsmefr/c1035pf.c libgsmefr/cod_12k2.c libgsmefr/convolve.c libgsmefr/d1035pf.c libgsmefr/d_gains.c libgsmefr/d_homing.c libgsmefr/d_plsf_5.c libgsmefr/dec_12k2.c libgsmefr/dec_lag6.c libgsmefr/e_homing.c libgsmefr/enc_lag6.c libgsmefr/g_code.c libgsmefr/g_pitch.c libgsmefr/int_lpc.c libgsmefr/inter_6.c libgsmefr/inv_sqrt.c libgsmefr/lag_wind.c libgsmefr/levinson.c libgsmefr/log2.c libgsmefr/lsp_az.c libgsmefr/lsp_lsf.c libgsmefr/oper_32b.c libgsmefr/pitch_f6.c libgsmefr/pitch_ol.c libgsmefr/pow2.c libgsmefr/pre_proc.c libgsmefr/pred_lt6.c libgsmefr/preemph.c libgsmefr/pstfilt2.c libgsmefr/q_gains.c libgsmefr/q_plsf_5.c libgsmefr/reorder.c libgsmefr/residu.c libgsmefr/syn_filt.c libgsmefr/weight_a.c
diffstat 38 files changed, 7158 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgsmefr/agc.c	Fri Nov 25 16:18:21 2022 +0000
@@ -0,0 +1,186 @@
+/*************************************************************************
+ *
+ *  FUNCTION:  agc
+ *
+ *  PURPOSE: Scales the postfilter output on a subframe basis by automatic
+ *           control of the subframe gain.
+ *
+ *  DESCRIPTION:
+ *   sig_out[n] = sig_out[n] * gain[n];
+ *   where gain[n] is the gain at the nth sample given by
+ *     gain[n] = agc_fac * gain[n-1] + (1 - agc_fac) g_in/g_out
+ *   g_in/g_out is the square root of the ratio of energy at the input
+ *   and output of the postfilter.
+ *
+ *************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "count.h"
+#include "sig_proc.h"
+#include "cnst.h"
+
+Word16 past_gain;               /* initial value of past_gain = 1.0  */
+
+void agc (
+    Word16 *sig_in,             /* (i)     : postfilter input signal  */
+    Word16 *sig_out,            /* (i/o)   : postfilter output signal */
+    Word16 agc_fac,             /* (i)     : AGC factor               */
+    Word16 l_trm                /* (i)     : subframe size            */
+)
+{
+    Word16 i, exp;
+    Word16 gain_in, gain_out, g0, gain;
+    Word32 s;
+
+    Word16 temp;
+
+    /* calculate gain_out with exponent */
+
+    temp = shr (sig_out[0], 2);
+    s = L_mult (temp, temp);
+
+    for (i = 1; i < l_trm; i++)
+    {
+        temp = shr (sig_out[i], 2);
+        s = L_mac (s, temp, temp);
+    }
+
+    test (); 
+    if (s == 0)
+    {
+        past_gain = 0;          move16 (); 
+        return;
+    }
+    exp = sub (norm_l (s), 1);
+    gain_out = round (L_shl (s, exp));
+
+    /* calculate gain_in with exponent */
+
+    temp = shr (sig_in[0], 2);
+    s = L_mult (temp, temp);
+
+    for (i = 1; i < l_trm; i++)
+    {
+        temp = shr (sig_in[i], 2);
+        s = L_mac (s, temp, temp);
+    }
+
+    test (); 
+    if (s == 0)
+    {
+        g0 = 0;                 move16 (); 
+    }
+    else
+    {
+        i = norm_l (s);
+        gain_in = round (L_shl (s, i));
+        exp = sub (exp, i);
+
+        /*---------------------------------------------------*
+         *  g0 = (1-agc_fac) * sqrt(gain_in/gain_out);       *
+         *---------------------------------------------------*/
+
+        s = L_deposit_l (div_s (gain_out, gain_in));
+        s = L_shl (s, 7);       /* s = gain_out / gain_in */
+        s = L_shr (s, exp);     /* add exponent */
+
+        s = Inv_sqrt (s);
+        i = round (L_shl (s, 9));
+
+        /* g0 = i * (1-agc_fac) */
+        g0 = mult (i, sub (32767, agc_fac));
+    }
+
+    /* compute gain[n] = agc_fac * gain[n-1]
+                        + (1-agc_fac) * sqrt(gain_in/gain_out) */
+    /* sig_out[n] = gain[n] * sig_out[n]                        */
+
+    gain = past_gain;           move16 (); 
+
+    for (i = 0; i < l_trm; i++)
+    {
+        gain = mult (gain, agc_fac);
+        gain = add (gain, g0);
+        sig_out[i] = extract_h (L_shl (L_mult (sig_out[i], gain), 3));
+                                move16 (); 
+    }
+
+    past_gain = gain;           move16 (); 
+
+    return;
+}
+
+void agc2 (
+ Word16 *sig_in,        /* (i)     : postfilter input signal  */
+ Word16 *sig_out,       /* (i/o)   : postfilter output signal */
+ Word16 l_trm           /* (i)     : subframe size            */
+)
+{
+    Word16 i, exp;
+    Word16 gain_in, gain_out, g0;
+    Word32 s;
+
+    Word16 temp;
+
+    /* calculate gain_out with exponent */
+
+    temp = shr (sig_out[0], 2);
+    s = L_mult (temp, temp);
+    for (i = 1; i < l_trm; i++)
+    {
+        temp = shr (sig_out[i], 2);
+        s = L_mac (s, temp, temp);
+    }
+
+    test (); 
+    if (s == 0)
+    {
+        return;
+    }
+    exp = sub (norm_l (s), 1);
+    gain_out = round (L_shl (s, exp));
+
+    /* calculate gain_in with exponent */
+
+    temp = shr (sig_in[0], 2);
+    s = L_mult (temp, temp);
+    for (i = 1; i < l_trm; i++)
+    {
+        temp = shr (sig_in[i], 2);
+        s = L_mac (s, temp, temp);
+    }
+
+    test (); 
+    if (s == 0)
+    {
+        g0 = 0;                 move16 (); 
+    }
+    else
+    {
+        i = norm_l (s);
+        gain_in = round (L_shl (s, i));
+        exp = sub (exp, i);
+
+        /*---------------------------------------------------*
+         *  g0 = sqrt(gain_in/gain_out);                     *
+         *---------------------------------------------------*/
+
+        s = L_deposit_l (div_s (gain_out, gain_in));
+        s = L_shl (s, 7);       /* s = gain_out / gain_in */
+        s = L_shr (s, exp);     /* add exponent */
+
+        s = Inv_sqrt (s);
+        g0 = round (L_shl (s, 9));
+    }
+
+    /* sig_out(n) = gain(n) sig_out(n) */
+
+    for (i = 0; i < l_trm; i++)
+    {
+        sig_out[i] = extract_h (L_shl (L_mult (sig_out[i], g0), 3));
+                                move16 (); 
+    }
+
+    return;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgsmefr/autocorr.c	Fri Nov 25 16:18:21 2022 +0000
@@ -0,0 +1,99 @@
+/*************************************************************************
+ *
+ *  FUNCTION:  autocorr
+ *
+ *  PURPOSE:   Compute autocorrelations of signal with windowing
+ *
+ *  DESCRIPTION:
+ *       - Windowing of input speech:   s'[n] = s[n] * w[n]
+ *       - Autocorrelations of input speech:
+ *             r[k] = sum_{i=k}^{239} s'[i]*s'[i-k]    k=0,...,10
+ *         The autocorrelations are expressed in normalized double precision
+ *         format.
+ *
+ *************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "oper_32b.h"
+#include "count.h"
+#include "cnst.h"
+
+Word16 Autocorr (
+    Word16 x[],         /* (i)    : Input signal                    */
+    Word16 m,           /* (i)    : LPC order                       */
+    Word16 r_h[],       /* (o)    : Autocorrelations  (msb)         */
+    Word16 r_l[],       /* (o)    : Autocorrelations  (lsb)         */
+    Word16 wind[]       /* (i)    : window for LPC analysis         */
+)
+{
+    Word16 i, j, norm;
+    Word16 y[L_WINDOW];
+    Word32 sum;
+    Word16 overfl, overfl_shft;
+
+    /* Windowing of signal */
+
+    for (i = 0; i < L_WINDOW; i++)
+    {
+        y[i] = mult_r (x[i], wind[i]); move16 (); 
+    }
+
+    /* Compute r[0] and test for overflow */
+
+    overfl_shft = 0;                   move16 (); 
+
+    do
+    {
+        overfl = 0;                    move16 (); 
+        sum = 0L;                      move32 ();
+
+        for (i = 0; i < L_WINDOW; i++)
+        {
+            sum = L_mac (sum, y[i], y[i]);
+        }
+
+        /* If overflow divide y[] by 4 */
+
+        test (); 
+        if (L_sub (sum, MAX_32) == 0L)
+        {
+            overfl_shft = add (overfl_shft, 4);
+            overfl = 1;                move16 (); /* Set the overflow flag */
+
+            for (i = 0; i < L_WINDOW; i++)
+            {
+                y[i] = shr (y[i], 2);  move16 (); 
+            }
+        }
+        test (); 
+    }
+    while (overfl != 0);
+
+    sum = L_add (sum, 1L);             /* Avoid the case of all zeros */
+
+    /* Normalization of r[0] */
+
+    norm = norm_l (sum);
+    sum = L_shl (sum, norm);
+    L_Extract (sum, &r_h[0], &r_l[0]); /* Put in DPF format (see oper_32b) */
+
+    /* r[1] to r[m] */
+
+    for (i = 1; i <= m; i++)
+    {
+        sum = 0;                       move32 (); 
+
+        for (j = 0; j < L_WINDOW - i; j++)
+        {
+            sum = L_mac (sum, y[j], y[j + i]);
+        }
+
+        sum = L_shl (sum, norm);
+        L_Extract (sum, &r_h[i], &r_l[i]);
+    }
+
+    norm = sub (norm, overfl_shft);
+
+    return norm;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgsmefr/az_lsp.c	Fri Nov 25 16:18:21 2022 +0000
@@ -0,0 +1,261 @@
+/***********************************************************************
+ *
+ *  FUNCTION:  Az_lsp
+ *
+ *  PURPOSE:   Compute the LSPs from  the LP coefficients  (order=10)
+ *
+ *  DESCRIPTION:
+ *    - The sum and difference filters are computed and divided by
+ *      1+z^{-1}   and   1-z^{-1}, respectively.
+ *
+ *         f1[i] = a[i] + a[11-i] - f1[i-1] ;   i=1,...,5
+ *         f2[i] = a[i] - a[11-i] + f2[i-1] ;   i=1,...,5
+ *
+ *    - The roots of F1(z) and F2(z) are found using Chebyshev polynomial
+ *      evaluation. The polynomials are evaluated at 60 points regularly
+ *      spaced in the frequency domain. The sign change interval is
+ *      subdivided 4 times to better track the root.
+ *      The LSPs are found in the cosine domain [1,-1].
+ *
+ *    - If less than 10 roots are found, the LSPs from the past frame are
+ *      used.
+ *
+ ***********************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "oper_32b.h"
+#include "count.h"
+#include "cnst.h"
+
+#include "grid.tab"
+
+/* M = LPC order, NC = M/2 */
+
+#define NC   M/2
+
+/* local function */
+
+static Word16 Chebps (Word16 x, Word16 f[], Word16 n);
+
+void Az_lsp (
+    Word16 a[],         /* (i)     : predictor coefficients                 */
+    Word16 lsp[],       /* (o)     : line spectral pairs                    */
+    Word16 old_lsp[]    /* (i)     : old lsp[] (in case not found 10 roots) */
+)
+{
+    Word16 i, j, nf, ip;
+    Word16 xlow, ylow, xhigh, yhigh, xmid, ymid, xint;
+    Word16 x, y, sign, exp;
+    Word16 *coef;
+    Word16 f1[M / 2 + 1], f2[M / 2 + 1];
+    Word32 t0;
+
+    /*-------------------------------------------------------------*
+     *  find the sum and diff. pol. F1(z) and F2(z)                *
+     *    F1(z) <--- F1(z)/(1+z**-1) & F2(z) <--- F2(z)/(1-z**-1)  *
+     *                                                             *
+     * f1[0] = 1.0;                                                *
+     * f2[0] = 1.0;                                                *
+     *                                                             *
+     * for (i = 0; i< NC; i++)                                     *
+     * {                                                           *
+     *   f1[i+1] = a[i+1] + a[M-i] - f1[i] ;                       *
+     *   f2[i+1] = a[i+1] - a[M-i] + f2[i] ;                       *
+     * }                                                           *
+     *-------------------------------------------------------------*/
+
+    f1[0] = 1024;                  move16 (); /* f1[0] = 1.0 */
+    f2[0] = 1024;                  move16 (); /* f2[0] = 1.0 */
+
+    for (i = 0; i < NC; i++)
+    {
+        t0 = L_mult (a[i + 1], 8192);   /* x = (a[i+1] + a[M-i]) >> 2  */
+        t0 = L_mac (t0, a[M - i], 8192);
+        x = extract_h (t0);
+        /* f1[i+1] = a[i+1] + a[M-i] - f1[i] */
+        f1[i + 1] = sub (x, f1[i]);move16 (); 
+
+        t0 = L_mult (a[i + 1], 8192);   /* x = (a[i+1] - a[M-i]) >> 2 */
+        t0 = L_msu (t0, a[M - i], 8192);
+        x = extract_h (t0);
+        /* f2[i+1] = a[i+1] - a[M-i] + f2[i] */
+        f2[i + 1] = add (x, f2[i]);move16 (); 
+    }
+
+    /*-------------------------------------------------------------*
+     * find the LSPs using the Chebychev pol. evaluation           *
+     *-------------------------------------------------------------*/
+
+    nf = 0;                        move16 (); /* number of found frequencies */
+    ip = 0;                        move16 (); /* indicator for f1 or f2      */
+
+    coef = f1;                     move16 (); 
+
+    xlow = grid[0];                move16 (); 
+    ylow = Chebps (xlow, coef, NC);move16 (); 
+
+    j = 0;
+    test (); test (); 
+    /* while ( (nf < M) && (j < grid_points) ) */
+    while ((sub (nf, M) < 0) && (sub (j, grid_points) < 0))
+    {
+        j++;
+        xhigh = xlow;              move16 (); 
+        yhigh = ylow;              move16 (); 
+        xlow = grid[j];            move16 (); 
+        ylow = Chebps (xlow, coef, NC);
+                                   move16 (); 
+
+        test (); 
+        if (L_mult (ylow, yhigh) <= (Word32) 0L)
+        {
+
+            /* divide 4 times the interval */
+
+            for (i = 0; i < 4; i++)
+            {
+                /* xmid = (xlow + xhigh)/2 */
+                xmid = add (shr (xlow, 1), shr (xhigh, 1));
+                ymid = Chebps (xmid, coef, NC);
+                                   move16 (); 
+
+                test (); 
+                if (L_mult (ylow, ymid) <= (Word32) 0L)
+                {
+                    yhigh = ymid;  move16 (); 
+                    xhigh = xmid;  move16 (); 
+                }
+                else
+                {
+                    ylow = ymid;   move16 (); 
+                    xlow = xmid;   move16 (); 
+                }
+            }
+
+            /*-------------------------------------------------------------*
+             * Linear interpolation                                        *
+             *    xint = xlow - ylow*(xhigh-xlow)/(yhigh-ylow);            *
+             *-------------------------------------------------------------*/
+
+            x = sub (xhigh, xlow);
+            y = sub (yhigh, ylow);
+
+            test (); 
+            if (y == 0)
+            {
+                xint = xlow;       move16 (); 
+            }
+            else
+            {
+                sign = y;          move16 (); 
+                y = abs_s (y);
+                exp = norm_s (y);
+                y = shl (y, exp);
+                y = div_s ((Word16) 16383, y);
+                t0 = L_mult (x, y);
+                t0 = L_shr (t0, sub (20, exp));
+                y = extract_l (t0);     /* y= (xhigh-xlow)/(yhigh-ylow) */
+
+                test (); 
+                if (sign < 0)
+                    y = negate (y);
+
+                t0 = L_mult (ylow, y);
+                t0 = L_shr (t0, 11);
+                xint = sub (xlow, extract_l (t0)); /* xint = xlow - ylow*y */
+            }
+
+            lsp[nf] = xint;        move16 (); 
+            xlow = xint;           move16 (); 
+            nf++;
+
+            test (); 
+            if (ip == 0)
+            {
+                ip = 1;            move16 (); 
+                coef = f2;         move16 (); 
+            }
+            else
+            {
+                ip = 0;            move16 (); 
+                coef = f1;         move16 (); 
+            }
+            ylow = Chebps (xlow, coef, NC);
+                                   move16 (); 
+
+        }
+        test (); test (); 
+    }
+
+    /* Check if M roots found */
+
+    test (); 
+    if (sub (nf, M) < 0)
+    {
+        for (i = 0; i < M; i++)
+        {
+            lsp[i] = old_lsp[i];   move16 (); 
+        }
+
+    }
+    return;
+}
+
+/************************************************************************
+ *
+ *  FUNCTION:  Chebps
+ *
+ *  PURPOSE:   Evaluates the Chebyshev polynomial series
+ *
+ *  DESCRIPTION:
+ *  - The polynomial order is   n = m/2 = 5
+ *  - The polynomial F(z) (F1(z) or F2(z)) is given by
+ *     F(w) = 2 exp(-j5w) C(x)
+ *    where
+ *      C(x) = T_n(x) + f(1)T_n-1(x) + ... +f(n-1)T_1(x) + f(n)/2
+ *    and T_m(x) = cos(mw) is the mth order Chebyshev polynomial ( x=cos(w) )
+ *  - The function returns the value of C(x) for the input x.
+ *
+ ***********************************************************************/
+
+static Word16 Chebps (Word16 x, Word16 f[], Word16 n)
+{
+    Word16 i, cheb;
+    Word16 b0_h, b0_l, b1_h, b1_l, b2_h, b2_l;
+    Word32 t0;
+
+    b2_h = 256;                    move16 (); /* b2 = 1.0 */
+    b2_l = 0;                      move16 (); 
+
+    t0 = L_mult (x, 512);          /* 2*x                 */
+    t0 = L_mac (t0, f[1], 8192);   /* + f[1]              */
+    L_Extract (t0, &b1_h, &b1_l);  /* b1 = 2*x + f[1]     */
+
+    for (i = 2; i < n; i++)
+    {
+        t0 = Mpy_32_16 (b1_h, b1_l, x);         /* t0 = 2.0*x*b1        */
+        t0 = L_shl (t0, 1);
+        t0 = L_mac (t0, b2_h, (Word16) 0x8000); /* t0 = 2.0*x*b1 - b2   */
+        t0 = L_msu (t0, b2_l, 1);
+        t0 = L_mac (t0, f[i], 8192);            /* t0 = 2.0*x*b1 - b2 + f[i] */
+
+        L_Extract (t0, &b0_h, &b0_l);           /* b0 = 2.0*x*b1 - b2 + f[i]*/
+
+        b2_l = b1_l;               move16 ();   /* b2 = b1; */
+        b2_h = b1_h;               move16 (); 
+        b1_l = b0_l;               move16 ();   /* b1 = b0; */
+        b1_h = b0_h;               move16 (); 
+    }
+
+    t0 = Mpy_32_16 (b1_h, b1_l, x);             /* t0 = x*b1; */
+    t0 = L_mac (t0, b2_h, (Word16) 0x8000);     /* t0 = x*b1 - b2   */
+    t0 = L_msu (t0, b2_l, 1);
+    t0 = L_mac (t0, f[i], 4096);                /* t0 = x*b1 - b2 + f[i]/2 */
+
+    t0 = L_shl (t0, 6);
+
+    cheb = extract_h (t0);
+
+    return (cheb);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgsmefr/c1035pf.c	Fri Nov 25 16:18:21 2022 +0000
@@ -0,0 +1,891 @@
+#include "typedef.h"
+#include "basic_op.h"
+#include "sig_proc.h"
+#include "count.h"
+
+#define L_CODE    40
+#define NB_TRACK  5
+#define NB_PULSE  10
+#define STEP      5
+
+/* local functions */
+
+void cor_h_x (
+    Word16 h[],    /* (i)  : impulse response of weighted synthesis filter */
+    Word16 x[],    /* (i)  : target                                        */
+    Word16 dn[]    /* (o)  : correlation between target and h[]            */
+);
+
+void set_sign (
+    Word16 dn[],      /* (i/o)  : correlation between target and h[]       */
+    Word16 cn[],      /* (i)  : residual after long term prediction        */
+    Word16 sign[],    /* (o)  : sign of d[n]                               */
+    Word16 pos_max[], /* (o)  : position of maximum of dn[]                */
+    Word16 ipos[]     /* (o)  : starting position for each pulse           */
+);
+
+void cor_h (
+    Word16 h[],         /* (i)  : impulse response of weighted synthesis
+                                  filter */
+    Word16 sign[],      /* (i)  : sign of d[n]                             */
+    Word16 rr[][L_CODE] /* (o)  : matrix of autocorrelation                */
+);
+void search_10i40 (
+    Word16 dn[],         /* (i) : correlation between target and h[]       */
+    Word16 rr[][L_CODE], /* (i) : matrix of autocorrelation                */
+    Word16 ipos[],       /* (i) : starting position for each pulse         */
+    Word16 pos_max[],    /* (i) : position of maximum of dn[]              */
+    Word16 codvec[]      /* (o) : algebraic codebook vector                */
+);
+void build_code (
+    Word16 codvec[], /* (i)  : algebraic codebook vector                   */
+    Word16 sign[],   /* (i)  : sign of dn[]                                */
+    Word16 cod[],    /* (o)  : algebraic (fixed) codebook excitation       */
+    Word16 h[],      /* (i)  : impulse response of weighted synthesis filter*/
+    Word16 y[],      /* (o)  : filtered fixed codebook excitation           */
+    Word16 indx[]    /* (o)  : index of 10 pulses (position+sign+ampl)*10   */
+);
+
+void q_p (
+    Word16 *ind,   /* Pulse position                                        */
+    Word16 n       /* Pulse number                                          */
+);
+
+/*************************************************************************
+ *
+ *  FUNCTION:  code_10i40_35bits()
+ *
+ *  PURPOSE:  Searches a 35 bit algebraic codebook containing 10 pulses
+ *            in a frame of 40 samples.
+ *
+ *  DESCRIPTION:
+ *    The code contains 10 nonzero pulses: i0...i9.
+ *    All pulses can have two possible amplitudes: +1 or -1.
+ *    The 40 positions in a subframe are divided into 5 tracks of
+ *    interleaved positions. Each track contains two pulses.
+ *    The pulses can have the following possible positions:
+ *
+ *       i0, i5 :  0, 5, 10, 15, 20, 25, 30, 35.
+ *       i1, i6 :  1, 6, 11, 16, 21, 26, 31, 36.
+ *       i2, i7 :  2, 7, 12, 17, 22, 27, 32, 37.
+ *       i3, i8 :  3, 8, 13, 18, 23, 28, 33, 38.
+ *       i4, i9 :  4, 9, 14, 19, 24, 29, 34, 39.
+ *
+ *    Each pair of pulses require 1 bit for their signs and 6 bits for their
+ *    positions (3 bits + 3 bits). This results in a 35 bit codebook.
+ *    The function determines the optimal pulse signs and positions, builds
+ *    the codevector, and computes the filtered codevector.
+ *
+ *************************************************************************/
+
+void code_10i40_35bits (
+    Word16 x[],   /* (i)   : target vector                                 */
+    Word16 cn[],  /* (i)   : residual after long term prediction           */
+    Word16 h[],   /* (i)   : impulse response of weighted synthesis filter
+                             h[-L_subfr..-1] must be set to zero           */
+    Word16 cod[], /* (o)   : algebraic (fixed) codebook excitation         */
+    Word16 y[],   /* (o)   : filtered fixed codebook excitation            */
+    Word16 indx[] /* (o)   : index of 10 pulses (sign + position)          */
+)
+{
+    Word16 ipos[NB_PULSE], pos_max[NB_TRACK], codvec[NB_PULSE];
+    Word16 dn[L_CODE], sign[L_CODE];
+    Word16 rr[L_CODE][L_CODE], i;
+
+    cor_h_x (h, x, dn);
+    set_sign (dn, cn, sign, pos_max, ipos);
+    cor_h (h, sign, rr);
+    search_10i40 (dn, rr, ipos, pos_max, codvec);
+    build_code (codvec, sign, cod, h, y, indx);
+    for (i = 0; i < 10; i++)
+    {
+        q_p (&indx[i], i);
+    }
+    return;
+}
+
+/*************************************************************************
+ *
+ *  FUNCTION:  cor_h_x()
+ *
+ *  PURPOSE:  Computes correlation between target signal "x[]" and
+ *            impulse response"h[]".
+ *
+ *  DESCRIPTION:
+ *    The correlation is given by:
+ *       d[n] = sum_{i=n}^{L-1} x[i] h[i-n]      n=0,...,L-1
+ *
+ *    d[n] is normalized such that the sum of 5 maxima of d[n] corresponding
+ *    to each position track does not saturate.
+ *
+ *************************************************************************/
+void cor_h_x (
+    Word16 h[],     /* (i)   : impulse response of weighted synthesis filter */
+    Word16 x[],     /* (i)   : target                                        */
+    Word16 dn[]     /* (o)   : correlation between target and h[]            */
+)
+{
+    Word16 i, j, k;
+    Word32 s, y32[L_CODE], max, tot;
+
+    /* first keep the result on 32 bits and find absolute maximum */
+
+    tot = 5;                                     move32 (); 
+
+    for (k = 0; k < NB_TRACK; k++)
+    {
+        max = 0;                                 move32 (); 
+        for (i = k; i < L_CODE; i += STEP)
+        {
+            s = 0;                               move32 (); 
+            for (j = i; j < L_CODE; j++)
+                s = L_mac (s, x[j], h[j - i]);
+            
+            y32[i] = s;                          move32 (); 
+            
+            s = L_abs (s);
+            test (); 
+            if (L_sub (s, max) > (Word32) 0L)
+                max = s;                         move32 (); 
+        }
+        tot = L_add (tot, L_shr (max, 1));
+    }
+    
+    j = sub (norm_l (tot), 2);                   /* multiply tot by 4 */
+    
+    for (i = 0; i < L_CODE; i++)
+    {
+        dn[i] = round (L_shl (y32[i], j));       move16 (); 
+    }
+}
+
+/*************************************************************************
+ *
+ *  FUNCTION  set_sign()
+ *
+ *  PURPOSE: Builds sign[] vector according to "dn[]" and "cn[]", and modifies
+ *           dn[] to include the sign information (dn[i]=sign[i]*dn[i]).
+ *           Also finds the position of maximum of correlation in each track
+ *           and the starting position for each pulse.
+ *
+ *************************************************************************/
+
+void set_sign (
+    Word16 dn[],      /* (i/o): correlation between target and h[]         */
+    Word16 cn[],      /* (i)  : residual after long term prediction        */
+    Word16 sign[],    /* (o)  : sign of d[n]                               */
+    Word16 pos_max[], /* (o)  : position of maximum correlation            */
+    Word16 ipos[]     /* (o)  : starting position for each pulse           */
+)
+{
+    Word16 i, j;
+    Word16 val, cor, k_cn, k_dn, max, max_of_all, pos;
+    Word16 en[L_CODE];                  /* correlation vector */
+    Word32 s;
+
+    /* calculate energy for normalization of cn[] and dn[] */
+
+    s = 256;                                     move32 (); 
+    for (i = 0; i < L_CODE; i++)
+    {
+        s = L_mac (s, cn[i], cn[i]);
+    }
+    s = Inv_sqrt (s);                            move32 (); 
+    k_cn = extract_h (L_shl (s, 5));
+    
+    s = 256;                                     move32 (); 
+    for (i = 0; i < L_CODE; i++)
+    {
+        s = L_mac (s, dn[i], dn[i]);
+    }
+    s = Inv_sqrt (s);                            move32 (); 
+    k_dn = extract_h (L_shl (s, 5));
+    
+    for (i = 0; i < L_CODE; i++)
+    {
+        val = dn[i];                             move16 (); 
+        cor = round (L_shl (L_mac (L_mult (k_cn, cn[i]), k_dn, val), 10));
+
+        test (); 
+        if (cor >= 0)
+        {
+            sign[i] = 32767;                     move16 (); /* sign = +1 */
+        }
+        else
+        {
+            sign[i] = -32767;                    move16 (); /* sign = -1 */
+            cor = negate (cor);
+            val = negate (val);
+        }
+        /* modify dn[] according to the fixed sign */        
+        dn[i] = val;                             move16 (); 
+        en[i] = cor;                             move16 (); 
+    }
+    
+    max_of_all = -1;                             move16 (); 
+    for (i = 0; i < NB_TRACK; i++)
+    {
+        max = -1;                                move16 (); 
+        
+        for (j = i; j < L_CODE; j += STEP)
+        {
+            cor = en[j];                         move16 (); 
+            val = sub (cor, max);
+            test (); 
+            if (val > 0)
+            {
+                max = cor;                       move16 (); 
+                pos = j;                         move16 (); 
+            }
+        }
+        /* store maximum correlation position */
+        pos_max[i] = pos;                        move16 (); 
+        val = sub (max, max_of_all);
+        test (); 
+        if (val > 0)
+        {
+            max_of_all = max;                    move16 ();
+            /* starting position for i0 */            
+            ipos[0] = i;                         move16 (); 
+        }
+    }
+    
+    /*----------------------------------------------------------------*
+     *     Set starting position of each pulse.                       *
+     *----------------------------------------------------------------*/
+    
+    pos = ipos[0];                               move16 (); 
+    ipos[5] = pos;                               move16 (); 
+    
+    for (i = 1; i < NB_TRACK; i++)
+    {
+        pos = add (pos, 1);
+        if (sub (pos, NB_TRACK) >= 0)
+        {
+            pos = 0;                             move16 (); 
+        }
+        ipos[i] = pos;                           move16 (); 
+        ipos[i + 5] = pos;                       move16 (); 
+    }
+}
+
+void q_p (
+    Word16 *ind,        /* Pulse position */
+    Word16 n            /* Pulse number   */
+)
+{
+    static const Word16 gray[8] = {0, 1, 3, 2, 6, 4, 5, 7};
+    Word16 tmp;
+    
+    tmp = *ind;                                  move16 (); 
+    
+    test ();
+    if (sub (n, 5) < 0)
+    {
+        tmp = (tmp & 0x8) | gray[tmp & 0x7];     logic16 (); logic16 ();
+                                                 logic16 ();
+    }
+    else
+    {
+        tmp = gray[tmp & 0x7];                   logic16 (); move16 (); 
+    }
+    
+    *ind = tmp;                                  move16 (); 
+}
+
+/*************************************************************************
+ *
+ *  FUNCTION:  cor_h()
+ *
+ *  PURPOSE:  Computes correlations of h[] needed for the codebook search;
+ *            and includes the sign information into the correlations.
+ *
+ *  DESCRIPTION: The correlations are given by
+ *         rr[i][j] = sum_{n=i}^{L-1} h[n-i] h[n-j];   i>=j; i,j=0,...,L-1
+ *
+ *  and the sign information is included by
+ *         rr[i][j] = rr[i][j]*sign[i]*sign[j]
+ *
+ *************************************************************************/
+
+void cor_h (
+    Word16 h[],         /* (i) : impulse response of weighted synthesis
+                                 filter                                  */
+    Word16 sign[],      /* (i) : sign of d[n]                            */
+    Word16 rr[][L_CODE] /* (o) : matrix of autocorrelation               */
+)
+{
+    Word16 i, j, k, dec, h2[L_CODE];
+    Word32 s;
+
+    /* Scaling for maximum precision */
+
+    s = 2;                                       move32 (); 
+    for (i = 0; i < L_CODE; i++)
+        s = L_mac (s, h[i], h[i]);
+    
+    j = sub (extract_h (s), 32767);
+    test (); 
+    if (j == 0)
+    {
+        for (i = 0; i < L_CODE; i++)
+        {
+            h2[i] = shr (h[i], 1);               move16 (); 
+        }
+    }
+    else
+    {
+        s = L_shr (s, 1);
+        k = extract_h (L_shl (Inv_sqrt (s), 7));
+        k = mult (k, 32440);                     /* k = 0.99*k */
+        
+        for (i = 0; i < L_CODE; i++)
+        {
+            h2[i] = round (L_shl (L_mult (h[i], k), 9));
+                                                 move16 (); 
+        }
+    }
+    
+    /* build matrix rr[] */
+    s = 0;                                       move32 (); 
+    i = L_CODE - 1;
+    for (k = 0; k < L_CODE; k++, i--)
+    {
+        s = L_mac (s, h2[k], h2[k]);
+        rr[i][i] = round (s);                    move16 (); 
+    }
+    
+    for (dec = 1; dec < L_CODE; dec++)
+    {
+        s = 0;                                   move32 (); 
+        j = L_CODE - 1;
+        i = sub (j, dec);
+        for (k = 0; k < (L_CODE - dec); k++, i--, j--)
+        {
+            s = L_mac (s, h2[k], h2[k + dec]);
+            rr[j][i] = mult (round (s), mult (sign[i], sign[j]));
+                                                 move16 (); 
+            rr[i][j] = rr[j][i];                 move16 (); 
+        }
+    }
+}
+
+/*************************************************************************
+ *
+ *  FUNCTION  search_10i40()
+ *
+ *  PURPOSE: Search the best codevector; determine positions of the 10 pulses
+ *           in the 40-sample frame.
+ *
+ *************************************************************************/
+
+#define _1_2    (Word16)(32768L/2)
+#define _1_4    (Word16)(32768L/4)
+#define _1_8    (Word16)(32768L/8)
+#define _1_16   (Word16)(32768L/16)
+#define _1_32   (Word16)(32768L/32)
+#define _1_64   (Word16)(32768L/64)
+#define _1_128  (Word16)(32768L/128)
+
+void search_10i40 (
+    Word16 dn[],         /* (i) : correlation between target and h[]        */
+    Word16 rr[][L_CODE], /* (i) : matrix of autocorrelation                 */
+    Word16 ipos[],       /* (i) : starting position for each pulse          */
+    Word16 pos_max[],    /* (i) : position of maximum of dn[]               */
+    Word16 codvec[]      /* (o) : algebraic codebook vector                 */
+)
+{
+    Word16 i0, i1, i2, i3, i4, i5, i6, i7, i8, i9;
+    Word16 i, j, k, pos, ia, ib;
+    Word16 psk, ps, ps0, ps1, ps2, sq, sq2;
+    Word16 alpk, alp, alp_16;
+    Word16 rrv[L_CODE];
+    Word32 s, alp0, alp1, alp2;
+
+    /* fix i0 on maximum of correlation position */
+
+    i0 = pos_max[ipos[0]];                       move16 (); 
+
+    /*------------------------------------------------------------------*
+     * i1 loop:                                                         *
+     *------------------------------------------------------------------*/
+    
+    /* Default value */
+    psk = -1;                                    move16 (); 
+    alpk = 1;                                    move16 (); 
+    for (i = 0; i < NB_PULSE; i++)
+    {
+        codvec[i] = i;                           move16 ();
+    }
+
+    for (i = 1; i < NB_TRACK; i++)
+    {
+        i1 = pos_max[ipos[1]];                   move16 (); 
+        ps0 = add (dn[i0], dn[i1]);
+        alp0 = L_mult (rr[i0][i0], _1_16);
+        alp0 = L_mac (alp0, rr[i1][i1], _1_16);
+        alp0 = L_mac (alp0, rr[i0][i1], _1_8);
+        
+        /*----------------------------------------------------------------*
+         * i2 and i3 loop:                                                *
+         *----------------------------------------------------------------*/
+        
+        /* initialize 4 indices for next loop. */
+        move16 (); /* initialize "rr[i3][i3]" pointer */
+        move16 (); /* initialize "rr[i0][i3]" pointer */
+        move16 (); /* initialize "rr[i1][i3]" pointer */
+        move16 (); /* initialize "rrv[i3]" pointer    */
+        
+        for (i3 = ipos[3]; i3 < L_CODE; i3 += STEP)
+        {
+            s = L_mult (rr[i3][i3], _1_8);       /* index incr= STEP+L_CODE */
+            s = L_mac (s, rr[i0][i3], _1_4);     /* index increment = STEP  */
+            s = L_mac (s, rr[i1][i3], _1_4);     /* index increment = STEP  */
+            rrv[i3] = round (s);                 move16 (); 
+        }
+        
+        /* Default value */
+        sq = -1;                                 move16 (); 
+        alp = 1;                                 move16 (); 
+        ps = 0;                                  move16 ();
+        ia = ipos[2];                            move16 ();
+        ib = ipos[3];                            move16 ();
+        
+        /* initialize 4 indices for i2 loop. */
+        move16 (); /* initialize "dn[i2]" pointer     */
+        move16 (); /* initialize "rr[i2][i2]" pointer */
+        move16 (); /* initialize "rr[i0][i2]" pointer */
+        move16 (); /* initialize "rr[i1][i2]" pointer */
+        
+        for (i2 = ipos[2]; i2 < L_CODE; i2 += STEP)
+        {
+            /* index increment = STEP  */            
+            ps1 = add (ps0, dn[i2]);    
+            
+            /* index incr= STEP+L_CODE */
+            alp1 = L_mac (alp0, rr[i2][i2], _1_16);
+            /* index increment = STEP  */
+            alp1 = L_mac (alp1, rr[i0][i2], _1_8);
+            /* index increment = STEP  */
+            alp1 = L_mac (alp1, rr[i1][i2], _1_8);
+            
+            /* initialize 3 indices for i3 inner loop */
+            move16 (); /* initialize "dn[i3]" pointer     */
+            move16 (); /* initialize "rrv[i3]" pointer    */
+            move16 (); /* initialize "rr[i2][i3]" pointer */
+            
+            for (i3 = ipos[3]; i3 < L_CODE; i3 += STEP)
+            {
+                /* index increment = STEP */                
+                ps2 = add (ps1, dn[i3]);    
+                
+                /* index increment = STEP */
+                alp2 = L_mac (alp1, rrv[i3], _1_2);
+                /* index increment = STEP */
+                alp2 = L_mac (alp2, rr[i2][i3], _1_8);
+                
+                sq2 = mult (ps2, ps2);
+
+                alp_16 = round (alp2);
+                
+                s = L_msu (L_mult (alp, sq2), sq, alp_16);
+                
+                test (); 
+                if (s > 0)
+                {
+                    sq = sq2;                    move16 (); 
+                    ps = ps2;                    move16 (); 
+                    alp = alp_16;                move16 (); 
+                    ia = i2;                     move16 (); 
+                    ib = i3;                     move16 (); 
+                }
+            }
+        }
+        i2 = ia;                                 move16 (); 
+        i3 = ib;                                 move16 (); 
+        
+        /*----------------------------------------------------------------*
+         * i4 and i5 loop:                                                *
+         *----------------------------------------------------------------*/
+        
+        ps0 = ps;                                move16 (); 
+        alp0 = L_mult (alp, _1_2);
+        
+        /* initialize 6 indices for next loop (see i2-i3 loop) */
+        move16 (); move16 (); move16 (); move16 (); move16 (); move16 (); 
+        
+        for (i5 = ipos[5]; i5 < L_CODE; i5 += STEP)
+        {
+            s = L_mult (rr[i5][i5], _1_8);
+            s = L_mac (s, rr[i0][i5], _1_4);
+            s = L_mac (s, rr[i1][i5], _1_4);
+            s = L_mac (s, rr[i2][i5], _1_4);
+            s = L_mac (s, rr[i3][i5], _1_4);
+            rrv[i5] = round (s);                 move16 (); 
+        }
+        
+        /* Default value */
+        sq = -1;                                 move16 (); 
+        alp = 1;                                 move16 (); 
+        ps = 0;                                  move16 ();
+        ia = ipos[4];                            move16 ();
+        ib = ipos[5];                            move16 ();
+        
+        /* initialize 6 indices for i4 loop (see i2-i3 loop) */
+        move16 (); move16 (); move16 (); move16 (); move16 (); move16 (); 
+        
+        for (i4 = ipos[4]; i4 < L_CODE; i4 += STEP)
+        {
+            ps1 = add (ps0, dn[i4]);
+            
+            alp1 = L_mac (alp0, rr[i4][i4], _1_32);
+            alp1 = L_mac (alp1, rr[i0][i4], _1_16);
+            alp1 = L_mac (alp1, rr[i1][i4], _1_16);
+            alp1 = L_mac (alp1, rr[i2][i4], _1_16);
+            alp1 = L_mac (alp1, rr[i3][i4], _1_16);
+            
+            /* initialize 3 indices for i5 inner loop (see i2-i3 loop) */
+            move16 (); move16 (); move16 (); 
+            
+            for (i5 = ipos[5]; i5 < L_CODE; i5 += STEP)
+            {
+                ps2 = add (ps1, dn[i5]);
+                
+                alp2 = L_mac (alp1, rrv[i5], _1_4);
+                alp2 = L_mac (alp2, rr[i4][i5], _1_16);
+                
+                sq2 = mult (ps2, ps2);
+                
+                alp_16 = round (alp2);
+                
+                s = L_msu (L_mult (alp, sq2), sq, alp_16);
+                
+                test (); 
+                if (s > 0)
+                {
+                    sq = sq2;                    move16 (); 
+                    ps = ps2;                    move16 (); 
+                    alp = alp_16;                move16 (); 
+                    ia = i4;                     move16 (); 
+                    ib = i5;                     move16 (); 
+                }
+            }
+        }
+        i4 = ia;                                 move16 (); 
+        i5 = ib;                                 move16 (); 
+        
+        /*----------------------------------------------------------------*
+         * i6 and i7 loop:                                                *
+         *----------------------------------------------------------------*/
+        
+        ps0 = ps;                                move16 (); 
+        alp0 = L_mult (alp, _1_2);
+        
+        /* initialize 8 indices for next loop (see i2-i3 loop) */
+        move16 (); move16 (); move16 (); move16 (); 
+        move16 (); move16 (); move16 (); move16 (); 
+        
+        for (i7 = ipos[7]; i7 < L_CODE; i7 += STEP)
+        {
+            s = L_mult (rr[i7][i7], _1_16);
+            s = L_mac (s, rr[i0][i7], _1_8);
+            s = L_mac (s, rr[i1][i7], _1_8);
+            s = L_mac (s, rr[i2][i7], _1_8);
+            s = L_mac (s, rr[i3][i7], _1_8);
+            s = L_mac (s, rr[i4][i7], _1_8);
+            s = L_mac (s, rr[i5][i7], _1_8);
+            rrv[i7] = round (s);                 move16 (); 
+        }
+        
+        /* Default value */
+        sq = -1;                                 move16 (); 
+        alp = 1;                                 move16 (); 
+        ps = 0;                                  move16 ();
+        ia = ipos[6];                            move16 ();
+        ib = ipos[7];                            move16 ();
+        
+        /* initialize 8 indices for i6 loop (see i2-i3 loop) */
+        move16 (); move16 (); move16 (); move16 (); 
+        move16 (); move16 (); move16 (); move16 (); 
+        
+        for (i6 = ipos[6]; i6 < L_CODE; i6 += STEP)
+        {
+            ps1 = add (ps0, dn[i6]);
+            
+            alp1 = L_mac (alp0, rr[i6][i6], _1_64);
+            alp1 = L_mac (alp1, rr[i0][i6], _1_32);
+            alp1 = L_mac (alp1, rr[i1][i6], _1_32);
+            alp1 = L_mac (alp1, rr[i2][i6], _1_32);
+            alp1 = L_mac (alp1, rr[i3][i6], _1_32);
+            alp1 = L_mac (alp1, rr[i4][i6], _1_32);
+            alp1 = L_mac (alp1, rr[i5][i6], _1_32);
+            
+            /* initialize 3 indices for i7 inner loop (see i2-i3 loop) */
+            move16 (); move16 (); move16 (); 
+            
+            for (i7 = ipos[7]; i7 < L_CODE; i7 += STEP)
+            {
+                ps2 = add (ps1, dn[i7]);
+                
+                alp2 = L_mac (alp1, rrv[i7], _1_4);
+                alp2 = L_mac (alp2, rr[i6][i7], _1_32);
+                
+                sq2 = mult (ps2, ps2);
+                
+                alp_16 = round (alp2);
+                
+                s = L_msu (L_mult (alp, sq2), sq, alp_16);
+                
+                test (); 
+                if (s > 0)
+                {
+                    sq = sq2;                    move16 (); 
+                    ps = ps2;                    move16 (); 
+                    alp = alp_16;                move16 (); 
+                    ia = i6;                     move16 (); 
+                    ib = i7;                     move16 (); 
+                }
+            }
+        }
+        i6 = ia;                                 move16 (); 
+        i7 = ib;                                 move16 (); 
+        
+        /*----------------------------------------------------------------*
+         * i8 and i9 loop:                                                *
+         *----------------------------------------------------------------*/
+        
+        ps0 = ps;                                move16 (); 
+        alp0 = L_mult (alp, _1_2);
+        
+        /* initialize 10 indices for next loop (see i2-i3 loop) */
+        move16 (); move16 (); move16 (); move16 (); move16 (); 
+        move16 (); move16 (); move16 (); move16 (); move16 (); 
+        
+        for (i9 = ipos[9]; i9 < L_CODE; i9 += STEP)
+        {
+            s = L_mult (rr[i9][i9], _1_16);
+            s = L_mac (s, rr[i0][i9], _1_8);
+            s = L_mac (s, rr[i1][i9], _1_8);
+            s = L_mac (s, rr[i2][i9], _1_8);
+            s = L_mac (s, rr[i3][i9], _1_8);
+            s = L_mac (s, rr[i4][i9], _1_8);
+            s = L_mac (s, rr[i5][i9], _1_8);
+            s = L_mac (s, rr[i6][i9], _1_8);
+            s = L_mac (s, rr[i7][i9], _1_8);
+            rrv[i9] = round (s);                 move16 (); 
+        }
+        
+        /* Default value */
+        sq = -1;                                 move16 (); 
+        alp = 1;                                 move16 (); 
+        ps = 0;                                  move16 ();
+        ia = ipos[8];                            move16 ();
+        ib = ipos[9];                            move16 ();
+        
+        /* initialize 10 indices for i8 loop (see i2-i3 loop) */
+        move16 (); move16 (); move16 (); move16 (); move16 (); 
+        move16 (); move16 (); move16 (); move16 (); move16 (); 
+        
+        for (i8 = ipos[8]; i8 < L_CODE; i8 += STEP)
+        {
+            ps1 = add (ps0, dn[i8]);
+            
+            alp1 = L_mac (alp0, rr[i8][i8], _1_128);
+            alp1 = L_mac (alp1, rr[i0][i8], _1_64);
+            alp1 = L_mac (alp1, rr[i1][i8], _1_64);
+            alp1 = L_mac (alp1, rr[i2][i8], _1_64);
+            alp1 = L_mac (alp1, rr[i3][i8], _1_64);
+            alp1 = L_mac (alp1, rr[i4][i8], _1_64);
+            alp1 = L_mac (alp1, rr[i5][i8], _1_64);
+            alp1 = L_mac (alp1, rr[i6][i8], _1_64);
+            alp1 = L_mac (alp1, rr[i7][i8], _1_64);
+            
+            /* initialize 3 indices for i9 inner loop (see i2-i3 loop) */
+            move16 (); move16 (); move16 (); 
+            
+            for (i9 = ipos[9]; i9 < L_CODE; i9 += STEP)
+            {
+                ps2 = add (ps1, dn[i9]);
+                
+                alp2 = L_mac (alp1, rrv[i9], _1_8);
+                alp2 = L_mac (alp2, rr[i8][i9], _1_64);
+                
+                sq2 = mult (ps2, ps2);
+                
+                alp_16 = round (alp2);
+                
+                s = L_msu (L_mult (alp, sq2), sq, alp_16);
+                
+                test (); 
+                if (s > 0)
+                {
+                    sq = sq2;                    move16 (); 
+                    ps = ps2;                    move16 (); 
+                    alp = alp_16;                move16 (); 
+                    ia = i8;                     move16 (); 
+                    ib = i9;                     move16 (); 
+                }
+            }
+        }
+        
+        /*----------------------------------------------------------------*
+         * memorise codevector if this one is better than the last one.   *
+         *----------------------------------------------------------------*/
+        
+        s = L_msu (L_mult (alpk, sq), psk, alp);
+        
+        test (); 
+        if (s > 0)
+        {
+            psk = sq;                            move16 (); 
+            alpk = alp;                          move16 (); 
+            codvec[0] = i0;                      move16 (); 
+            codvec[1] = i1;                      move16 (); 
+            codvec[2] = i2;                      move16 (); 
+            codvec[3] = i3;                      move16 (); 
+            codvec[4] = i4;                      move16 (); 
+            codvec[5] = i5;                      move16 (); 
+            codvec[6] = i6;                      move16 (); 
+            codvec[7] = i7;                      move16 (); 
+            codvec[8] = ia;                      move16 (); 
+            codvec[9] = ib;                      move16 (); 
+        }
+        /*----------------------------------------------------------------*
+         * Cyclic permutation of i1,i2,i3,i4,i5,i6,i7,i8 and i9.          *
+         *----------------------------------------------------------------*/
+        
+        pos = ipos[1];                           move16 (); 
+        for (j = 1, k = 2; k < NB_PULSE; j++, k++)
+        {
+            ipos[j] = ipos[k];                   move16 (); 
+        }
+        ipos[NB_PULSE - 1] = pos;                move16 (); 
+}
+}
+
+/*************************************************************************
+ *
+ *  FUNCTION:  build_code()
+ *
+ *  PURPOSE: Builds the codeword, the filtered codeword and index of the
+ *           codevector, based on the signs and positions of 10 pulses.
+ *
+ *************************************************************************/
+
+void build_code (
+    Word16 codvec[], /* (i)  : position of pulses                           */
+    Word16 sign[],   /* (i)  : sign of d[n]                                 */
+    Word16 cod[],    /* (o)  : innovative code vector                       */
+    Word16 h[],      /* (i)  : impulse response of weighted synthesis filter*/
+    Word16 y[],      /* (o)  : filtered innovative code                     */
+    Word16 indx[]    /* (o)  : index of 10 pulses (sign+position)           */
+)
+{
+    Word16 i, j, k, track, index, _sign[NB_PULSE];
+    Word16 *p0, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9;
+    Word32 s;
+
+    for (i = 0; i < L_CODE; i++)
+    {
+        cod[i] = 0;                              move16 (); 
+    }
+    for (i = 0; i < NB_TRACK; i++)
+    {
+        indx[i] = -1;                            move16 (); 
+    }
+    
+    for (k = 0; k < NB_PULSE; k++)
+    {
+        /* read pulse position */            
+        i = codvec[k];                           move16 ();
+        /* read sign           */        
+        j = sign[i];                             move16 (); 
+        
+        index = mult (i, 6554);                  /* index = pos/5       */
+        /* track = pos%5 */
+        track = sub (i, extract_l (L_shr (L_mult (index, 5), 1)));
+        test (); 
+        if (j > 0)
+        {
+            cod[i] = add (cod[i], 4096);
+            _sign[k] = 8192;                     move16 (); 
+            
+        }
+        else
+        {
+            cod[i] = sub (cod[i], 4096);
+            _sign[k] = -8192;                    move16 (); 
+            index = add (index, 8);
+        }
+        
+        test (); 
+        if (indx[track] < 0)
+        {
+            indx[track] = index;                 move16 (); 
+        }
+        else
+        {
+            test (); logic16 (); logic16 (); 
+            if (((index ^ indx[track]) & 8) == 0)
+            {
+                /* sign of 1st pulse == sign of 2nd pulse */
+                
+                test (); 
+                if (sub (indx[track], index) <= 0)
+                {
+                    indx[track + 5] = index;     move16 (); 
+                }
+                else
+                {
+                    indx[track + 5] = indx[track];
+                                                 move16 (); 
+                    indx[track] = index;         move16 (); 
+                }
+            }
+            else
+            {
+                /* sign of 1st pulse != sign of 2nd pulse */
+                
+                test (); logic16 (); logic16 (); 
+                if (sub ((indx[track] & 7), (index & 7)) <= 0)
+                {
+                    indx[track + 5] = indx[track];
+                                                 move16 (); 
+                    indx[track] = index;         move16 (); 
+                }
+                else
+                {
+                    indx[track + 5] = index;     move16 (); 
+                }
+            }
+        }
+    }
+    
+    p0 = h - codvec[0];                          move16 (); 
+    p1 = h - codvec[1];                          move16 (); 
+    p2 = h - codvec[2];                          move16 (); 
+    p3 = h - codvec[3];                          move16 (); 
+    p4 = h - codvec[4];                          move16 (); 
+    p5 = h - codvec[5];                          move16 (); 
+    p6 = h - codvec[6];                          move16 (); 
+    p7 = h - codvec[7];                          move16 (); 
+    p8 = h - codvec[8];                          move16 (); 
+    p9 = h - codvec[9];                          move16 (); 
+     
+    for (i = 0; i < L_CODE; i++)
+    {
+        s = 0;                                   move32 (); 
+        s = L_mac (s, *p0++, _sign[0]);
+        s = L_mac (s, *p1++, _sign[1]);
+        s = L_mac (s, *p2++, _sign[2]);
+        s = L_mac (s, *p3++, _sign[3]);
+        s = L_mac (s, *p4++, _sign[4]);
+        s = L_mac (s, *p5++, _sign[5]);
+        s = L_mac (s, *p6++, _sign[6]);
+        s = L_mac (s, *p7++, _sign[7]);
+        s = L_mac (s, *p8++, _sign[8]);
+        s = L_mac (s, *p9++, _sign[9]);
+        y[i] = round (s);                        move16 (); 
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgsmefr/cod_12k2.c	Fri Nov 25 16:18:21 2022 +0000
@@ -0,0 +1,834 @@
+/***************************************************************************
+ *
+ *  FILE NAME:    cod_12k2.c
+ *
+ *  FUNCTIONS DEFINED IN THIS FILE:
+ *                   Coder_12k2  and  Init_Coder_12k2
+ *
+ *
+ *  Init_Coder_12k2(void):
+ *      Initialization of variables for the coder section.
+ *
+ *  Coder_12k2(Word16 ana[], Word16 synth[]):
+ *      Speech encoder routine operating on a frame basis.
+ *
+
+***************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "sig_proc.h"
+#include "count.h"
+#include "codec.h"
+#include "cnst.h"
+
+#include "window2.tab"
+
+#include "vad.h"
+#include "dtx.h"
+
+/*-----------------------------------------------------------*
+ *    Coder constant parameters (defined in "cnst.h")        *
+ *-----------------------------------------------------------*
+ *   L_WINDOW    : LPC analysis window size                  *
+ *   L_FRAME     : Frame size                                *
+ *   L_FRAME_BY2 : Half the frame size                       *
+ *   L_SUBFR     : Sub-frame size                            *
+ *   M           : LPC order                                 *
+ *   MP1         : LPC order+1                               *
+ *   L_TOTAL     : Total size of speech buffer               *
+ *   PIT_MIN     : Minimum pitch lag                         *
+ *   PIT_MAX     : Maximum pitch lag                         *
+ *   L_INTERPOL  : Length of filter for interpolation        *
+ *-----------------------------------------------------------*/
+
+/*--------------------------------------------------------*
+ *         Static memory allocation.                      *
+ *--------------------------------------------------------*/
+
+ /* Speech vector */
+
+static Word16 old_speech[L_TOTAL];
+static Word16 *speech, *p_window, *p_window_mid;
+Word16 *new_speech;             /* Global variable */
+
+ /* Weight speech vector */
+
+static Word16 old_wsp[L_FRAME + PIT_MAX];
+static Word16 *wsp;
+
+ /* Excitation vector */
+
+static Word16 old_exc[L_FRAME + PIT_MAX + L_INTERPOL];
+static Word16 *exc;
+
+ /* Zero vector */
+
+static Word16 ai_zero[L_SUBFR + MP1];
+static Word16 *zero;
+
+ /* Impulse response vector */
+
+static Word16 *h1;
+static Word16 hvec[L_SUBFR * 2];
+
+ /* Spectral expansion factors */
+
+static const Word16 F_gamma1[M] =
+{
+    29491, 26542, 23888, 21499, 19349,
+    17414, 15672, 14105, 12694, 11425
+};
+static const Word16 F_gamma2[M] =
+{
+    19661, 11797, 7078, 4247, 2548,
+    1529, 917, 550, 330, 198
+};
+
+ /* Lsp (Line spectral pairs) */
+
+static Word16 lsp_old[M];
+static Word16 lsp_old_q[M];
+
+ /* Filter's memory */
+
+static Word16 mem_syn[M], mem_w0[M], mem_w[M];
+static Word16 mem_err[M + L_SUBFR], *error;
+
+/***************************************************************************
+ *  FUNCTION:   Init_Coder_12k2
+ *
+ *  PURPOSE:   Initialization of variables for the coder section.
+ *
+ *  DESCRIPTION:
+ *       - initilize pointers to speech buffer
+ *       - initialize static  pointers
+ *       - set static vectors to zero
+ *
+ ***************************************************************************/
+
+void Init_Coder_12k2 (void)
+{
+
+/*--------------------------------------------------------------------------*
+ *          Initialize pointers to speech vector.                           *
+ *--------------------------------------------------------------------------*/
+
+    new_speech = old_speech + L_TOTAL - L_FRAME;/* New speech     */
+    speech = new_speech;                        /* Present frame  */
+    p_window = old_speech + L_TOTAL - L_WINDOW; /* For LPC window */
+    p_window_mid = p_window;                    /* For LPC window */
+
+    /* Initialize static pointers */
+
+    wsp = old_wsp + PIT_MAX;
+    exc = old_exc + PIT_MAX + L_INTERPOL;
+    zero = ai_zero + MP1;
+    error = mem_err + M;
+    h1 = &hvec[L_SUBFR];
+
+    /* Static vectors to zero */
+
+    Set_zero (old_speech, L_TOTAL);
+    Set_zero (old_exc, PIT_MAX + L_INTERPOL);
+    Set_zero (old_wsp, PIT_MAX);
+    Set_zero (mem_syn, M);
+    Set_zero (mem_w, M);
+    Set_zero (mem_w0, M);
+    Set_zero (mem_err, M);
+    Set_zero (zero, L_SUBFR);
+    Set_zero (hvec, L_SUBFR);   /* set to zero "h1[-L_SUBFR..-1]" */
+
+    /* Initialize lsp_old [] */
+
+    lsp_old[0] = 30000;
+    lsp_old[1] = 26000;
+    lsp_old[2] = 21000;
+    lsp_old[3] = 15000;
+    lsp_old[4] = 8000;
+    lsp_old[5] = 0;
+    lsp_old[6] = -8000;
+    lsp_old[7] = -15000;
+    lsp_old[8] = -21000;
+    lsp_old[9] = -26000;
+
+    /* Initialize lsp_old_q[] */
+
+    Copy (lsp_old, lsp_old_q, M);
+
+    return;
+}
+
+/***************************************************************************
+ *   FUNCTION:   Coder_12k2
+ *
+ *   PURPOSE:  Principle encoder routine.
+ *
+ *   DESCRIPTION: This function is called every 20 ms speech frame,
+ *       operating on the newly read 160 speech samples. It performs the
+ *       principle encoding functions to produce the set of encoded parameters
+ *       which include the LSP, adaptive codebook, and fixed codebook
+ *       quantization indices (addresses and gains).
+ *
+ *   INPUTS:
+ *       No input arguments are passed to this function. However, before
+ *       calling this function, 160 new speech data samples should be copied to
+ *       the vector new_speech[]. This is a global pointer which is declared in
+ *       this file (it points to the end of speech buffer minus 160).
+ *
+ *   OUTPUTS:
+ *
+ *       ana[]:     vector of analysis parameters.
+ *       synth[]:   Local synthesis speech (for debugging purposes)
+ *
+ ***************************************************************************/
+
+void Coder_12k2 (
+    Word16 ana[],    /* output  : Analysis parameters */
+    Word16 synth[]   /* output  : Local synthesis     */
+)
+{
+    /* LPC coefficients */
+
+    Word16 r_l[MP1], r_h[MP1];      /* Autocorrelations lo and hi           */
+    Word16 A_t[(MP1) * 4];          /* A(z) unquantized for the 4 subframes */
+    Word16 Aq_t[(MP1) * 4];         /* A(z)   quantized for the 4 subframes */
+    Word16 Ap1[MP1];                /* A(z) with spectral expansion         */
+    Word16 Ap2[MP1];                /* A(z) with spectral expansion         */
+    Word16 *A, *Aq;                 /* Pointer on A_t and Aq_t              */
+    Word16 lsp_new[M], lsp_new_q[M];/* LSPs at 4th subframe                 */
+    Word16 lsp_mid[M], lsp_mid_q[M];/* LSPs at 2nd subframe                 */
+
+    /* Other vectors */
+
+    Word16 xn[L_SUBFR];            /* Target vector for pitch search        */
+    Word16 xn2[L_SUBFR];           /* Target vector for codebook search     */
+    Word16 res2[L_SUBFR];          /* Long term prediction residual         */
+    Word16 code[L_SUBFR];          /* Fixed codebook excitation             */
+    Word16 y1[L_SUBFR];            /* Filtered adaptive excitation          */
+    Word16 y2[L_SUBFR];            /* Filtered fixed codebook excitation    */
+
+    /* Scalars */
+
+    Word16 i, j, k, i_subfr;
+    Word16 T_op, T0, T0_min, T0_max, T0_frac;
+    Word16 gain_pit, gain_code, pit_flag, pit_sharp;
+    Word16 temp;
+    Word32 L_temp;
+
+    Word16 scal_acf, VAD_flag, lags[2], rc[4];
+
+    extern Word16 ptch;
+    extern Word16 txdtx_ctrl, CN_excitation_gain;
+    extern Word32 L_pn_seed_tx;
+    extern Word16 dtx_mode;
+
+    /*----------------------------------------------------------------------*
+     *  - Perform LPC analysis: (twice per frame)                           *
+     *       * autocorrelation + lag windowing                              *
+     *       * Levinson-Durbin algorithm to find a[]                        *
+     *       * convert a[] to lsp[]                                         *
+     *       * quantize and code the LSPs                                   *
+     *       * find the interpolated LSPs and convert to a[] for all        *
+     *         subframes (both quantized and unquantized)                   *
+     *----------------------------------------------------------------------*/
+
+    /* LP analysis centered at 2nd subframe */
+
+
+    scal_acf = Autocorr (p_window_mid, M, r_h, r_l, window_160_80);
+                                /* Autocorrelations */
+
+#if (WMOPS)
+    fwc ();                     /* function worst case */
+#endif
+
+    Lag_window (M, r_h, r_l);   /* Lag windowing    */
+
+#if (WMOPS)
+    fwc ();                     /* function worst case */
+#endif
+
+    Levinson (r_h, r_l, &A_t[MP1], rc); /* Levinson-Durbin  */
+
+#if (WMOPS)
+    fwc ();                     /* function worst case */
+#endif
+
+    Az_lsp (&A_t[MP1], lsp_mid, lsp_old); /* From A(z) to lsp */
+
+#if (WMOPS)
+    fwc ();                     /* function worst case */
+#endif
+
+    /* LP analysis centered at 4th subframe */
+
+    /* Autocorrelations */
+    scal_acf = Autocorr (p_window, M, r_h, r_l, window_232_8);
+
+#if (WMOPS)
+    fwc ();                     /* function worst case */
+#endif
+
+    Lag_window (M, r_h, r_l);   /* Lag windowing    */
+
+#if (WMOPS)
+    fwc ();                     /* function worst case */
+#endif
+
+    Levinson (r_h, r_l, &A_t[MP1 * 3], rc); /* Levinson-Durbin  */
+
+#if (WMOPS)
+    fwc ();                     /* function worst case */
+#endif
+
+    Az_lsp (&A_t[MP1 * 3], lsp_new, lsp_mid); /* From A(z) to lsp */
+
+#if (WMOPS)
+    fwc ();                     /* function worst case */
+#endif
+
+    if (dtx_mode == 1)
+    {
+        /* DTX enabled, make voice activity decision */
+        VAD_flag = vad_computation (r_h, r_l, scal_acf, rc, ptch);
+                                                                move16 (); 
+
+        tx_dtx (VAD_flag, &txdtx_ctrl); /* TX DTX handler */
+    }
+    else
+    {
+        /* DTX disabled, active speech in every frame */
+        VAD_flag = 1;
+        txdtx_ctrl = TX_VAD_FLAG | TX_SP_FLAG;
+    }
+
+    /* LSP quantization (lsp_mid[] and lsp_new[] jointly quantized) */
+
+    Q_plsf_5 (lsp_mid, lsp_new, lsp_mid_q, lsp_new_q, ana, txdtx_ctrl);
+
+#if (WMOPS)
+    fwc ();                     /* function worst case */
+#endif
+    ana += 5;                                                   move16 (); 
+
+    /*--------------------------------------------------------------------*
+     * Find interpolated LPC parameters in all subframes (both quantized  *
+     * and unquantized).                                                  *
+     * The interpolated parameters are in array A_t[] of size (M+1)*4     *
+     * and the quantized interpolated parameters are in array Aq_t[]      *
+     *--------------------------------------------------------------------*/
+
+    Int_lpc2 (lsp_old, lsp_mid, lsp_new, A_t);
+
+#if (WMOPS)
+    fwc ();                     /* function worst case */
+#endif
+
+    test (); logic16 (); 
+    if ((txdtx_ctrl & TX_SP_FLAG) != 0)
+    {
+        Int_lpc (lsp_old_q, lsp_mid_q, lsp_new_q, Aq_t);
+
+        /* update the LSPs for the next frame */
+        for (i = 0; i < M; i++)
+        {
+            lsp_old[i] = lsp_new[i];                            move16 (); 
+            lsp_old_q[i] = lsp_new_q[i];                        move16 (); 
+        }
+    }
+    else
+    {
+        /* Use unquantized LPC parameters in case of no speech activity */
+        for (i = 0; i < MP1; i++)
+        {
+            Aq_t[i] = A_t[i];                                   move16 (); 
+            Aq_t[i + MP1] = A_t[i + MP1];                       move16 (); 
+            Aq_t[i + MP1 * 2] = A_t[i + MP1 * 2];               move16 (); 
+            Aq_t[i + MP1 * 3] = A_t[i + MP1 * 3];               move16 (); 
+        }
+
+        /* update the LSPs for the next frame */
+        for (i = 0; i < M; i++)
+        {
+            lsp_old[i] = lsp_new[i];                            move16 (); 
+            lsp_old_q[i] = lsp_new[i];                          move16 (); 
+        }
+    }
+
+#if (WMOPS)
+    fwc ();                     /* function worst case */
+#endif
+
+    /*----------------------------------------------------------------------*
+     * - Find the weighted input speech wsp[] for the whole speech frame    *
+     * - Find the open-loop pitch delay for first 2 subframes               *
+     * - Set the range for searching closed-loop pitch in 1st subframe      *
+     * - Find the open-loop pitch delay for last 2 subframes                *
+     *----------------------------------------------------------------------*/
+
+    A = A_t;                                                    move16 (); 
+    for (i = 0; i < L_FRAME; i += L_SUBFR)
+    {
+        Weight_Ai (A, F_gamma1, Ap1);
+
+#if (WMOPS)
+        fwc ();                 /* function worst case */
+#endif
+
+        Weight_Ai (A, F_gamma2, Ap2);
+
+#if (WMOPS)
+        fwc ();                 /* function worst case */
+#endif
+
+        Residu (Ap1, &speech[i], &wsp[i], L_SUBFR);
+
+#if (WMOPS)
+        fwc ();                 /* function worst case */
+#endif
+
+        Syn_filt (Ap2, &wsp[i], &wsp[i], L_SUBFR, mem_w, 1);
+
+#if (WMOPS)
+        fwc ();                 /* function worst case */
+#endif
+
+        A += MP1;                                               move16 (); 
+    }
+
+    /* Find open loop pitch lag for first two subframes */
+
+    T_op = Pitch_ol (wsp, PIT_MIN, PIT_MAX, L_FRAME_BY2);       move16 (); 
+
+#if (WMOPS)
+    fwc ();                     /* function worst case */
+#endif
+
+    lags[0] = T_op;                                             move16 (); 
+
+    test (); logic16 (); 
+    if ((txdtx_ctrl & TX_SP_FLAG) != 0)
+    {
+        /* Range for closed loop pitch search in 1st subframe */
+
+        T0_min = sub (T_op, 3);
+        test (); 
+        if (sub (T0_min, PIT_MIN) < 0)
+        {
+            T0_min = PIT_MIN;                                   move16 (); 
+        }
+        T0_max = add (T0_min, 6);
+        test (); 
+        if (sub (T0_max, PIT_MAX) > 0)
+        {
+            T0_max = PIT_MAX;                                   move16 (); 
+            T0_min = sub (T0_max, 6);
+        }
+#if (WMOPS)
+        fwc ();                 /* function worst case */
+#endif
+    }
+    /* Find open loop pitch lag for last two subframes */
+
+    T_op = Pitch_ol (&wsp[L_FRAME_BY2], PIT_MIN, PIT_MAX, L_FRAME_BY2);
+                                                                move16 (); 
+
+#if (WMOPS)
+    fwc ();                     /* function worst case */
+#endif
+
+    if (dtx_mode == 1)
+    {
+        lags[1] = T_op;                                         move16 (); 
+        periodicity_update (lags, &ptch);
+    }
+    /*----------------------------------------------------------------------*
+     *          Loop for every subframe in the analysis frame               *
+     *----------------------------------------------------------------------*
+     *  To find the pitch and innovation parameters. The subframe size is   *
+     *  L_SUBFR and the loop is repeated L_FRAME/L_SUBFR times.             *
+     *     - find the weighted LPC coefficients                             *
+     *     - find the LPC residual signal res[]                             *
+     *     - compute the target signal for pitch search                     *
+     *     - compute impulse response of weighted synthesis filter (h1[])   *
+     *     - find the closed-loop pitch parameters                          *
+     *     - encode the pitch delay                                         *
+     *     - update the impulse response h1[] by including pitch            *
+     *     - find target vector for codebook search                         *
+     *     - codebook search                                                *
+     *     - encode codebook address                                        *
+     *     - VQ of pitch and codebook gains                                 *
+     *     - find synthesis speech                                          *
+     *     - update states of weighting filter                              *
+     *----------------------------------------------------------------------*/
+
+    /* pointer to interpolated LPC parameters          */
+    A = A_t;                                                    move16 ();
+    /* pointer to interpolated quantized LPC parameters */    
+    Aq = Aq_t;                                                  move16 (); 
+
+    for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)
+    {
+
+        test (); logic16 (); 
+        if ((txdtx_ctrl & TX_SP_FLAG) != 0)
+        {
+
+            /*---------------------------------------------------------------*
+             * Find the weighted LPC coefficients for the weighting filter.  *
+             *---------------------------------------------------------------*/
+
+            Weight_Ai (A, F_gamma1, Ap1);
+
+#if (WMOPS)
+            fwc ();             /* function worst case */
+#endif
+
+            Weight_Ai (A, F_gamma2, Ap2);
+
+#if (WMOPS)
+            fwc ();             /* function worst case */
+#endif
+
+            /*---------------------------------------------------------------*
+             * Compute impulse response, h1[], of weighted synthesis filter  *
+             *---------------------------------------------------------------*/
+
+            for (i = 0; i <= M; i++)
+            {
+                ai_zero[i] = Ap1[i];                            move16 (); 
+            }
+
+            Syn_filt (Aq, ai_zero, h1, L_SUBFR, zero, 0);
+
+#if (WMOPS)
+            fwc ();             /* function worst case */
+#endif
+
+            Syn_filt (Ap2, h1, h1, L_SUBFR, zero, 0);
+
+#if (WMOPS)
+            fwc ();             /* function worst case */
+#endif
+
+        }
+        /*---------------------------------------------------------------*
+         *          Find the target vector for pitch search:             *
+         *---------------------------------------------------------------*/
+
+        Residu (Aq, &speech[i_subfr], res2, L_SUBFR);   /* LPC residual */
+
+#if (WMOPS)
+        fwc ();                 /* function worst case */
+#endif
+
+        test (); logic16 (); 
+        if ((txdtx_ctrl & TX_SP_FLAG) == 0)
+        {
+            /* Compute comfort noise excitation gain based on
+            LP residual energy */
+
+            CN_excitation_gain = compute_CN_excitation_gain (res2);
+            move16 (); 
+        }
+        else
+        {
+            Copy (res2, &exc[i_subfr], L_SUBFR);
+
+#if (WMOPS)
+            fwc ();             /* function worst case */
+#endif
+
+            Syn_filt (Aq, &exc[i_subfr], error, L_SUBFR, mem_err, 0);
+
+#if (WMOPS)
+            fwc ();             /* function worst case */
+#endif
+
+            Residu (Ap1, error, xn, L_SUBFR);
+
+#if (WMOPS)
+            fwc ();             /* function worst case */
+#endif
+
+            Syn_filt (Ap2, xn, xn, L_SUBFR, mem_w0, 0); /* target signal xn[]*/
+
+#if (WMOPS)
+            fwc ();             /* function worst case */
+#endif
+
+            /*--------------------------------------------------------------*
+             *                 Closed-loop fractional pitch search          *
+             *--------------------------------------------------------------*/
+
+            /* flag for first and 3th subframe */            
+            pit_flag = i_subfr;                                 move16 (); 
+            test (); 
+            /* set t0_min and t0_max for 3th subf.*/
+            if (sub (i_subfr, L_FRAME_BY2) == 0)
+            {
+                T0_min = sub (T_op, 3);
+
+                test (); 
+                if (sub (T0_min, PIT_MIN) < 0)
+                {
+                    T0_min = PIT_MIN;                           move16 (); 
+                }
+                T0_max = add (T0_min, 6);
+                test (); 
+                if (sub (T0_max, PIT_MAX) > 0)
+                {
+                    T0_max = PIT_MAX;                           move16 (); 
+                    T0_min = sub (T0_max, 6);
+                }
+                pit_flag = 0;                                   move16 (); 
+            }
+#if (WMOPS)
+            fwc ();             /* function worst case */
+#endif
+
+            T0 = Pitch_fr6 (&exc[i_subfr], xn, h1, L_SUBFR, T0_min, T0_max,
+                            pit_flag, &T0_frac);                move16 (); 
+
+#if (WMOPS)
+            fwc ();             /* function worst case */
+#endif
+
+            *ana = Enc_lag6 (T0, &T0_frac, &T0_min, &T0_max, PIT_MIN,
+                             PIT_MAX, pit_flag);
+            move16 (); 
+
+#if (WMOPS)
+            fwc ();             /* function worst case */
+#endif
+        }
+        ana++;
+        /* Incrementation of ana is done here to work also
+        when no speech activity is present */
+
+        test (); logic16 (); 
+
+        if ((txdtx_ctrl & TX_SP_FLAG) != 0)
+        {
+
+            /*---------------------------------------------------------------*
+             * - find unity gain pitch excitation (adaptive codebook entry)  *
+             *   with fractional interpolation.                              *
+             * - find filtered pitch exc. y1[]=exc[] convolved with h1[]     *
+             * - compute pitch gain and limit between 0 and 1.2              *
+             * - update target vector for codebook search                    *
+             * - find LTP residual.                                          *
+             *---------------------------------------------------------------*/
+
+            Pred_lt_6 (&exc[i_subfr], T0, T0_frac, L_SUBFR);
+
+#if (WMOPS)
+            fwc ();             /* function worst case */
+#endif
+
+            Convolve (&exc[i_subfr], h1, y1, L_SUBFR);
+
+#if (WMOPS)
+            fwc ();             /* function worst case */
+#endif
+
+            gain_pit = G_pitch (xn, y1, L_SUBFR);      move16 (); 
+
+#if (WMOPS)
+            fwc ();             /* function worst case */
+#endif
+
+            *ana = q_gain_pitch (&gain_pit);                    move16 (); 
+
+#if (WMOPS)
+            fwc ();             /* function worst case */
+#endif
+
+        }
+        else
+        {
+            gain_pit = 0;                                       move16 (); 
+        }
+
+        ana++;                  /* Incrementation of ana is done here to work
+                                   also when no speech activity is present */
+
+        test (); logic16 (); 
+
+        if ((txdtx_ctrl & TX_SP_FLAG) != 0)
+        {
+            /* xn2[i]   = xn[i] - y1[i] * gain_pit  */
+            /* res2[i] -= exc[i+i_subfr] * gain_pit */
+
+            for (i = 0; i < L_SUBFR; i++)
+            {
+                L_temp = L_mult (y1[i], gain_pit);
+                L_temp = L_shl (L_temp, 3);
+                xn2[i] = sub (xn[i], extract_h (L_temp));       move16 (); 
+
+                L_temp = L_mult (exc[i + i_subfr], gain_pit);
+                L_temp = L_shl (L_temp, 3);
+                res2[i] = sub (res2[i], extract_h (L_temp));    move16 (); 
+            }
+
+#if (WMOPS)
+            fwc ();             /* function worst case */
+#endif
+
+            /*-------------------------------------------------------------*
+             * - include pitch contribution into impulse resp. h1[]        *
+             *-------------------------------------------------------------*/
+
+            /* pit_sharp = gain_pit;                   */
+            /* if (pit_sharp > 1.0) pit_sharp = 1.0;   */
+
+            pit_sharp = shl (gain_pit, 3);
+
+            for (i = T0; i < L_SUBFR; i++)
+            {
+                temp = mult (h1[i - T0], pit_sharp);
+                h1[i] = add (h1[i], temp);                      move16 (); 
+            }
+
+#if (WMOPS)
+            fwc ();             /* function worst case */
+#endif
+
+            /*--------------------------------------------------------------*
+             * - Innovative codebook search (find index and gain)           *
+             *--------------------------------------------------------------*/
+
+            code_10i40_35bits (xn2, res2, h1, code, y2, ana);
+
+#if (WMOPS)
+            fwc ();             /* function worst case */
+#endif
+
+        }
+        else
+        {
+            build_CN_code (code, &L_pn_seed_tx);
+        }
+        ana += 10;                                              move16 (); 
+
+        test (); logic16 (); 
+        if ((txdtx_ctrl & TX_SP_FLAG) != 0)
+        {
+
+            /*-------------------------------------------------------*
+             * - Add the pitch contribution to code[].               *
+             *-------------------------------------------------------*/
+
+            for (i = T0; i < L_SUBFR; i++)
+            {
+                temp = mult (code[i - T0], pit_sharp);
+                code[i] = add (code[i], temp);                  move16 (); 
+            }
+
+#if (WMOPS)
+            fwc ();             /* function worst case */
+#endif
+
+            /*------------------------------------------------------*
+             * - Quantization of fixed codebook gain.               *
+             *------------------------------------------------------*/
+
+            gain_code = G_code (xn2, y2);                       move16 (); 
+
+#if (WMOPS)
+            fwc ();             /* function worst case */
+#endif
+
+        }
+        *ana++ = q_gain_code (code, L_SUBFR, &gain_code, txdtx_ctrl, i_subfr);
+        move16 (); 
+
+#if (WMOPS)
+        fwc ();                 /* function worst case */
+#endif
+
+        /*------------------------------------------------------*
+         * - Find the total excitation                          *
+         * - find synthesis speech corresponding to exc[]       *
+         * - update filter memories for finding the target      *
+         *   vector in the next subframe                        *
+         *   (update mem_err[] and mem_w0[])                    *
+         *------------------------------------------------------*/
+
+        for (i = 0; i < L_SUBFR; i++)
+        {
+            /* exc[i] = gain_pit*exc[i] + gain_code*code[i]; */
+
+            L_temp = L_mult (exc[i + i_subfr], gain_pit);
+            L_temp = L_mac (L_temp, code[i], gain_code);
+            L_temp = L_shl (L_temp, 3);
+            exc[i + i_subfr] = round (L_temp);                  move16 (); 
+        }
+
+#if (WMOPS)
+        fwc ();                 /* function worst case */
+#endif
+
+        Syn_filt (Aq, &exc[i_subfr], &synth[i_subfr], L_SUBFR, mem_syn, 1);
+
+#if (WMOPS)
+        fwc ();                 /* function worst case */
+#endif
+
+        test (); logic16 (); 
+        if ((txdtx_ctrl & TX_SP_FLAG) != 0)
+        {
+
+            for (i = L_SUBFR - M, j = 0; i < L_SUBFR; i++, j++)
+            {
+                mem_err[j] = sub (speech[i_subfr + i], synth[i_subfr + i]);
+                                                                move16 (); 
+                temp = extract_h (L_shl (L_mult (y1[i], gain_pit), 3));
+                k = extract_h (L_shl (L_mult (y2[i], gain_code), 5));
+                mem_w0[j] = sub (xn[i], add (temp, k));         move16 (); 
+            }
+        }
+        else
+        {
+            for (j = 0; j < M; j++)
+            {
+                mem_err[j] = 0;                                 move16 (); 
+                mem_w0[j] = 0;                                  move16 (); 
+            }
+        }
+
+#if (WMOPS)
+        fwc ();                 /* function worst case */
+#endif
+        /* interpolated LPC parameters for next subframe */
+        A += MP1;                                               move16 (); 
+        Aq += MP1;                                              move16 (); 
+    }
+
+    /*--------------------------------------------------*
+     * Update signal for next frame.                    *
+     * -> shift to the left by L_FRAME:                 *
+     *     speech[], wsp[] and  exc[]                   *
+     *--------------------------------------------------*/
+
+    Copy (&old_speech[L_FRAME], &old_speech[0], L_TOTAL - L_FRAME);
+
+#if (WMOPS)
+    fwc ();                     /* function worst case */
+#endif
+
+    Copy (&old_wsp[L_FRAME], &old_wsp[0], PIT_MAX);
+
+#if (WMOPS)
+    fwc ();                     /* function worst case */
+#endif
+
+    Copy (&old_exc[L_FRAME], &old_exc[0], PIT_MAX + L_INTERPOL);
+
+#if (WMOPS)
+    fwc ();                     /* function worst case */
+#endif
+
+    return;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgsmefr/convolve.c	Fri Nov 25 16:18:21 2022 +0000
@@ -0,0 +1,43 @@
+/*************************************************************************
+ *
+ *  FUNCTION:   Convolve
+ *
+ *  PURPOSE:
+ *     Perform the convolution between two vectors x[] and h[] and
+ *     write the result in the vector y[]. All vectors are of length L
+ *     and only the first L samples of the convolution are computed.
+ *
+ *  DESCRIPTION:
+ *     The convolution is given by
+ *
+ *          y[n] = sum_{i=0}^{n} x[i] h[n-i],        n=0,...,L-1
+ *
+ *************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "count.h"
+
+void Convolve (
+    Word16 x[],        /* (i)     : input vector                           */
+    Word16 h[],        /* (i)     : impulse response                       */
+    Word16 y[],        /* (o)     : output vector                          */
+    Word16 L           /* (i)     : vector size                            */
+)
+{
+    Word16 i, n;
+    Word32 s;
+
+    for (n = 0; n < L; n++)
+    {
+        s = 0;                  move32 (); 
+        for (i = 0; i <= n; i++)
+        {
+            s = L_mac (s, x[i], h[n - i]);
+        }
+        s = L_shl (s, 3);
+        y[n] = extract_h (s);   move16 (); 
+    }
+
+    return;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgsmefr/d1035pf.c	Fri Nov 25 16:18:21 2022 +0000
@@ -0,0 +1,76 @@
+/*************************************************************************
+ *
+ *  FUNCTION:   dec_10i40_35bits()
+ *
+ *  PURPOSE:  Builds the innovative codevector from the received
+ *            index of algebraic codebook.
+ *
+ *   See  c1035pf.c  for more details about the algebraic codebook structure.
+ *
+ *************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "count.h"
+
+#define L_CODE    40            /* codevector length */
+#define NB_PULSE  10            /* number of pulses  */
+#define NB_TRACK  5             /* number of track */
+
+void dec_10i40_35bits (
+    Word16 index[],    /* (i)     : index of 10 pulses (sign+position)       */
+    Word16 cod[]       /* (o)     : algebraic (fixed) codebook excitation    */
+)
+{
+    static const Word16 dgray[8] = {0, 1, 3, 2, 5, 6, 4, 7};
+    Word16 i, j, pos1, pos2, sign, tmp;
+
+    for (i = 0; i < L_CODE; i++)
+    {
+        cod[i] = 0;                                     move16 (); 
+    }
+
+    /* decode the positions and signs of pulses and build the codeword */
+
+    for (j = 0; j < NB_TRACK; j++)
+    {
+        /* compute index i */
+
+        tmp = index[j];                                 move16 ();
+        i = tmp & 7;                                    logic16 (); 
+        i = dgray[i];                                   move16 (); 
+
+        i = extract_l (L_shr (L_mult (i, 5), 1));
+        pos1 = add (i, j); /* position of pulse "j" */
+
+        i = shr (tmp, 3) & 1;                           logic16 (); 
+        test (); 
+        if (i == 0)
+        {
+            sign = 4096;                                move16 (); /* +1.0 */
+        }
+        else
+        {
+            sign = -4096;                               move16 (); /* -1.0 */
+        }
+
+        cod[pos1] = sign;                               move16 (); 
+
+        /* compute index i */
+
+        i = index[add (j, 5)] & 7;                      logic16 (); 
+        i = dgray[i];                                   move16 (); 
+        i = extract_l (L_shr (L_mult (i, 5), 1));
+
+        pos2 = add (i, j);      /* position of pulse "j+5" */
+
+        test (); 
+        if (sub (pos2, pos1) < 0)
+        {
+            sign = negate (sign);
+        }
+        cod[pos2] = add (cod[pos2], sign);              move16 (); 
+    }
+
+    return;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgsmefr/d_gains.c	Fri Nov 25 16:18:21 2022 +0000
@@ -0,0 +1,490 @@
+/*************************************************************************
+ *
+ *  FILE NAME:   D_GAINS.C
+ *
+ *  FUNCTIONS DEFINED IN THIS FILE:
+ *
+ *        d_gain_pitch(), d_gain_code() and gmed5()
+ *
+ * MA prediction is performed on the innovation energy
+ * ( in dB/(20*log10(2)) ) with mean removed.
+ *************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "oper_32b.h"
+#include "count.h"
+#include "sig_proc.h"
+
+#include "gains_tb.h"
+
+#include "cnst.h"
+#include "dtx.h"
+
+extern Word16 gain_code_old_rx[4 * DTX_HANGOVER];
+
+/* Static variables for bad frame handling */
+
+/* Variables used by d_gain_pitch: */
+Word16 pbuf[5], past_gain_pit, prev_gp;
+
+/* Variables used by d_gain_code: */
+Word16 gbuf[5], past_gain_code, prev_gc;
+
+/* Static variables for CNI (used by d_gain_code) */
+
+Word16 gcode0_CN, gain_code_old_CN, gain_code_new_CN, gain_code_muting_CN;
+
+/* Memories of gain dequantization: */
+
+/* past quantized energies.      */
+/* initialized to -14.0/constant, constant = 20*Log10(2) */
+
+Word16 past_qua_en[4];
+
+/* MA prediction coeff   */
+Word16 pred[4];
+
+/*************************************************************************
+ *
+ *  FUNCTION:   gmed5
+ *
+ *  PURPOSE:    calculates 5-point median.
+ *
+ *  DESCRIPTION:
+ *             
+ *************************************************************************/
+
+Word16 gmed5 (        /* out      : index of the median value (0...4) */
+    Word16 ind[]      /* in       : Past gain values                  */
+)
+{
+    Word16 i, j, ix = 0, tmp[5];
+    Word16 max, tmp2[5];
+
+    for (i = 0; i < 5; i++)
+    {
+        tmp2[i] = ind[i];                                      move16 (); 
+    }
+
+    for (i = 0; i < 5; i++)
+    {
+        max = -8192;                                           move16 (); 
+        for (j = 0; j < 5; j++)
+        {
+            test (); 
+            if (sub (tmp2[j], max) >= 0)
+            {
+                max = tmp2[j];                                 move16 (); 
+                ix = j;                                        move16 (); 
+            }
+        }
+        tmp2[ix] = -16384;                                     move16 (); 
+        tmp[i] = ix;                                           move16 (); 
+    }
+
+    return (ind[tmp[2]]);
+}
+
+/*************************************************************************
+ *
+ *  FUNCTION:   d_gain_pitch
+ *
+ *  PURPOSE:  decodes the pitch gain using the received index.
+ *
+ *  DESCRIPTION:
+ *       In case of no frame erasure, the gain is obtained from the
+ *       quantization table at the given index; otherwise, a downscaled
+ *       past gain is used.
+ *
+ *************************************************************************/
+
+Word16 d_gain_pitch ( /* out      : quantized pitch gain           */
+    Word16 index,     /* in       : index of quantization          */
+    Word16 bfi,       /* in       : bad frame indicator (good = 0) */
+    Word16 state,
+    Word16 prev_bf,
+    Word16 rxdtx_ctrl
+)
+{
+    static const Word16 pdown[7] =
+    {
+        32767, 32112, 32112, 26214,
+        9830, 6553, 6553
+    };
+
+    Word16 gain, tmp, i;
+
+    test (); 
+    if (bfi == 0)
+    {
+        test (); logic16 (); 
+        if ((rxdtx_ctrl & RX_SP_FLAG) != 0)
+        {
+            gain = shr (qua_gain_pitch[index], 2);             move16 (); 
+
+            test (); 
+            if (prev_bf != 0)
+            {
+                test (); 
+                if (sub (gain, prev_gp) > 0)
+                {
+                    gain = prev_gp;
+                }
+            }
+        }
+        else
+        {
+            gain = 0;                                          move16 (); 
+        }
+        prev_gp = gain;                                        move16 (); 
+    }
+    else
+    {
+        test (); logic16 (); 
+        if ((rxdtx_ctrl & RX_SP_FLAG) != 0)
+        {
+            tmp = gmed5 (pbuf);                                move16 (); 
+
+            test (); 
+            if (sub (tmp, past_gain_pit) < 0)
+            {
+                past_gain_pit = tmp;                           move16 (); 
+            }
+            gain = mult (pdown[state], past_gain_pit);
+        }
+        else
+        {
+            gain = 0;                                          move16 (); 
+        }
+    }
+
+    past_gain_pit = gain;                                      move16 (); 
+
+    test (); 
+    if (sub (past_gain_pit, 4096) > 0)  /* if (past_gain_pit > 1.0) */
+    {
+        past_gain_pit = 4096;                                  move16 (); 
+    }
+    for (i = 1; i < 5; i++)
+    {
+        pbuf[i - 1] = pbuf[i];                                 move16 (); 
+    }
+
+    pbuf[4] = past_gain_pit;                                   move16 (); 
+
+    return gain;
+}
+
+/*************************************************************************
+ *
+ *  FUNCTION:  d_gain_code
+ *
+ *  PURPOSE:  decode the fixed codebook gain using the received index.
+ *
+ *  DESCRIPTION:
+ *      The received index gives the gain correction factor gamma.
+ *      The quantized gain is given by   g_q = g0 * gamma
+ *      where g0 is the predicted gain.
+ *      To find g0, 4th order MA prediction is applied to the mean-removed
+ *      innovation energy in dB.
+ *      In case of frame erasure, downscaled past gain is used.
+ *
+ *************************************************************************/
+
+/* average innovation energy.                             */
+/* MEAN_ENER = 36.0/constant, constant = 20*Log10(2)      */
+#define MEAN_ENER  783741L      /* 36/(20*log10(2))       */
+
+void d_gain_code (
+    Word16 index,      /* input : received quantization index */
+    Word16 code[],     /* input : innovation codevector       */
+    Word16 lcode,      /* input : codevector length           */
+    Word16 *gain_code, /* output: decoded innovation gain     */
+    Word16 bfi,        /* input : bad frame indicator         */
+    Word16 state,
+    Word16 prev_bf,
+    Word16 rxdtx_ctrl,
+    Word16 i_subfr,
+    Word16 rx_dtx_state
+)
+{
+    static const Word16 cdown[7] =
+    {
+        32767, 32112, 32112, 32112,
+        32112, 32112, 22937
+    };
+
+    Word16 i, tmp;
+    Word16 gcode0, exp, frac, av_pred_en;
+    Word32 ener, ener_code;
+
+    test (); test (); logic16 (); 
+    if (((rxdtx_ctrl & RX_UPD_SID_QUANT_MEM) != 0) && (i_subfr == 0))
+    {
+        gcode0_CN = update_gcode0_CN (gain_code_old_rx);       move16 (); 
+        gcode0_CN = shl (gcode0_CN, 4);
+    }
+
+    /* Handle cases of comfort noise fixed codebook gain decoding in
+       which past valid SID frames are repeated */
+
+    test (); test (); test (); logic16 (); logic16 (); logic16 (); 
+    if (((rxdtx_ctrl & RX_NO_TRANSMISSION) != 0)
+        || ((rxdtx_ctrl & RX_INVALID_SID_FRAME) != 0)
+        || ((rxdtx_ctrl & RX_LOST_SID_FRAME) != 0))
+    {
+
+        test (); logic16 (); 
+        if ((rxdtx_ctrl & RX_NO_TRANSMISSION) != 0)
+        {
+            /* DTX active: no transmission. Interpolate gain values
+            in memory */
+            test (); 
+            if (i_subfr == 0)
+            {
+                *gain_code = interpolate_CN_param (gain_code_old_CN,
+                                            gain_code_new_CN, rx_dtx_state);
+                                                               move16 (); 
+            }
+            else
+            {
+                *gain_code = prev_gc;                          move16 (); 
+            }
+        }
+        else
+        {                       /* Invalid or lost SID frame:
+            use gain values from last good SID frame */
+            gain_code_old_CN = gain_code_new_CN;               move16 (); 
+            *gain_code = gain_code_new_CN;                     move16 (); 
+
+            /* reset table of past quantized energies */
+            for (i = 0; i < 4; i++)
+            {
+                past_qua_en[i] = -2381;                        move16 (); 
+            }
+        }
+
+        test (); logic16 (); 
+        if ((rxdtx_ctrl & RX_DTX_MUTING) != 0)
+        {
+            /* attenuate the gain value by 0.75 dB in each subframe */
+            /* (total of 3 dB per frame) */
+            gain_code_muting_CN = mult (gain_code_muting_CN, 30057);
+            *gain_code = gain_code_muting_CN;                  move16 (); 
+        }
+        else
+        {
+            /* Prepare for DTX muting by storing last good gain value */
+            gain_code_muting_CN = gain_code_new_CN;            move16 (); 
+        }
+
+        past_gain_code = *gain_code;                           move16 (); 
+
+        for (i = 1; i < 5; i++)
+        {
+            gbuf[i - 1] = gbuf[i];                             move16 (); 
+        }
+
+        gbuf[4] = past_gain_code;                              move16 (); 
+        prev_gc = past_gain_code;                              move16 (); 
+
+        return;
+    }
+
+    /*----------------- Test erasure ---------------*/
+
+    test (); 
+    if (bfi != 0)
+    {
+        tmp = gmed5 (gbuf);                                    move16 (); 
+        test (); 
+        if (sub (tmp, past_gain_code) < 0)
+        {
+            past_gain_code = tmp;                              move16 (); 
+        }
+        past_gain_code = mult (past_gain_code, cdown[state]);
+        *gain_code = past_gain_code;                           move16 (); 
+
+        av_pred_en = 0;                                        move16 (); 
+        for (i = 0; i < 4; i++)
+        {
+            av_pred_en = add (av_pred_en, past_qua_en[i]);
+        }
+
+        /* av_pred_en = 0.25*av_pred_en - 4/(20Log10(2)) */
+        av_pred_en = mult (av_pred_en, 8192);   /*  *= 0.25  */
+
+        /* if (av_pred_en < -14/(20Log10(2))) av_pred_en = .. */
+        test (); 
+        if (sub (av_pred_en, -2381) < 0)
+        {
+            av_pred_en = -2381;                                move16 (); 
+        }
+        for (i = 3; i > 0; i--)
+        {
+            past_qua_en[i] = past_qua_en[i - 1];               move16 (); 
+        }
+        past_qua_en[0] = av_pred_en;                           move16 (); 
+        for (i = 1; i < 5; i++)
+        {
+            gbuf[i - 1] = gbuf[i];                             move16 (); 
+        }
+        gbuf[4] = past_gain_code;                              move16 (); 
+
+        /* Use the most recent comfort noise fixed codebook gain value
+           for updating the fixed codebook gain history */
+        test ();
+        if (gain_code_new_CN == 0)
+        {
+            tmp = prev_gc;                                     move16 ();
+        }
+        else
+        {
+            tmp = gain_code_new_CN;
+        }
+
+        update_gain_code_history_rx (tmp, gain_code_old_rx);
+
+        test ();
+        if (sub (i_subfr, (3 * L_SUBFR)) == 0)
+        {
+            gain_code_old_CN = *gain_code;                     move16 (); 
+        }
+        return;
+    }
+
+    test (); logic16 (); 
+    if ((rxdtx_ctrl & RX_SP_FLAG) != 0)
+    {
+
+        /*-------------- Decode codebook gain ---------------*/
+
+        /*-------------------------------------------------------------------*
+         *  energy of code:                                                   *
+         *  ~~~~~~~~~~~~~~~                                                   *
+         *  ener_code = 10 * Log10(energy/lcode) / constant                   *
+         *            = 1/2 * Log2(energy/lcode)                              *
+         *                                           constant = 20*Log10(2)   *
+         *-------------------------------------------------------------------*/
+
+        /* ener_code = log10(ener_code/lcode) / (20*log10(2)) */
+        ener_code = 0;                                         move32 (); 
+        for (i = 0; i < lcode; i++)
+        {
+            ener_code = L_mac (ener_code, code[i], code[i]);
+        }
+        /* ener_code = ener_code / lcode */
+        ener_code = L_mult (round (ener_code), 26214);
+
+        /* ener_code = 1/2 * Log2(ener_code) */
+        Log2 (ener_code, &exp, &frac);
+        ener_code = L_Comp (sub (exp, 30), frac);
+
+        /* predicted energy */
+
+        ener = MEAN_ENER;                                      move32 (); 
+        for (i = 0; i < 4; i++)
+        {
+            ener = L_mac (ener, past_qua_en[i], pred[i]);
+        }
+
+        /*-------------------------------------------------------------------*
+         *  predicted codebook gain                                           *
+         *  ~~~~~~~~~~~~~~~~~~~~~~~                                           *
+         *  gcode0     = Pow10( (ener*constant - ener_code*constant) / 20 )   *
+         *             = Pow2(ener-ener_code)                                 *
+         *                                           constant = 20*Log10(2)   *
+         *-------------------------------------------------------------------*/
+
+        ener = L_shr (L_sub (ener, ener_code), 1);
+        L_Extract (ener, &exp, &frac);
+
+        gcode0 = extract_l (Pow2 (exp, frac));  /* predicted gain */
+
+        gcode0 = shl (gcode0, 4);
+
+        *gain_code = mult (qua_gain_code[index], gcode0);      move16 (); 
+
+        test (); 
+        if (prev_bf != 0)
+        {
+            test (); 
+            if (sub (*gain_code, prev_gc) > 0)
+            {
+                *gain_code = prev_gc;     move16 (); 
+            }
+        }
+        /*-------------------------------------------------------------------*
+         *  update table of past quantized energies                           *
+         *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                           *
+         *  past_qua_en      = 20 * Log10(qua_gain_code) / constant           *
+         *                   = Log2(qua_gain_code)                            *
+         *                                           constant = 20*Log10(2)   *
+         *-------------------------------------------------------------------*/
+
+        for (i = 3; i > 0; i--)
+        {
+            past_qua_en[i] = past_qua_en[i - 1];               move16 (); 
+        }
+        Log2 (L_deposit_l (qua_gain_code[index]), &exp, &frac);
+
+        past_qua_en[0] = shr (frac, 5);                        move16 (); 
+        past_qua_en[0] = add (past_qua_en[0], shl (sub (exp, 11), 10));
+        move16 (); 
+
+        update_gain_code_history_rx (*gain_code, gain_code_old_rx);
+
+        if (sub (i_subfr, (3 * L_SUBFR)) == 0)
+        {
+            gain_code_old_CN = *gain_code;                     move16 (); 
+        }
+    }
+    else
+    {
+        test (); test (); logic16 (); 
+        if (((rxdtx_ctrl & RX_FIRST_SID_UPDATE) != 0) && (i_subfr == 0))
+        {
+            gain_code_new_CN = mult (gcode0_CN, qua_gain_code[index]);
+
+            /*---------------------------------------------------------------*
+             *  reset table of past quantized energies                        *
+             *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                        *
+             *---------------------------------------------------------------*/
+
+            for (i = 0; i < 4; i++)
+            {
+                past_qua_en[i] = -2381;                        move16 (); 
+            }
+        }
+        test (); test (); logic16 (); 
+        if (((rxdtx_ctrl & RX_CONT_SID_UPDATE) != 0) && (i_subfr == 0))
+        {
+            gain_code_old_CN = gain_code_new_CN;               move16 (); 
+            gain_code_new_CN = mult (gcode0_CN, qua_gain_code[index]);
+                                                               move16 (); 
+        }
+        test (); 
+        if (i_subfr == 0)
+        {
+            *gain_code = interpolate_CN_param (gain_code_old_CN,
+                                               gain_code_new_CN,
+                                               rx_dtx_state);  move16 (); 
+        }
+        else
+        {
+            *gain_code = prev_gc;                              move16 (); 
+        }
+    }
+
+    past_gain_code = *gain_code;                               move16 (); 
+
+    for (i = 1; i < 5; i++)
+    {
+        gbuf[i - 1] = gbuf[i];                                 move16 (); 
+    }
+    gbuf[4] = past_gain_code;                                  move16 (); 
+    prev_gc = past_gain_code;                                  move16 (); 
+
+    return;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgsmefr/d_homing.c	Fri Nov 25 16:18:21 2022 +0000
@@ -0,0 +1,344 @@
+/**************************************************************************
+ *
+ *   File Name:  d_homing.c
+ *
+ *   Purpose:
+ *      This file contains the following functions:
+ *
+ *      decoder_homing_frame_test()  checks if a frame of input speech
+ *                                   parameters matches the Decoder Homing
+ *                                   Frame pattern.
+ *
+ *      decoder_reset()              called by reset_dec() to reset all of
+ *                                   the state variables for the decoder
+ *
+ *      reset_dec()                  calls functions to reset the state
+ *                                   variables for the decoder, and for
+ *                                   the receive DTX and Comfort Noise.
+ *
+ **************************************************************************/
+
+#include "typedef.h"
+#include "cnst.h"
+#include "dtx.h"
+#include "codec.h"
+#include "d_homing.h"
+#include "q_plsf_5.tab"
+
+#define PRM_NO    57
+
+/***************************************************************************
+ *
+ *   FUNCTION NAME:  decoder_homing_frame_test
+ *
+ *   PURPOSE:
+ *      Checks if a frame of input speech parameters matches the Decoder
+ *      Homing Frame pattern, which is:
+ *
+ *      parameter    decimal value    hexidecimal value
+ *      ---------    -------------    -----------------
+ *      LPC 1        4                0x0004
+ *      LPC 2        47               0x002F
+ *      LPC 3        180              0x00B4
+ *      LPC 4        144              0x0090
+ *      LPC 5        62               0x003E
+ *      LTP-LAG 1    342              0x0156
+ *      LTP-GAIN 1   11               0x000B
+ *      PULSE1_1     0                0x0000
+ *      PULSE1_2     1                0x0001
+ *      PULSE1_3     15               0x000F
+ *      PULSE1_4     1                0x0001
+ *      PULSE1_5     13               0x000D
+ *      PULSE1_6     0                0x0000
+ *      PULSE1_7     3                0x0003
+ *      PULSE1_8     0                0x0000
+ *      PULSE1_9     3                0x0003
+ *      PULSE1_10    0                0x0000
+ *      FCB-GAIN 1   3                0x0003
+ *      LTP-LAG 2    54               0x0036
+ *      LTP-GAIN 2   1                0x0001
+ *      PULSE2_1     8                0x0008
+ *      PULSE2_2     8                0x0008
+ *      PULSE2_3     5                0x0005
+ *      PULSE2_4     8                0x0008
+ *      PULSE2_5     1                0x0001
+ *      PULSE2_6     0                0x0000
+ *      PULSE2_7     0                0x0000
+ *      PULSE2_8     1                0x0001
+ *      PULSE2_9     1                0x0001
+ *      PULSE2_10    0                0x0000
+ *      FCB-GAIN 2   0                0x0000
+ *      LTP-LAG 3    342              0x0156
+ *      LTP-GAIN 3   0                0x0000
+ *      PULSE3_1     0                0x0000
+ *      PULSE3_2     0                0x0000
+ *      PULSE3_3     0                0x0000
+ *      PULSE3_4     0                0x0000
+ *      PULSE3_5     0                0x0000
+ *      PULSE3_6     0                0x0000
+ *      PULSE3_7     0                0x0000
+ *      PULSE3_8     0                0x0000
+ *      PULSE3_9     0                0x0000
+ *      PULSE3_10    0                0x0000
+ *      FCB-GAIN 3   0                0x0000
+ *      LTP-LAG 4    54               0x0036
+ *      LTP-GAIN 4   11               0x000B
+ *      PULSE4_1     0                0x0000
+ *      PULSE4_2     0                0x0000
+ *      PULSE4_3     0                0x0000
+ *      PULSE4_4     0                0x0000
+ *      PULSE4_5     0                0x0000
+ *      PULSE4_6     0                0x0000
+ *      PULSE4_7     0                0x0000
+ *      PULSE4_8     0                0x0000
+ *      PULSE4_9     0                0x0000
+ *      PULSE4_10    0                0x0000
+ *      FCB-GAIN 4   0                0x0000
+ *
+ *   INPUT:
+ *      parm[]  one frame of speech parameters in parallel format
+ *
+ *      nbr_of_params
+ *              the number of consecutive parameters in parm[] to match
+ *
+ *   OUTPUT:
+ *      None
+ *
+ *   RETURN:
+ *      0       input frame does not match the Decoder Homing Frame pattern.
+ *      1       input frame matches the Decoder Homing Frame pattern.
+ *
+ **************************************************************************/
+
+Word16 decoder_homing_frame_test (Word16 parm[], Word16 nbr_of_params)
+{
+    static const Word16 dhf_mask[PRM_NO] =
+    {
+        0x0004,                 /* LPC 1 */
+        0x002f,                 /* LPC 2 */
+        0x00b4,                 /* LPC 3 */
+        0x0090,                 /* LPC 4 */
+        0x003e,                 /* LPC 5 */
+
+        0x0156,                 /* LTP-LAG 1 */
+        0x000b,                 /* LTP-GAIN 1 */
+        0x0000,                 /* PULSE 1_1 */
+        0x0001,                 /* PULSE 1_2 */
+        0x000f,                 /* PULSE 1_3 */
+        0x0001,                 /* PULSE 1_4 */
+        0x000d,                 /* PULSE 1_5 */
+        0x0000,                 /* PULSE 1_6 */
+        0x0003,                 /* PULSE 1_7 */
+        0x0000,                 /* PULSE 1_8 */
+        0x0003,                 /* PULSE 1_9 */
+        0x0000,                 /* PULSE 1_10 */
+        0x0003,                 /* FCB-GAIN 1 */
+
+        0x0036,                 /* LTP-LAG 2 */
+        0x0001,                 /* LTP-GAIN 2 */
+        0x0008,                 /* PULSE 2_1 */
+        0x0008,                 /* PULSE 2_2 */
+        0x0005,                 /* PULSE 2_3 */
+        0x0008,                 /* PULSE 2_4 */
+        0x0001,                 /* PULSE 2_5 */
+        0x0000,                 /* PULSE 2_6 */
+        0x0000,                 /* PULSE 2_7 */
+        0x0001,                 /* PULSE 2_8 */
+        0x0001,                 /* PULSE 2_9 */
+        0x0000,                 /* PULSE 2_10 */
+        0x0000,                 /* FCB-GAIN 2 */
+
+        0x0156,                 /* LTP-LAG 3 */
+        0x0000,                 /* LTP-GAIN 3 */
+        0x0000,                 /* PULSE 3_1 */
+        0x0000,                 /* PULSE 3_2 */
+        0x0000,                 /* PULSE 3_3 */
+        0x0000,                 /* PULSE 3_4 */
+        0x0000,                 /* PULSE 3_5 */
+        0x0000,                 /* PULSE 3_6 */
+        0x0000,                 /* PULSE 3_7 */
+        0x0000,                 /* PULSE 3_8 */
+        0x0000,                 /* PULSE 3_9 */
+        0x0000,                 /* PULSE 3_10 */
+        0x0000,                 /* FCB-GAIN 3 */
+
+        0x0036,                 /* LTP-LAG 4 */
+        0x000b,                 /* LTP-GAIN 4 */
+        0x0000,                 /* PULSE 4_1 */
+        0x0000,                 /* PULSE 4_2 */
+        0x0000,                 /* PULSE 4_3 */
+        0x0000,                 /* PULSE 4_4 */
+        0x0000,                 /* PULSE 4_5 */
+        0x0000,                 /* PULSE 4_6 */
+        0x0000,                 /* PULSE 4_7 */
+        0x0000,                 /* PULSE 4_8 */
+        0x0000,                 /* PULSE 4_9 */
+        0x0000,                 /* PULSE 4_10 */
+        0x0000                  /* FCB-GAIN 4 */ };
+
+    Word16 i, j;
+
+    for (i = 0; i < nbr_of_params; i++)
+    {
+        j = parm[i] ^ dhf_mask[i];
+
+        if (j)
+            break;
+    }
+
+    return !j;
+}
+
+/***************************************************************************
+ *
+ *   FUNCTION NAME:  decoder_reset
+ *
+ *   PURPOSE:
+ *      resets all of the state variables for the decoder
+ *
+ *   INPUT:
+ *      None
+ *
+ *   OUTPUT:
+ *      None
+ *
+ *   RETURN:
+ *      None
+ *
+ **************************************************************************/
+
+void decoder_reset (void)
+{
+    /* External declarations for decoder variables which need to be reset */
+
+    /* variable defined in decoder.c */
+    /* ----------------------------- */
+    extern Word16 synth_buf[L_FRAME + M];
+
+    /* variable defined in agc.c */
+    /* -------------------------- */
+    extern Word16 past_gain;
+
+    /* variables defined in d_gains.c */
+    /* ------------------------------ */
+    /* Error concealment */
+    extern Word16 pbuf[5], past_gain_pit, prev_gp, gbuf[5], past_gain_code,
+     prev_gc;
+
+    /* CNI */
+    extern Word16 gcode0_CN, gain_code_old_CN, gain_code_new_CN;
+    extern Word16 gain_code_muting_CN;
+
+    /* Memories of gain dequantization: */
+    extern Word16 past_qua_en[4], pred[4];
+
+    /* variables defined in d_plsf_5.c */
+    /* ------------------------------ */
+    /* Past quantized prediction error */
+    extern Word16 past_r2_q[M];
+
+    /* Past dequantized lsfs */
+    extern Word16 past_lsf_q[M];
+
+    /* CNI */
+    extern Word16 lsf_p_CN[M], lsf_new_CN[M], lsf_old_CN[M];
+
+    /* variables defined in dec_lag6.c */
+    /* ------------------------------ */
+    extern Word16 old_T0;
+
+    /* variable defined in preemph.c */
+    /* ------------------------------ */
+    extern Word16 mem_pre;
+
+    Word16 i;
+
+    /* reset all the decoder state variables */
+    /* ------------------------------------- */
+
+    /* Variable in decoder.c: */
+    for (i = 0; i < M; i++)
+    {
+        synth_buf[i] = 0;
+    }
+
+    /* Variables in dec_12k2.c: */
+    Init_Decoder_12k2 ();
+
+    /* Variable in agc.c: */
+    past_gain = 4096;
+
+    /* Variables in d_gains.c: */
+    for (i = 0; i < 5; i++)
+    {
+        pbuf[i] = 410;          /* Error concealment */
+        gbuf[i] = 1;            /* Error concealment */
+    }
+
+    past_gain_pit = 0;          /* Error concealment */
+    prev_gp = 4096;             /* Error concealment */
+    past_gain_code = 0;         /* Error concealment */
+    prev_gc = 1;                /* Error concealment */
+    gcode0_CN = 0;              /* CNI */
+    gain_code_old_CN = 0;       /* CNI */
+    gain_code_new_CN = 0;       /* CNI */
+    gain_code_muting_CN = 0;    /* CNI */
+
+    for (i = 0; i < 4; i++)
+    {
+        past_qua_en[i] = -2381; /* past quantized energies */
+    }
+
+    pred[0] = 44;               /* MA prediction coeff */
+    pred[1] = 37;               /* MA prediction coeff */
+    pred[2] = 22;               /* MA prediction coeff */
+    pred[3] = 12;               /* MA prediction coeff */
+
+    /* Variables in d_plsf_5.c: */
+    for (i = 0; i < M; i++)
+    {
+        past_r2_q[i] = 0;               /* Past quantized prediction error */
+        past_lsf_q[i] = mean_lsf[i];    /* Past dequantized lsfs */
+        lsf_p_CN[i] = mean_lsf[i];      /* CNI */
+        lsf_new_CN[i] = mean_lsf[i];    /* CNI */
+        lsf_old_CN[i] = mean_lsf[i];    /* CNI */
+    }
+
+    /* Variable in dec_lag6.c: */
+    old_T0 = 40;                /* Old integer lag */
+
+    /* Variable in preemph.c: */
+    mem_pre = 0;                /* Filter memory */
+
+    /* Variables in pstfilt2.c: */
+    Init_Post_Filter ();
+
+    return;
+}
+
+/***************************************************************************
+ *
+ *   FUNCTION NAME:  reset_dec
+ *
+ *   PURPOSE:
+ *      resets all of the state variables for the decoder, and for the
+ *      receive DTX and Comfort Noise.
+ *
+ *   INPUT:
+ *      None
+ *
+ *   OUTPUT:
+ *      None
+ *
+ *   RETURN:
+ *      None
+ *
+ **************************************************************************/
+
+void reset_dec (void)
+{
+    decoder_reset (); /* reset all the state variables in the speech decoder*/
+    reset_rx_dtx ();  /* reset all the receive DTX and CN state variables */
+
+    return;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgsmefr/d_plsf_5.c	Fri Nov 25 16:18:21 2022 +0000
@@ -0,0 +1,289 @@
+/*************************************************************************
+ *
+ *  FUNCTION:   D_plsf_5()
+ *
+ *  PURPOSE: Decodes the 2 sets of LSP parameters in a frame using the
+ *           received quantization indices.
+ *
+ *  DESCRIPTION:
+ *           The two sets of LSFs are quantized using split by 5 matrix
+ *           quantization (split-MQ) with 1st order MA prediction.
+ *
+ *   See "q_plsf_5.c" for more details about the quantization procedure
+ *
+ *************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "count.h"
+#include "sig_proc.h"
+
+#include "q_plsf_5.tab"         /* Codebooks of LSF prediction residual */
+
+#include "cnst.h"
+#include "dtx.h"
+
+/* M  ->order of linear prediction filter                      */
+/* LSF_GAP  -> Minimum distance between LSF after quantization */
+/*             50 Hz = 205                                     */
+/* PRED_FAC -> Prediction factor = 0.65                        */
+/* ALPHA    ->  0.9                                            */
+/* ONE_ALPHA-> (1.0-ALPHA)                                     */
+
+#define M         10
+#define LSF_GAP   205
+#define PRED_FAC  21299
+#define ALPHA     31128
+#define ONE_ALPHA 1639
+
+/* Past quantized prediction error */
+
+Word16 past_r2_q[M];
+
+/* Past dequantized lsfs */
+
+Word16 past_lsf_q[M];
+
+/* Reference LSF parameter vector (comfort noise) */
+
+Word16 lsf_p_CN[M];
+
+/*  LSF memories for comfort noise interpolation */
+
+Word16 lsf_old_CN[M], lsf_new_CN[M];
+
+ /* LSF parameter buffer */
+
+extern Word16 lsf_old_rx[DTX_HANGOVER][M];
+
+void D_plsf_5 (
+    Word16 *indice,       /* input : quantization indices of 5 submatrices */
+    Word16 *lsp1_q,       /* output: quantized 1st LSP vector              */
+    Word16 *lsp2_q,       /* output: quantized 2nd LSP vector              */
+    Word16 bfi,           /* input : bad frame indicator (set to 1 if a bad
+                                     frame is received)                    */
+    Word16 rxdtx_ctrl,    /* input : RX DTX control word                   */
+    Word16 rx_dtx_state   /* input : state of the comfort noise insertion
+                                     period                                */
+)
+{
+    Word16 i;
+    const Word16 *p_dico;
+    Word16 temp, sign;
+    Word16 lsf1_r[M], lsf2_r[M];
+    Word16 lsf1_q[M], lsf2_q[M];
+
+    /* Update comfort noise LSF quantizer memory */
+    test (); logic16 (); 
+    if ((rxdtx_ctrl & RX_UPD_SID_QUANT_MEM) != 0)
+    {
+        update_lsf_p_CN (lsf_old_rx, lsf_p_CN);
+    }
+    /* Handle cases of comfort noise LSF decoding in which past
+    valid SID frames are repeated */
+
+    test (); logic16 (); 
+    test (); logic16 (); 
+    test (); logic16 (); 
+    if (((rxdtx_ctrl & RX_NO_TRANSMISSION) != 0)
+        || ((rxdtx_ctrl & RX_INVALID_SID_FRAME) != 0)
+        || ((rxdtx_ctrl & RX_LOST_SID_FRAME) != 0))
+    {
+
+        test (); logic16 (); 
+        if ((rxdtx_ctrl & RX_NO_TRANSMISSION) != 0)
+        {
+            /* DTX active: no transmission. Interpolate LSF values in memory */
+            interpolate_CN_lsf (lsf_old_CN, lsf_new_CN, lsf2_q, rx_dtx_state);
+        }
+        else
+        {                       /* Invalid or lost SID frame: use LSFs
+                                   from last good SID frame */
+            for (i = 0; i < M; i++)
+            {
+                lsf_old_CN[i] = lsf_new_CN[i];  move16 (); 
+                lsf2_q[i] = lsf_new_CN[i];      move16 (); 
+                past_r2_q[i] = 0;               move16 (); 
+            }
+        }
+
+        for (i = 0; i < M; i++)
+        {
+            past_lsf_q[i] = lsf2_q[i];          move16 (); 
+        }
+
+        /*  convert LSFs to the cosine domain */
+        Lsf_lsp (lsf2_q, lsp2_q, M);
+
+        return;
+    }
+
+    test (); 
+    if (bfi != 0)                               /* if bad frame */
+    {
+        /* use the past LSFs slightly shifted towards their mean */
+
+        for (i = 0; i < M; i++)
+        {
+            /* lsfi_q[i] = ALPHA*past_lsf_q[i] + ONE_ALPHA*mean_lsf[i]; */
+
+            lsf1_q[i] = add (mult (past_lsf_q[i], ALPHA),
+                             mult (mean_lsf[i], ONE_ALPHA));
+                                                move16 (); 
+
+            lsf2_q[i] = lsf1_q[i];              move16 (); 
+        }
+
+        /* estimate past quantized residual to be used in next frame */
+
+        for (i = 0; i < M; i++)
+        {
+            /* temp  = mean_lsf[i] +  past_r2_q[i] * PRED_FAC; */
+
+            temp = add (mean_lsf[i], mult (past_r2_q[i], PRED_FAC));
+
+            past_r2_q[i] = sub (lsf2_q[i], temp);
+                                                move16 (); 
+        }
+    }
+    else
+        /* if good LSFs received */
+    {
+        /* decode prediction residuals from 5 received indices */
+
+        p_dico = &dico1_lsf[shl (indice[0], 2)];
+        lsf1_r[0] = *p_dico++;                  move16 (); 
+        lsf1_r[1] = *p_dico++;                  move16 (); 
+        lsf2_r[0] = *p_dico++;                  move16 (); 
+        lsf2_r[1] = *p_dico++;                  move16 (); 
+
+        p_dico = &dico2_lsf[shl (indice[1], 2)];
+        lsf1_r[2] = *p_dico++;                  move16 (); 
+        lsf1_r[3] = *p_dico++;                  move16 (); 
+        lsf2_r[2] = *p_dico++;                  move16 (); 
+        lsf2_r[3] = *p_dico++;                  move16 (); 
+
+        sign = indice[2] & 1;                   logic16 (); 
+        i = shr (indice[2], 1);
+        p_dico = &dico3_lsf[shl (i, 2)];        move16 (); 
+
+        test (); 
+        if (sign == 0)
+        {
+            lsf1_r[4] = *p_dico++;              move16 (); 
+            lsf1_r[5] = *p_dico++;              move16 (); 
+            lsf2_r[4] = *p_dico++;              move16 (); 
+            lsf2_r[5] = *p_dico++;              move16 (); 
+        }
+        else
+        {
+            lsf1_r[4] = negate (*p_dico++);     move16 (); 
+            lsf1_r[5] = negate (*p_dico++);     move16 (); 
+            lsf2_r[4] = negate (*p_dico++);     move16 (); 
+            lsf2_r[5] = negate (*p_dico++);     move16 (); 
+        }
+
+        p_dico = &dico4_lsf[shl (indice[3], 2)];move16 (); 
+        lsf1_r[6] = *p_dico++;                  move16 (); 
+        lsf1_r[7] = *p_dico++;                  move16 (); 
+        lsf2_r[6] = *p_dico++;                  move16 (); 
+        lsf2_r[7] = *p_dico++;                  move16 (); 
+
+        p_dico = &dico5_lsf[shl (indice[4], 2)];move16 (); 
+        lsf1_r[8] = *p_dico++;                  move16 (); 
+        lsf1_r[9] = *p_dico++;                  move16 (); 
+        lsf2_r[8] = *p_dico++;                  move16 (); 
+        lsf2_r[9] = *p_dico++;                  move16 (); 
+
+        /* Compute quantized LSFs and update the past quantized residual */
+        /* Use lsf_p_CN as predicted LSF vector in case of no speech
+           activity */
+
+        test (); logic16 (); 
+        if ((rxdtx_ctrl & RX_SP_FLAG) != 0)
+        {
+            for (i = 0; i < M; i++)
+            {
+                temp = add (mean_lsf[i], mult (past_r2_q[i], PRED_FAC));
+                lsf1_q[i] = add (lsf1_r[i], temp);
+                                                move16 (); 
+                lsf2_q[i] = add (lsf2_r[i], temp);
+                                                move16 (); 
+                past_r2_q[i] = lsf2_r[i];       move16 (); 
+            }
+        }
+        else
+        {                       /* Valid SID frame */
+            for (i = 0; i < M; i++)
+            {
+                lsf2_q[i] = add (lsf2_r[i], lsf_p_CN[i]);
+                                                move16 (); 
+
+                /* Use the dequantized values of lsf2 also for lsf1 */
+                lsf1_q[i] = lsf2_q[i];          move16 (); 
+
+                past_r2_q[i] = 0;               move16 (); 
+            }
+        }
+    }
+
+    /* verification that LSFs have minimum distance of LSF_GAP Hz */
+
+    Reorder_lsf (lsf1_q, LSF_GAP, M);
+    Reorder_lsf (lsf2_q, LSF_GAP, M);
+
+    test (); logic16 (); 
+    if ((rxdtx_ctrl & RX_FIRST_SID_UPDATE) != 0)
+    {
+        for (i = 0; i < M; i++)
+        {
+            lsf_new_CN[i] = lsf2_q[i];          move16 (); 
+        }
+    }
+    test (); logic16 (); 
+    if ((rxdtx_ctrl & RX_CONT_SID_UPDATE) != 0)
+    {
+        for (i = 0; i < M; i++)
+        {
+            lsf_old_CN[i] = lsf_new_CN[i];      move16 (); 
+            lsf_new_CN[i] = lsf2_q[i];          move16 (); 
+        }
+    }
+    test (); logic16 (); 
+    if ((rxdtx_ctrl & RX_SP_FLAG) != 0)
+    {
+        /* Update lsf history with quantized LSFs
+           when speech activity is present. If the current frame is
+           a bad one, update with most recent good comfort noise LSFs */
+
+        if (bfi==0)
+        {
+            update_lsf_history (lsf1_q, lsf2_q, lsf_old_rx);
+        }
+        else
+        {
+            update_lsf_history (lsf_new_CN, lsf_new_CN, lsf_old_rx);
+        }
+
+        for (i = 0; i < M; i++)
+        {
+            lsf_old_CN[i] = lsf2_q[i];          move16 (); 
+        }
+    }
+    else
+    {
+        interpolate_CN_lsf (lsf_old_CN, lsf_new_CN, lsf2_q, rx_dtx_state);
+    }
+
+    for (i = 0; i < M; i++)
+    {
+        past_lsf_q[i] = lsf2_q[i];              move16 (); 
+    }
+
+    /*  convert LSFs to the cosine domain */
+
+    Lsf_lsp (lsf1_q, lsp1_q, M);
+    Lsf_lsp (lsf2_q, lsp2_q, M);
+
+    return;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgsmefr/dec_12k2.c	Fri Nov 25 16:18:21 2022 +0000
@@ -0,0 +1,424 @@
+/***************************************************************************
+ *
+ *  FILE NAME:    dec_12k2.c
+ *
+ *  FUNCTIONS DEFINED IN THIS FILE:
+ *                   Init_Decoder_12k2   and  Decoder_12k2
+ *
+ *
+ *  Init_Decoder_12k2():
+ *      Initialization of variables for the decoder section.
+ *
+ *  Decoder_12k2():
+ *      Speech decoder routine operating on a frame basis.
+ *
+ ***************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "sig_proc.h"
+#include "count.h"
+#include "codec.h"
+#include "cnst.h"
+
+#include "dtx.h"
+
+extern Word16 dtx_mode;
+
+/*---------------------------------------------------------------*
+ *   Decoder constant parameters (defined in "cnst.h")           *
+ *---------------------------------------------------------------*
+ *   L_FRAME     : Frame size.                                   *
+ *   L_FRAME_BY2 : Half the frame size.                          *
+ *   L_SUBFR     : Sub-frame size.                               *
+ *   M           : LPC order.                                    *
+ *   MP1         : LPC order+1                                   *
+ *   PIT_MIN     : Minimum pitch lag.                            *
+ *   PIT_MAX     : Maximum pitch lag.                            *
+ *   L_INTERPOL  : Length of filter for interpolation            *
+ *   PRM_SIZE    : size of vector containing analysis parameters *
+ *---------------------------------------------------------------*/
+
+/*--------------------------------------------------------*
+ *         Static memory allocation.                      *
+ *--------------------------------------------------------*/
+
+ /* Excitation vector */
+
+static Word16 old_exc[L_FRAME + PIT_MAX + L_INTERPOL];
+static Word16 *exc;
+
+ /* Lsp (Line spectral pairs) */
+
+static Word16 lsp_old[M];
+
+ /* Filter's memory */
+
+static Word16 mem_syn[M];
+
+ /* Memories for bad frame handling */
+
+static Word16 prev_bf;
+static Word16 state;
+
+/***************************************************************************
+ *
+ *   FUNCTION:  Init_Decoder_12k2
+ *
+ *   PURPOSE: Initialization of variables for the decoder section.
+ *
+ ***************************************************************************/
+
+void Init_Decoder_12k2 (void)
+{
+    /* Initialize static pointer */
+
+    exc = old_exc + PIT_MAX + L_INTERPOL;
+
+    /* Static vectors to zero */
+
+    Set_zero (old_exc, PIT_MAX + L_INTERPOL);
+    Set_zero (mem_syn, M);
+
+    /* Initialize lsp_old [] */
+
+    lsp_old[0] = 30000;
+    lsp_old[1] = 26000;
+    lsp_old[2] = 21000;
+    lsp_old[3] = 15000;
+    lsp_old[4] = 8000;
+    lsp_old[5] = 0;
+    lsp_old[6] = -8000;
+    lsp_old[7] = -15000;
+    lsp_old[8] = -21000;
+    lsp_old[9] = -26000;
+
+    /* Initialize memories of bad frame handling */
+
+    prev_bf = 0;
+    state = 0;
+
+    return;
+}
+
+/***************************************************************************
+ *
+ *   FUNCTION:  Decoder_12k2
+ *
+ *   PURPOSE:   Speech decoder routine.
+ *
+ ***************************************************************************/
+
+void Decoder_12k2 (
+    Word16 parm[], /* input : vector of synthesis parameters
+                      parm[0] = bad frame indicator (bfi)       */
+    Word16 synth[],/* output: synthesis speech                  */
+    Word16 A_t[],  /* output: decoded LP filter in 4 subframes  */
+    Word16 TAF,
+    Word16 SID_flag
+)
+{
+
+    /* LPC coefficients */
+
+    Word16 *Az;                 /* Pointer on A_t */
+
+    /* LSPs */
+
+    Word16 lsp_new[M];
+    Word16 lsp_mid[M];
+
+    /* Algebraic codevector */
+
+    Word16 code[L_SUBFR];
+
+    /* excitation */
+
+    Word16 excp[L_SUBFR];
+
+    /* Scalars */
+
+    Word16 i, i_subfr;
+    Word16 T0, T0_frac, index;
+    Word16 gain_pit, gain_code, bfi, pit_sharp;
+    Word16 temp;
+    Word32 L_temp;
+
+    extern Word16 rxdtx_ctrl, rx_dtx_state;
+    extern Word32 L_pn_seed_rx;
+
+    /* Test bad frame indicator (bfi) */
+
+    bfi = *parm++;              move16 (); 
+
+    /* Set state machine */
+
+    test (); test (); 
+    if (bfi != 0)
+    {
+        state = add (state, 1);
+    }
+    else if (sub (state, 6) == 0)
+    {
+        state = 5;
+    }
+    else
+    {
+        state = 0;
+    }
+
+    test (); 
+    if (sub (state, 6) > 0)
+    {
+        state = 6;
+    }
+    rx_dtx (&rxdtx_ctrl, TAF, bfi, SID_flag);
+
+    /* If this frame is the first speech frame after CNI period,     */
+    /* set the BFH state machine to an appropriate state depending   */
+    /* on whether there was DTX muting before start of speech or not */
+    /* If there was DTX muting, the first speech frame is muted.     */
+    /* If there was no DTX muting, the first speech frame is not     */
+    /* muted. The BFH state machine starts from state 5, however, to */
+    /* keep the audible noise resulting from a SID frame which is    */
+    /* erroneously interpreted as a good speech frame as small as    */
+    /* possible (the decoder output in this case is quickly muted)   */
+    test (); logic16 ();
+    if ((rxdtx_ctrl & RX_FIRST_SP_FLAG) != 0)
+    {
+        test (); logic16 ();
+        if ((rxdtx_ctrl & RX_PREV_DTX_MUTING) != 0)
+        {
+            state = 5;    move16 ();
+            prev_bf = 1;  move16 ();
+        }
+        else
+        {
+            state = 5;    move16 ();
+            prev_bf = 0;  move16 ();
+        }
+    }
+
+#if (WMOPS)
+    fwc ();                     /* function worst case */
+
+    /* Note! The following test is performed only for determining
+       whether or not DTX mode is active, in order to switch off
+       worst worst case complexity printout when DTX mode is active
+    */
+    if ((rxdtx_ctrl & RX_SP_FLAG) == 0)
+    {
+        dtx_mode = 1;
+    }
+#endif
+
+    D_plsf_5 (parm, lsp_mid, lsp_new, bfi, rxdtx_ctrl, rx_dtx_state);
+
+#if (WMOPS)
+    fwc ();                     /* function worst case */
+#endif
+    /* Advance synthesis parameters pointer */
+    parm += 5;                  move16 (); 
+
+    test (); logic16 (); 
+    if ((rxdtx_ctrl & RX_SP_FLAG) != 0)
+    {
+        /* Interpolation of LPC for the 4 subframes */
+
+        Int_lpc (lsp_old, lsp_mid, lsp_new, A_t);
+    }
+    else
+    {
+        /* Comfort noise: use the same parameters in each subframe */
+        Lsp_Az (lsp_new, A_t);
+
+        for (i = 0; i < MP1; i++)
+        {
+            A_t[i + MP1] = A_t[i];      move16 (); 
+            A_t[i + 2 * MP1] = A_t[i];  move16 (); 
+            A_t[i + 3 * MP1] = A_t[i];  move16 (); 
+        }
+    }
+
+    /* update the LSPs for the next frame */
+    for (i = 0; i < M; i++)
+    {
+        lsp_old[i] = lsp_new[i];        move16 (); 
+    }
+#if (WMOPS)
+    fwc ();                     /* function worst case */
+#endif
+
+    /*---------------------------------------------------------------------*
+     *       Loop for every subframe in the analysis frame                 *
+     *---------------------------------------------------------------------*
+     * The subframe size is L_SUBFR and the loop is repeated               *
+     * L_FRAME/L_SUBFR times                                               *
+     *     - decode the pitch delay                                        *
+     *     - decode algebraic code                                         *
+     *     - decode pitch and codebook gains                               *
+     *     - find the excitation and compute synthesis speech              *
+     *---------------------------------------------------------------------*/
+
+    /* pointer to interpolated LPC parameters */
+    Az = A_t;                           move16 (); 
+
+    for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)
+    {
+
+        index = *parm++;                move16 (); /* pitch index */
+
+        test (); logic16 (); 
+        if ((rxdtx_ctrl & RX_SP_FLAG) != 0)
+        {
+            T0 = Dec_lag6 (index, PIT_MIN, PIT_MAX, i_subfr, L_FRAME_BY2,
+                           &T0_frac, bfi);
+#if (WMOPS)
+            fwc ();             /* function worst case */
+#endif
+
+            /*-------------------------------------------------*
+             * - Find the adaptive codebook vector.            *
+             *-------------------------------------------------*/
+
+            Pred_lt_6 (&exc[i_subfr], T0, T0_frac, L_SUBFR);
+#if (WMOPS)
+            fwc ();             /* function worst case */
+#endif
+        }
+        else
+        {
+            T0 = L_SUBFR;               move16 (); 
+        }
+
+        /*-------------------------------------------------------*
+         * - Decode pitch gain.                                  *
+         *-------------------------------------------------------*/
+
+        index = *parm++;                move16 (); 
+
+        gain_pit = d_gain_pitch (index, bfi, state, prev_bf, rxdtx_ctrl);
+        move16 (); 
+#if (WMOPS)
+        fwc ();                 /* function worst case */
+#endif
+
+        /*-------------------------------------------------------*
+         * - Decode innovative codebook.                         *
+         *-------------------------------------------------------*/
+
+        test (); logic16 (); 
+        if ((rxdtx_ctrl & RX_SP_FLAG) != 0)
+        {
+            dec_10i40_35bits (parm, code);
+        }
+        else
+        {   /* Use pseudo noise for excitation when SP_flag == 0 */
+            build_CN_code (code, &L_pn_seed_rx);
+        }
+
+        parm += 10;                     move16 (); 
+#if (WMOPS)
+        fwc ();                 /* function worst case */
+#endif
+
+        /*-------------------------------------------------------*
+         * - Add the pitch contribution to code[].               *
+         *-------------------------------------------------------*/
+
+        /* pit_sharp = gain_pit;                   */
+        /* if (pit_sharp > 1.0) pit_sharp = 1.0;   */
+
+        pit_sharp = shl (gain_pit, 3);
+
+        /* This loop is not entered when SP_FLAG is 0 */
+        for (i = T0; i < L_SUBFR; i++)
+        {
+            temp = mult (code[i - T0], pit_sharp);
+            code[i] = add (code[i], temp);
+                                        move16 (); 
+        }
+#if (WMOPS)
+        fwc ();                 /* function worst case */
+#endif
+        /* post processing of excitation elements */
+
+        test (); /* This test is not passed when SP_FLAG is 0 */
+        if (sub (pit_sharp, 16384) > 0)
+        {
+            for (i = 0; i < L_SUBFR; i++)
+            {
+                temp = mult (exc[i + i_subfr], pit_sharp);
+                L_temp = L_mult (temp, gain_pit);
+                L_temp = L_shl (L_temp, 1);
+                excp[i] = round (L_temp);
+                                        move16 (); 
+            }
+        }
+        /*-------------------------------------------------*
+         * - Decode codebook gain.                         *
+         *-------------------------------------------------*/
+
+        index = *parm++;                move16 (); /* index of energy VQ */
+
+        d_gain_code (index, code, L_SUBFR, &gain_code, bfi, state, prev_bf,
+                     rxdtx_ctrl, i_subfr, rx_dtx_state);
+#if (WMOPS)
+        fwc ();                 /* function worst case */
+#endif
+
+        /*-------------------------------------------------------*
+         * - Find the total excitation.                          *
+         * - Find synthesis speech corresponding to exc[].       *
+         *-------------------------------------------------------*/
+        for (i = 0; i < L_SUBFR; i++)
+        {
+            /* exc[i] = gain_pit*exc[i] + gain_code*code[i]; */
+
+            L_temp = L_mult (exc[i + i_subfr], gain_pit);
+            L_temp = L_mac (L_temp, code[i], gain_code);
+            L_temp = L_shl (L_temp, 3);
+
+            exc[i + i_subfr] = round (L_temp);
+                                        move16 (); 
+        }
+#if (WMOPS)
+        fwc ();                 /* function worst case */
+#endif
+
+        test (); 
+        if (sub (pit_sharp, 16384) > 0)
+        {
+            for (i = 0; i < L_SUBFR; i++)
+            {
+                excp[i] = add (excp[i], exc[i + i_subfr]);
+                                        move16 (); 
+            }
+            agc2 (&exc[i_subfr], excp, L_SUBFR);
+            Syn_filt (Az, excp, &synth[i_subfr], L_SUBFR, mem_syn, 1);
+        }
+        else
+        {
+            Syn_filt (Az, &exc[i_subfr], &synth[i_subfr], L_SUBFR, mem_syn, 1);
+        }
+
+#if (WMOPS)
+        fwc ();                 /* function worst case */
+#endif
+        /* interpolated LPC parameters for next subframe */
+        Az += MP1;                      move16 (); 
+    }
+
+    /*--------------------------------------------------*
+     * Update signal for next frame.                    *
+     * -> shift to the left by L_FRAME  exc[]           *
+     *--------------------------------------------------*/
+
+    Copy (&old_exc[L_FRAME], &old_exc[0], PIT_MAX + L_INTERPOL);
+#if (WMOPS)
+    fwc ();                     /* function worst case */
+#endif
+    prev_bf = bfi;                      move16 (); 
+
+    return;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgsmefr/dec_lag6.c	Fri Nov 25 16:18:21 2022 +0000
@@ -0,0 +1,118 @@
+/*************************************************************************
+ *   FUNCTION:   Dec_lag6
+ *
+ *   PURPOSE:  Decoding of fractional pitch lag with 1/6 resolution.
+ *             Extract the integer and fraction parts of the pitch lag from
+ *             the received adaptive codebook index.
+ *
+ *    See "Enc_lag6.c" for more details about the encoding procedure.
+ *
+ *    The fractional lag in 1st and 3rd subframes is encoded with 9 bits
+ *    while that in 2nd and 4th subframes is relatively encoded with 6 bits.
+ *    Note that in relative encoding only 61 values are used. If the
+ *    decoder receives 61, 62, or 63 as the relative pitch index, it means
+ *    that a transmission error occurred. In this case, the pitch lag from
+ *    previous subframe is used.
+ *
+ *************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "count.h"
+
+/* Old integer lag */
+
+Word16 old_T0;
+
+Word16 
+Dec_lag6 (             /* output: return integer pitch lag       */
+    Word16 index,      /* input : received pitch index           */
+    Word16 pit_min,    /* input : minimum pitch lag              */
+    Word16 pit_max,    /* input : maximum pitch lag              */
+    Word16 i_subfr,    /* input : subframe flag                  */
+    Word16 L_frame_by2,/* input : speech frame size divided by 2 */
+    Word16 *T0_frac,   /* output: fractional part of pitch lag   */
+    Word16 bfi         /* input : bad frame indicator            */
+)
+{
+    Word16 pit_flag;
+    Word16 T0, i;
+    static Word16 T0_min, T0_max;
+
+    pit_flag = i_subfr;         move16 (); /* flag for 1st or 3rd subframe */
+    test (); 
+    if (sub (i_subfr, L_frame_by2) == 0)
+    {
+        pit_flag = 0;           move16 (); 
+    }
+    test (); 
+    if (pit_flag == 0)          /* if 1st or 3rd subframe */
+    {
+        test (); 
+        if (bfi == 0)
+        {                       /* if bfi == 0 decode pitch */
+            test (); 
+            if (sub (index, 463) < 0)
+            {
+                /* T0 = (index+5)/6 + 17 */
+                T0 = add (mult (add (index, 5), 5462), 17);
+                i = add (add (T0, T0), T0);
+                /* *T0_frac = index - T0*6 + 105 */
+                *T0_frac = add (sub (index, add (i, i)), 105);
+                                move16 (); 
+            }
+            else
+            {
+                T0 = sub (index, 368);
+                *T0_frac = 0;   move16 (); 
+            }
+        }
+        else
+            /* bfi == 1 */
+        {
+            T0 = old_T0;        move16 (); 
+            *T0_frac = 0;       move16 (); 
+        }
+
+        /* find T0_min and T0_max for 2nd (or 4th) subframe */
+
+        T0_min = sub (T0, 5);
+        test (); 
+        if (sub (T0_min, pit_min) < 0)
+        {
+            T0_min = pit_min;   move16 (); 
+        }
+        T0_max = add (T0_min, 9);
+        test (); 
+        if (sub (T0_max, pit_max) > 0)
+        {
+            T0_max = pit_max;   move16 (); 
+            T0_min = sub (T0_max, 9);
+        }
+    }
+    else
+        /* second or fourth subframe */
+    {
+        test (); test (); 
+        /* if bfi == 0 decode pitch */
+        if ((bfi == 0) && (sub (index, 61) < 0))
+        {
+            /* i = (index+5)/6 - 1 */
+            i = sub (mult (add (index, 5), 5462), 1);
+            T0 = add (i, T0_min);
+            i = add (add (i, i), i);
+            *T0_frac = sub (sub (index, 3), add (i, i));
+                                move16 (); 
+        }
+        else
+            /* bfi == 1  OR index >= 61 */
+        {
+            T0 = old_T0;        move16 (); 
+            *T0_frac = 0;       move16 (); 
+        }
+    }
+
+    old_T0 = T0;                move16 (); 
+
+    return T0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgsmefr/e_homing.c	Fri Nov 25 16:18:21 2022 +0000
@@ -0,0 +1,163 @@
+/**************************************************************************
+ *
+ *   File Name:  e_homing.c
+ *
+ *   Purpose:
+ *      This file contains the following functions:
+ *
+ *      encoder_homing_frame_test()  checks if a frame of input samples
+ *                                   matches the Encoder Homing Frame pattern.
+ *
+ *      encoder_reset()              called by reset_enc() to reset all
+ *                                   the state variables for the encoder.
+ *
+ *      reset_enc()                  calls functions to reset the state
+ *                                   variables for the encoder and VAD, and
+ *                                   for the transmit DTX and Comfort Noise.
+ *
+ **************************************************************************/
+
+#include "typedef.h"
+#include "cnst.h"
+#include "vad.h"
+#include "dtx.h"
+#include "codec.h"
+#include "sig_proc.h"
+#include "e_homing.h"
+
+/***************************************************************************
+ *
+ *   FUNCTION NAME:  encoder_homing_frame_test
+ *
+ *   PURPOSE:
+ *      Checks if a frame of input samples matches the Encoder Homing Frame
+ *      pattern, which is 0x0008 for all 160 samples in the frame.
+ *
+ *   INPUT:
+ *      input_frame[]    one frame of speech samples
+ *
+ *   OUTPUT:
+ *      None
+ *
+ *   RETURN:
+ *      0       input frame does not match the Encoder Homing Frame pattern.
+ *      1       input frame matches the Encoder Homing Frame pattern.
+ *
+ **************************************************************************/
+
+Word16 encoder_homing_frame_test (Word16 input_frame[])
+{
+    Word16 i, j;
+
+    for (i = 0; i < L_FRAME; i++)
+    {
+        j = input_frame[i] ^ EHF_MASK;
+
+        if (j)
+            break;
+    }
+
+    return !j;
+}
+
+/***************************************************************************
+ *
+ *   FUNCTION NAME:  encoder_reset
+ *
+ *   PURPOSE:
+ *      resets all of the state variables for the encoder
+ *
+ *   INPUT:
+ *      None
+ *
+ *   OUTPUT:
+ *      None
+ *
+ *   RETURN:
+ *      None
+ *
+ **************************************************************************/
+
+void encoder_reset (void)
+{
+    /* External declarations for encoder variables which need to be reset */
+
+    /* Variables defined in levinson.c */
+    /* ------------------------------- */
+    extern Word16 old_A[M + 1]; /* Last A(z) for case of unstable filter */
+
+    /* Variables defined in q_gains.c */
+    /* ------------------------------- */
+    /* Memories of gain quantization: */
+    extern Word16 past_qua_en[4], pred[4];
+
+    /* Variables defined in q_plsf_5.c */
+    /* ------------------------------- */
+    /* Past quantized prediction error */
+    extern Word16 past_r2_q[M];
+
+    Word16 i;
+
+    /* reset all the encoder state variables */
+    /* ------------------------------------- */
+
+    /* Variables in cod_12k2.c: */
+    Init_Coder_12k2 ();
+
+    /* Variables in levinson.c: */
+    old_A[0] = 4096;            /* Last A(z) for case of unstable filter */
+    for (i = 1; i < M + 1; i++)
+    {
+        old_A[i] = 0;
+    }
+
+    /* Variables in pre_proc.c: */
+    Init_Pre_Process ();
+
+    /* Variables in q_gains.c: */
+    for (i = 0; i < 4; i++)
+    {
+        past_qua_en[i] = -2381; /* past quantized energies */
+    }
+
+    pred[0] = 44;               /* MA prediction coeff */
+    pred[1] = 37;               /* MA prediction coeff */
+    pred[2] = 22;               /* MA prediction coeff */
+    pred[3] = 12;               /* MA prediction coeff */
+
+    /* Variables in q_plsf_5.c: */
+    for (i = 0; i < M; i++)
+    {
+        past_r2_q[i] = 0;       /* Past quantized prediction error */
+    }
+
+    return;
+}
+
+/***************************************************************************
+ *
+ *   FUNCTION NAME:  reset_enc
+ *
+ *   PURPOSE:
+ *      resets all of the state variables for the encoder and VAD, and for
+ *      the transmit DTX and Comfort Noise.
+ *
+ *   INPUT:
+ *      None
+ *
+ *   OUTPUT:
+ *      None
+ *
+ *   RETURN:
+ *      None
+ *
+ **************************************************************************/
+
+void reset_enc (void)
+{
+    encoder_reset (); /* reset all the state variables in the speech encoder*/
+    vad_reset ();     /* reset all the VAD state variables */
+    reset_tx_dtx ();  /* reset all the transmit DTX and CN variables */
+
+    return;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgsmefr/enc_lag6.c	Fri Nov 25 16:18:21 2022 +0000
@@ -0,0 +1,97 @@
+/*************************************************************************
+ *
+ *   FUNCTION:  Enc_lag6
+ *
+ *   PURPOSE:  Encoding of fractional pitch lag with 1/6 resolution.
+ *
+ *   DESCRIPTION:
+ *                    First and third subframes:
+ *                    --------------------------
+ *   The pitch range is divided as follows:
+ *           17 3/6  to   94 3/6   resolution 1/6
+ *           95      to   143      resolution 1
+ *
+ *   The period is encoded with 9 bits.
+ *   For the range with fractions:
+ *     index = (T-17)*6 + frac - 3;
+ *                         where T=[17..94] and frac=[-2,-1,0,1,2,3]
+ *   and for the integer only range
+ *     index = (T - 95) + 463;        where T=[95..143]
+ *
+ *                    Second and fourth subframes:
+ *                    ----------------------------
+ *   For the 2nd and 4th subframes a resolution of 1/6 is always used,
+ *   and the search range is relative to the lag in previous subframe.
+ *   If t0 is the lag in the previous subframe then
+ *   t_min=t0-5   and  t_max=t0+4   and  the range is given by
+ *       (t_min-1) 3/6   to  (t_max) 3/6
+ *
+ *   The period in the 2nd (and 4th) subframe is encoded with 6 bits:
+ *     index = (T-(t_min-1))*6 + frac - 3;
+ *                 where T=[t_min-1..t_max] and frac=[-2,-1,0,1,2,3]
+ *
+ *   Note that only 61 values are used. If the decoder receives 61, 62,
+ *   or 63 as the relative pitch index, it means that a transmission
+ *   error occurred and the pitch from previous subframe should be used.
+ *
+ *************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "count.h"
+
+Word16 Enc_lag6 (      /* output: Return index of encoding     */
+    Word16 T0,         /* input : Pitch delay                  */
+    Word16 *T0_frac,   /* in/out: Fractional pitch delay       */
+    Word16 *T0_min,    /* in/out: Minimum search delay         */
+    Word16 *T0_max,    /* in/out: Maximum search delay         */
+    Word16 pit_min,    /* input : Minimum pitch delay          */
+    Word16 pit_max,    /* input : Maximum pitch delay          */
+    Word16 pit_flag    /* input : Flag for 1st or 3rd subframe */
+)
+{
+    Word16 index, i;
+
+    test (); 
+    if (pit_flag == 0)          /* if 1st or 3rd subframe */
+    {
+        /* encode pitch delay (with fraction) */
+
+        test (); 
+        if (sub (T0, 94) <= 0)
+        {
+            /* index = T0*6 - 105 + *T0_frac */
+            i = add (add (T0, T0), T0);
+            index = add (sub (add (i, i), 105), *T0_frac);
+        } else
+        {   /* set fraction to 0 for delays > 94 */
+            *T0_frac = 0;       move16 (); 
+            index = add (T0, 368);
+        }
+
+        /* find T0_min and T0_max for second (or fourth) subframe */
+
+        *T0_min = sub (T0, 5);  move16 (); 
+        test (); 
+        if (sub (*T0_min, pit_min) < 0)
+        {
+            *T0_min = pit_min;  move16 (); 
+        }
+        *T0_max = add (*T0_min, 9);
+        test (); 
+        if (sub (*T0_max, pit_max) > 0)
+        {
+            *T0_max = pit_max;  move16 (); 
+            *T0_min = sub (*T0_max, 9); move16 (); 
+        }
+    } else
+        /* if second or fourth subframe */
+    {
+        /* index = 6*(T0-*T0_min) + 3 + *T0_frac  */
+        i = sub (T0, *T0_min);
+        i = add (add (i, i), i);
+        index = add (add (add (i, i), 3), *T0_frac);
+    }
+
+    return index;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgsmefr/g_code.c	Fri Nov 25 16:18:21 2022 +0000
@@ -0,0 +1,77 @@
+/*************************************************************************
+ *
+ *  FUNCTION:   G_code
+ *
+ *  PURPOSE:  Compute the innovative codebook gain.
+ *
+ *  DESCRIPTION:
+ *      The innovative codebook gain is given by
+ *
+ *              g = <x[], y[]> / <y[], y[]>
+ *
+ *      where x[] is the target vector, y[] is the filtered innovative
+ *      codevector, and <> denotes dot product.
+ *
+ *************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "count.h"
+#include "cnst.h"
+
+Word16 G_code (         /* out   : Gain of innovation code         */
+    Word16 xn2[],       /* in    : target vector                   */
+    Word16 y2[]         /* in    : filtered innovation vector      */
+)
+{
+    Word16 i;
+    Word16 xy, yy, exp_xy, exp_yy, gain;
+    Word16 scal_y2[L_SUBFR];
+    Word32 s;
+
+    /* Scale down Y[] by 2 to avoid overflow */
+
+    for (i = 0; i < L_SUBFR; i++)
+    {
+        scal_y2[i] = shr (y2[i], 1);  move16 (); 
+    }
+
+    /* Compute scalar product <X[],Y[]> */
+
+    s = 1L;                           move32 (); /* Avoid case of all zeros */
+    for (i = 0; i < L_SUBFR; i++)
+    {
+        s = L_mac (s, xn2[i], scal_y2[i]);
+    }
+    exp_xy = norm_l (s);
+    xy = extract_h (L_shl (s, exp_xy));
+
+    /* If (xy < 0) gain = 0  */
+
+    test (); 
+    if (xy <= 0)
+        return ((Word16) 0);
+
+    /* Compute scalar product <Y[],Y[]> */
+
+    s = 0L;                           move32 (); 
+    for (i = 0; i < L_SUBFR; i++)
+    {
+        s = L_mac (s, scal_y2[i], scal_y2[i]);
+    }
+    exp_yy = norm_l (s);
+    yy = extract_h (L_shl (s, exp_yy));
+
+    /* compute gain = xy/yy */
+
+    xy = shr (xy, 1);                 /* Be sure xy < yy */
+    gain = div_s (xy, yy);
+
+    /* Denormalization of division */
+    i = add (exp_xy, 5);              /* 15-1+9-18 = 5 */
+    i = sub (i, exp_yy);
+
+    gain = shr (gain, i);
+
+    return (gain);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgsmefr/g_pitch.c	Fri Nov 25 16:18:21 2022 +0000
@@ -0,0 +1,128 @@
+/*************************************************************************
+ *
+ *  FUNCTION:  G_pitch
+ *
+ *  PURPOSE:  Compute the pitch (adaptive codebook) gain. Result in Q12
+ *
+ *  DESCRIPTION:
+ *      The adaptive codebook gain is given by
+ *
+ *              g = <x[], y[]> / <y[], y[]>
+ *
+ *      where x[] is the target vector, y[] is the filtered adaptive
+ *      codevector, and <> denotes dot product.
+ *      The gain is limited to the range [0,1.2]
+ *
+ *************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "oper_32b.h"
+#include "count.h"
+#include "sig_proc.h"
+
+Word16 G_pitch (        /* (o)   : Gain of pitch lag saturated to 1.2      */
+    Word16 xn[],        /* (i)   : Pitch target.                           */
+    Word16 y1[],        /* (i)   : Filtered adaptive codebook.             */
+    Word16 L_subfr      /*       : Length of subframe.                     */
+)
+{
+    Word16 i;
+    Word16 xy, yy, exp_xy, exp_yy, gain;
+    Word32 s;
+
+    Word16 scaled_y1[80];       /* Usually dynamic allocation of (L_subfr) */
+
+    /* divide by 2 "y1[]" to avoid overflow */
+
+    for (i = 0; i < L_subfr; i++)
+    {
+        scaled_y1[i] = shr (y1[i], 2); move16 (); 
+    }
+
+    /* Compute scalar product <y1[],y1[]> */
+
+    s = 0L;                            move32 (); /* Avoid case of all zeros */
+    for (i = 0; i < L_subfr; i++)
+    {
+        s = L_mac (s, y1[i], y1[i]);
+    }
+    test (); 
+    if (L_sub (s, MAX_32) != 0L)       /* Test for overflow */
+    {
+        s = L_add (s, 1L);             /* Avoid case of all zeros */
+        exp_yy = norm_l (s);
+        yy = round (L_shl (s, exp_yy));
+    }
+    else
+    {
+        s = 1L;                        move32 (); /* Avoid case of all zeros */
+        for (i = 0; i < L_subfr; i++)
+        {
+            s = L_mac (s, scaled_y1[i], scaled_y1[i]);
+        }
+        exp_yy = norm_l (s);
+        yy = round (L_shl (s, exp_yy));
+        exp_yy = sub (exp_yy, 4);
+    }
+
+    /* Compute scalar product <xn[],y1[]> */
+
+    Overflow = 0;                      move16 (); 
+    s = 1L;                            move32 (); /* Avoid case of all zeros */
+    for (i = 0; i < L_subfr; i++)
+    {
+        Carry = 0;                     move16 ();
+        s = L_macNs (s, xn[i], y1[i]);
+
+        test ();
+        if (Overflow != 0)
+        {
+	    break;
+        }
+    }
+    test (); 
+    if (Overflow == 0)
+    {
+        exp_xy = norm_l (s);
+        xy = round (L_shl (s, exp_xy));
+    }
+    else
+    {
+        s = 1L;                        move32 (); /* Avoid case of all zeros */
+        for (i = 0; i < L_subfr; i++)
+        {
+            s = L_mac (s, xn[i], scaled_y1[i]);
+        }
+        exp_xy = norm_l (s);
+        xy = round (L_shl (s, exp_xy));
+        exp_xy = sub (exp_xy, 2);
+    }
+
+    /* If (xy < 4) gain = 0 */
+
+    i = sub (xy, 4);
+
+    test (); 
+    if (i < 0)
+        return ((Word16) 0);
+
+    /* compute gain = xy/yy */
+
+    xy = shr (xy, 1);                  /* Be sure xy < yy */
+    gain = div_s (xy, yy);
+
+    i = add (exp_xy, 3 - 1);           /* Denormalization of division */
+    i = sub (i, exp_yy);
+
+    gain = shr (gain, i);
+
+    /* if(gain >1.2) gain = 1.2 */
+
+    test (); 
+    if (sub (gain, 4915) > 0)
+    {
+        gain = 4915;                   move16 (); 
+    }
+    return (gain);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgsmefr/int_lpc.c	Fri Nov 25 16:18:21 2022 +0000
@@ -0,0 +1,112 @@
+/*************************************************************************
+ *
+ *  FUNCTION:  Int_lpc()
+ *
+ *  PURPOSE:  Interpolates the LSPs and converts to LPC parameters to get
+ *            a different LP filter in each subframe.
+ *
+ *  DESCRIPTION:
+ *     The 20 ms speech frame is divided into 4 subframes.
+ *     The LSPs are quantized and transmitted at the 2nd and 4th subframes
+ *     (twice per frame) and interpolated at the 1st and 3rd subframe.
+ *
+ *          |------|------|------|------|
+ *             sf1    sf2    sf3    sf4
+ *       F0            Fm            F1
+ *
+ *     sf1:   1/2 Fm + 1/2 F0         sf3:   1/2 F1 + 1/2 Fm
+ *     sf2:       Fm                  sf4:       F1
+ *
+ *************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "count.h"
+#include "sig_proc.h"
+
+#define M   10                  /* LP order */
+#define MP1 11                  /* M+1 */
+
+void Int_lpc (
+    Word16 lsp_old[],   /* input : LSP vector at the 4th subframe
+                           of past frame    */
+    Word16 lsp_mid[],   /* input : LSP vector at the 2nd subframe
+                           of present frame */
+    Word16 lsp_new[],   /* input : LSP vector at the 4th subframe of
+                           present frame */
+    Word16 Az[]         /* output: interpolated LP parameters in
+                           all subframes */
+)
+{
+    Word16 i;
+    Word16 lsp[M];
+
+    /*  lsp[i] = lsp_mid[i] * 0.5 + lsp_old[i] * 0.5 */
+
+    for (i = 0; i < M; i++)
+    {
+        lsp[i] = add (shr (lsp_mid[i], 1), shr (lsp_old[i], 1));
+                                move16 (); 
+    }
+
+    Lsp_Az (lsp, Az);           /* Subframe 1 */
+    Az += MP1;                  move16 (); 
+
+    Lsp_Az (lsp_mid, Az);       /* Subframe 2 */
+    Az += MP1;                  move16 (); 
+
+    for (i = 0; i < M; i++)
+    {
+        lsp[i] = add (shr (lsp_mid[i], 1), shr (lsp_new[i], 1));
+                                move16 (); 
+    }
+
+    Lsp_Az (lsp, Az);           /* Subframe 3 */
+    Az += MP1;                  move16 (); 
+
+    Lsp_Az (lsp_new, Az);       /* Subframe 4 */
+
+    return;
+}
+
+/*----------------------------------------------------------------------*
+ * Function Int_lpc2()                                                  *
+ * ~~~~~~~~~~~~~~~~~~                                                   *
+ * Interpolation of the LPC parameters.                                 *
+ * Same as the previous function but we do not recompute Az() for       *
+ * subframe 2 and 4 because it is already available.                    *
+ *----------------------------------------------------------------------*/
+
+void Int_lpc2 (
+             Word16 lsp_old[],  /* input : LSP vector at the 4th subframe
+                                 of past frame    */
+             Word16 lsp_mid[],  /* input : LSP vector at the 2nd subframe
+                                 of present frame */
+             Word16 lsp_new[],  /* input : LSP vector at the 4th subframe of
+                                 present frame */
+             Word16 Az[]        /* output: interpolated LP parameters
+                                 in subframes 1 and 3 */
+)
+{
+    Word16 i;
+    Word16 lsp[M];
+
+    /*  lsp[i] = lsp_mid[i] * 0.5 + lsp_old[i] * 0.5 */
+
+    for (i = 0; i < M; i++)
+    {
+        lsp[i] = add (shr (lsp_mid[i], 1), shr (lsp_old[i], 1));
+                                move16 (); 
+    }
+    Lsp_Az (lsp, Az);           /* Subframe 1 */
+    Az += MP1 * 2;              move16 (); 
+
+    for (i = 0; i < M; i++)
+    {
+        lsp[i] = add (shr (lsp_mid[i], 1), shr (lsp_new[i], 1));
+                                move16 (); 
+    }
+    Lsp_Az (lsp, Az);           /* Subframe 3 */
+
+    return;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgsmefr/inter_6.c	Fri Nov 25 16:18:21 2022 +0000
@@ -0,0 +1,57 @@
+/*************************************************************************
+ *
+ *  FUNCTION:  Interpol_6()
+ *
+ *  PURPOSE:  Interpolating the normalized correlation with 1/6 resolution.
+ *
+ *************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "count.h"
+
+#define UP_SAMP      6
+#define L_INTERPOL   4
+#define FIR_SIZE     (UP_SAMP*L_INTERPOL+1)
+
+/* 1/6 resolution interpolation filter  (-3 dB at 3600 Hz) */
+
+static const Word16 inter_6[FIR_SIZE] =
+{
+    29519,
+    28316, 24906, 19838, 13896, 7945, 2755,
+    -1127, -3459, -4304, -3969, -2899, -1561,
+    -336, 534, 970, 1023, 823, 516,
+    220, 0, -131, -194, -215, 0
+};
+
+Word16 Interpol_6 (  /* (o)  : interpolated value  */
+    Word16 *x,       /* (i)  : input vector        */
+    Word16 frac      /* (i)  : fraction            */
+)
+{
+    Word16 i, k;
+    Word16 *x1, *x2;
+    const Word16 *c1, *c2;
+    Word32 s;
+
+    test (); 
+    if (frac < 0)
+    {
+        frac = add (frac, UP_SAMP);
+        x--;
+    }
+    x1 = &x[0];                         move16 (); 
+    x2 = &x[1];                         move16 (); 
+    c1 = &inter_6[frac];                move16 (); 
+    c2 = &inter_6[sub (UP_SAMP, frac)]; move16 (); 
+
+    s = 0;                              move32 (); 
+    for (i = 0, k = 0; i < L_INTERPOL; i++, k += UP_SAMP)
+    {
+        s = L_mac (s, x1[-i], c1[k]);
+        s = L_mac (s, x2[i], c2[k]);
+    }
+
+    return round (s);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgsmefr/inv_sqrt.c	Fri Nov 25 16:18:21 2022 +0000
@@ -0,0 +1,67 @@
+/*************************************************************************
+ *
+ *  FUNCTION:   Inv_sqrt
+ *
+ *  PURPOSE:   Computes 1/sqrt(L_x),  where  L_x is positive.
+ *             If L_x is negative or zero, the result is 1 (3fff ffff).
+ *
+ *  DESCRIPTION:
+ *       The function 1/sqrt(L_x) is approximated by a table and linear
+ *       interpolation. The inverse square root is computed using the
+ *       following steps:
+ *          1- Normalization of L_x.
+ *          2- If (30-exponent) is even then shift right once.
+ *          3- exponent = (30-exponent)/2  +1
+ *          4- i = bit25-b31 of L_x;  16<=i<=63  because of normalization.
+ *          5- a = bit10-b24
+ *          6- i -=16
+ *          7- L_y = table[i]<<16 - (table[i] - table[i+1]) * a * 2
+ *          8- L_y >>= exponent
+ *
+ *************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "count.h"
+
+#include "inv_sqrt.tab" /* Table for inv_sqrt() */
+
+Word32 Inv_sqrt (       /* (o) : output value   */
+    Word32 L_x          /* (i) : input value    */
+)
+{
+    Word16 exp, i, a, tmp;
+    Word32 L_y;
+
+    test (); 
+    if (L_x <= (Word32) 0)
+        return ((Word32) 0x3fffffffL);
+
+    exp = norm_l (L_x);
+    L_x = L_shl (L_x, exp);     /* L_x is normalize */
+
+    exp = sub (30, exp);
+    test (); logic16 (); 
+    if ((exp & 1) == 0)         /* If exponent even -> shift right */
+    {
+        L_x = L_shr (L_x, 1);
+    }
+    exp = shr (exp, 1);
+    exp = add (exp, 1);
+
+    L_x = L_shr (L_x, 9);
+    i = extract_h (L_x);        /* Extract b25-b31 */
+    L_x = L_shr (L_x, 1);
+    a = extract_l (L_x);        /* Extract b10-b24 */
+    a = a & (Word16) 0x7fff;    logic16 (); 
+
+    i = sub (i, 16);
+
+    L_y = L_deposit_h (table[i]);       /* table[i] << 16          */
+    tmp = sub (table[i], table[i + 1]); /* table[i] - table[i+1])  */
+    L_y = L_msu (L_y, tmp, a);  /* L_y -=  tmp*a*2         */
+
+    L_y = L_shr (L_y, exp);     /* denormalization */
+
+    return (L_y);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgsmefr/lag_wind.c	Fri Nov 25 16:18:21 2022 +0000
@@ -0,0 +1,37 @@
+/*************************************************************************
+ *
+ *  FUNCTION:  Lag_window()
+ *
+ *  PURPOSE:  Lag windowing of autocorrelations.
+ *
+ *  DESCRIPTION:
+ *         r[i] = r[i]*lag_wind[i],   i=1,...,10
+ *
+ *     r[i] and lag_wind[i] are in special double precision format.
+ *     See "oper_32b.c" for the format.
+ *
+ *************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "oper_32b.h"
+#include "count.h"
+
+#include "lag_wind.tab"
+
+void Lag_window (
+    Word16 m,           /* (i)     : LPC order                        */
+    Word16 r_h[],       /* (i/o)   : Autocorrelations  (msb)          */
+    Word16 r_l[]        /* (i/o)   : Autocorrelations  (lsb)          */
+)
+{
+    Word16 i;
+    Word32 x;
+
+    for (i = 1; i <= m; i++)
+    {
+        x = Mpy_32 (r_h[i], r_l[i], lag_h[i - 1], lag_l[i - 1]);
+        L_Extract (x, &r_h[i], &r_l[i]);
+    }
+    return;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgsmefr/levinson.c	Fri Nov 25 16:18:21 2022 +0000
@@ -0,0 +1,194 @@
+/*************************************************************************
+ *
+ *   FUNCTION:  Levinson()
+ *
+ *   PURPOSE:  Levinson-Durbin algorithm in double precision. To compute the
+ *             LP filter parameters from the speech autocorrelations.
+ *
+ *   DESCRIPTION:
+ *       R[i]    autocorrelations.
+ *       A[i]    filter coefficients.
+ *       K       reflection coefficients.
+ *       Alpha   prediction gain.
+ *
+ *       Initialisation:
+ *               A[0] = 1
+ *               K    = -R[1]/R[0]
+ *               A[1] = K
+ *               Alpha = R[0] * (1-K**2]
+ *
+ *       Do for  i = 2 to M
+ *
+ *            S =  SUM ( R[j]*A[i-j] ,j=1,i-1 ) +  R[i]
+ *
+ *            K = -S / Alpha
+ *
+ *            An[j] = A[j] + K*A[i-j]   for j=1 to i-1
+ *                                      where   An[i] = new A[i]
+ *            An[i]=K
+ *
+ *            Alpha=Alpha * (1-K**2)
+ *
+ *       END
+ *
+ *************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "oper_32b.h"
+#include "count.h"
+
+/* Lpc order == 10 */
+
+#define M 10
+
+/* Last A(z) for case of unstable filter */
+
+Word16 old_A[M + 1];
+
+void Levinson (
+    Word16 Rh[],    /* (i)     : Rh[m+1] Vector of autocorrelations (msb) */
+    Word16 Rl[],    /* (i)     : Rl[m+1] Vector of autocorrelations (lsb) */
+    Word16 A[],     /* (o)     : A[m]    LPC coefficients  (m = 10)       */
+    Word16 rc[]     /* (o)     : rc[4]   First 4 reflection coefficients  */
+
+)
+{
+    Word16 i, j;
+    Word16 hi, lo;
+    Word16 Kh, Kl;                /* reflexion coefficient; hi and lo      */
+    Word16 alp_h, alp_l, alp_exp; /* Prediction gain; hi lo and exponent   */
+    Word16 Ah[M + 1], Al[M + 1];  /* LPC coef. in double prec.             */
+    Word16 Anh[M + 1], Anl[M + 1];/* LPC coef.for next iteration in double
+                                     prec. */
+    Word32 t0, t1, t2;            /* temporary variable                    */
+
+    /* K = A[1] = -R[1] / R[0] */
+
+    t1 = L_Comp (Rh[1], Rl[1]);
+    t2 = L_abs (t1);                    /* abs R[1]         */
+    t0 = Div_32 (t2, Rh[0], Rl[0]);     /* R[1]/R[0]        */
+    test (); 
+    if (t1 > 0)
+        t0 = L_negate (t0);             /* -R[1]/R[0]       */
+    L_Extract (t0, &Kh, &Kl);           /* K in DPF         */
+
+    rc[0] = round (t0);                 move16 (); 
+
+    t0 = L_shr (t0, 4);                 /* A[1] in          */
+    L_Extract (t0, &Ah[1], &Al[1]);     /* A[1] in DPF      */
+
+    /*  Alpha = R[0] * (1-K**2) */
+
+    t0 = Mpy_32 (Kh, Kl, Kh, Kl);       /* K*K             */
+    t0 = L_abs (t0);                    /* Some case <0 !! */
+    t0 = L_sub ((Word32) 0x7fffffffL, t0); /* 1 - K*K        */
+    L_Extract (t0, &hi, &lo);           /* DPF format      */
+    t0 = Mpy_32 (Rh[0], Rl[0], hi, lo); /* Alpha in        */
+
+    /* Normalize Alpha */
+
+    alp_exp = norm_l (t0);
+    t0 = L_shl (t0, alp_exp);
+    L_Extract (t0, &alp_h, &alp_l);     /* DPF format    */
+
+    /*--------------------------------------*
+     * ITERATIONS  I=2 to M                 *
+     *--------------------------------------*/
+
+    for (i = 2; i <= M; i++)
+    {
+        /* t0 = SUM ( R[j]*A[i-j] ,j=1,i-1 ) +  R[i] */
+
+        t0 = 0;                         move32 (); 
+        for (j = 1; j < i; j++)
+        {
+            t0 = L_add (t0, Mpy_32 (Rh[j], Rl[j], Ah[i - j], Al[i - j]));
+        }
+        t0 = L_shl (t0, 4);
+
+        t1 = L_Comp (Rh[i], Rl[i]);
+        t0 = L_add (t0, t1);            /* add R[i]        */
+
+        /* K = -t0 / Alpha */
+
+        t1 = L_abs (t0);
+        t2 = Div_32 (t1, alp_h, alp_l); /* abs(t0)/Alpha              */
+        test (); 
+        if (t0 > 0)
+            t2 = L_negate (t2);         /* K =-t0/Alpha                */
+        t2 = L_shl (t2, alp_exp);       /* denormalize; compare to Alpha */
+        L_Extract (t2, &Kh, &Kl);       /* K in DPF                      */
+
+        test (); 
+        if (sub (i, 5) < 0)
+        {
+            rc[i - 1] = round (t2);     move16 (); 
+        }
+        /* Test for unstable filter. If unstable keep old A(z) */
+
+        test (); 
+        if (sub (abs_s (Kh), 32750) > 0)
+        {
+            for (j = 0; j <= M; j++)
+            {
+                A[j] = old_A[j];        move16 (); 
+            }
+
+            for (j = 0; j < 4; j++)
+            {
+                rc[j] = 0;              move16 (); 
+            }
+
+            return;
+        }
+        /*------------------------------------------*
+         *  Compute new LPC coeff. -> An[i]         *
+         *  An[j]= A[j] + K*A[i-j]     , j=1 to i-1 *
+         *  An[i]= K                                *
+         *------------------------------------------*/
+
+        for (j = 1; j < i; j++)
+        {
+            t0 = Mpy_32 (Kh, Kl, Ah[i - j], Al[i - j]);
+            t0 = L_mac (t0, Ah[j], 32767);
+            t0 = L_mac (t0, Al[j], 1);
+            L_Extract (t0, &Anh[j], &Anl[j]);
+        }
+        t2 = L_shr (t2, 4);
+        L_Extract (t2, &Anh[i], &Anl[i]);
+
+        /*  Alpha = Alpha * (1-K**2) */
+
+        t0 = Mpy_32 (Kh, Kl, Kh, Kl);           /* K*K             */
+        t0 = L_abs (t0);                        /* Some case <0 !! */
+        t0 = L_sub ((Word32) 0x7fffffffL, t0);  /* 1 - K*K        */
+        L_Extract (t0, &hi, &lo);               /* DPF format      */
+        t0 = Mpy_32 (alp_h, alp_l, hi, lo);
+
+        /* Normalize Alpha */
+
+        j = norm_l (t0);
+        t0 = L_shl (t0, j);
+        L_Extract (t0, &alp_h, &alp_l);         /* DPF format    */
+        alp_exp = add (alp_exp, j);             /* Add normalization to
+                                                   alp_exp */
+
+        /* A[j] = An[j] */
+
+        for (j = 1; j <= i; j++)
+        {
+            Ah[j] = Anh[j];                     move16 (); 
+            Al[j] = Anl[j];                     move16 (); 
+        }
+    }
+
+    A[0] = 4096;                                move16 (); 
+    for (i = 1; i <= M; i++)
+    {
+        t0 = L_Comp (Ah[i], Al[i]);
+        old_A[i] = A[i] = round (L_shl (t0, 1));move16 (); move16 (); 
+    }
+
+    return;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgsmefr/log2.c	Fri Nov 25 16:18:21 2022 +0000
@@ -0,0 +1,63 @@
+/*************************************************************************
+ *
+ *   FUNCTION:   Log2()
+ *
+ *   PURPOSE:   Computes log2(L_x),  where   L_x is positive.
+ *              If L_x is negative or zero, the result is 0.
+ *
+ *   DESCRIPTION:
+ *        The function Log2(L_x) is approximated by a table and linear
+ *        interpolation. The following steps are used to compute Log2(L_x)
+ *
+ *           1- Normalization of L_x.
+ *           2- exponent = 30-exponent
+ *           3- i = bit25-b31 of L_x;  32<=i<=63  (because of normalization).
+ *           4- a = bit10-b24
+ *           5- i -=32
+ *           6- fraction = table[i]<<16 - (table[i] - table[i+1]) * a * 2
+ *
+ *************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "count.h"
+
+#include "log2.tab"     /* Table for Log2() */
+
+void Log2 (
+    Word32 L_x,         /* (i) : input value                                 */
+    Word16 *exponent,   /* (o) : Integer part of Log2.   (range: 0<=val<=30) */
+    Word16 *fraction    /* (o) : Fractional part of Log2. (range: 0<=val<1) */
+)
+{
+    Word16 exp, i, a, tmp;
+    Word32 L_y;
+
+    test (); 
+    if (L_x <= (Word32) 0)
+    {
+        *exponent = 0;          move16 (); 
+        *fraction = 0;          move16 (); 
+        return;
+    }
+    exp = norm_l (L_x);
+    L_x = L_shl (L_x, exp);     /* L_x is normalized */
+
+    *exponent = sub (30, exp);  move16 (); 
+
+    L_x = L_shr (L_x, 9);
+    i = extract_h (L_x);        /* Extract b25-b31 */
+    L_x = L_shr (L_x, 1);
+    a = extract_l (L_x);        /* Extract b10-b24 of fraction */
+    a = a & (Word16) 0x7fff;    logic16 (); 
+
+    i = sub (i, 32);
+
+    L_y = L_deposit_h (table[i]);       /* table[i] << 16        */
+    tmp = sub (table[i], table[i + 1]); /* table[i] - table[i+1] */
+    L_y = L_msu (L_y, tmp, a);  /* L_y -= tmp*a*2        */
+
+    *fraction = extract_h (L_y);move16 (); 
+
+    return;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgsmefr/lsp_az.c	Fri Nov 25 16:18:21 2022 +0000
@@ -0,0 +1,117 @@
+/*************************************************************************
+ *
+ *  FUNCTION:   Lsp_Az
+ *
+ *  PURPOSE:  Converts from the line spectral pairs (LSP) to
+ *            LP coefficients, for a 10th order filter.
+ *
+ *  DESCRIPTION:
+ *     - Find the coefficients of F1(z) and F2(z) (see Get_lsp_pol)
+ *     - Multiply F1(z) by 1+z^{-1} and F2(z) by 1-z^{-1}
+ *     - A(z) = ( F1(z) + F2(z) ) / 2
+ *
+ *************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "oper_32b.h"
+#include "count.h"
+#include "sig_proc.h"
+
+/* local function */
+
+static void Get_lsp_pol (Word16 *lsp, Word32 *f);
+
+void Lsp_Az (
+    Word16 lsp[],        /* (i)  : line spectral frequencies            */
+    Word16 a[]           /* (o)  : predictor coefficients (order = 10)  */
+)
+{
+    Word16 i, j;
+    Word32 f1[6], f2[6];
+    Word32 t0;
+
+    Get_lsp_pol (&lsp[0], f1);
+    Get_lsp_pol (&lsp[1], f2);
+
+    for (i = 5; i > 0; i--)
+    {
+        f1[i] = L_add (f1[i], f1[i - 1]);    move32 (); /* f1[i] += f1[i-1]; */
+        f2[i] = L_sub (f2[i], f2[i - 1]);    move32 (); /* f2[i] -= f2[i-1]; */
+    }
+
+    a[0] = 4096;                             move16 (); 
+    for (i = 1, j = 10; i <= 5; i++, j--)
+    {
+        t0 = L_add (f1[i], f2[i]);           /* f1[i] + f2[i] */
+        a[i] = extract_l (L_shr_r (t0, 13)); move16 (); 
+        t0 = L_sub (f1[i], f2[i]);           /* f1[i] - f2[i] */
+        a[j] = extract_l (L_shr_r (t0, 13)); move16 (); 
+    }
+
+    return;
+}
+
+/*************************************************************************
+ *
+ *  FUNCTION:  Get_lsp_pol
+ *
+ *  PURPOSE:  Find the polynomial F1(z) or F2(z) from the LSPs.
+ *            If the LSP vector is passed at address 0  F1(z) is computed
+ *            and if it is passed at address 1  F2(z) is computed.
+ *
+ *  DESCRIPTION:
+ *       This is performed by expanding the product polynomials:
+ *
+ *           F1(z) =   product   ( 1 - 2 lsp[i] z^-1 + z^-2 )
+ *                   i=0,2,4,6,8
+ *           F2(z) =   product   ( 1 - 2 lsp[i] z^-1 + z^-2 )
+ *                   i=1,3,5,7,9
+ *
+ *       where lsp[] is the LSP vector in the cosine domain.
+ *
+ *       The expansion is performed using the following recursion:
+ *
+ *            f[0] = 1
+ *            b = -2.0 * lsp[0]
+ *            f[1] = b
+ *            for i=2 to 5 do
+ *               b = -2.0 * lsp[2*i-2];
+ *               f[i] = b*f[i-1] + 2.0*f[i-2];
+ *               for j=i-1 down to 2 do
+ *                   f[j] = f[j] + b*f[j-1] + f[j-2];
+ *               f[1] = f[1] + b;
+ *
+ *************************************************************************/
+
+static void Get_lsp_pol (Word16 *lsp, Word32 *f)
+{
+    Word16 i, j, hi, lo;
+    Word32 t0;
+    
+    /* f[0] = 1.0;             */
+    *f = L_mult (4096, 2048);              move32 (); 
+    f++;                                   move32 (); 
+    *f = L_msu ((Word32) 0, *lsp, 512);    /* f[1] =  -2.0 * lsp[0];  */
+    f++;                                   move32 (); 
+    lsp += 2;                              /* Advance lsp pointer     */
+
+    for (i = 2; i <= 5; i++)
+    {
+        *f = f[-2];                        move32 (); 
+
+        for (j = 1; j < i; j++, f--)
+        {
+            L_Extract (f[-1], &hi, &lo);
+            t0 = Mpy_32_16 (hi, lo, *lsp); /* t0 = f[-1] * lsp    */
+            t0 = L_shl (t0, 1);
+            *f = L_add (*f, f[-2]);        move32 (); /* *f += f[-2]      */
+            *f = L_sub (*f, t0);move32 (); /* *f -= t0            */
+        }
+        *f = L_msu (*f, *lsp, 512);        move32 (); /* *f -= lsp<<9     */
+        f += i;                            /* Advance f pointer   */
+        lsp += 2;                          /* Advance lsp pointer */
+    }
+
+    return;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgsmefr/lsp_lsf.c	Fri Nov 25 16:18:21 2022 +0000
@@ -0,0 +1,76 @@
+/*************************************************************************
+ *
+ *   FUNCTIONS:  Lsp_lsf and Lsf_lsp
+ *
+ *   PURPOSE:
+ *      Lsp_lsf:   Transformation lsp to lsf
+ *      Lsf_lsp:   Transformation lsf to lsp
+ *
+ *   DESCRIPTION:
+ *         lsp[i] = cos(2*pi*lsf[i]) and lsf[i] = arccos(lsp[i])/(2*pi)
+ *
+ *   The transformation from lsp[i] to lsf[i] and lsf[i] to lsp[i] are
+ *   approximated by a look-up table and interpolation.
+ *
+ *************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "count.h"
+
+#include "lsp_lsf.tab"          /* Look-up table for transformations */
+
+void Lsf_lsp (
+    Word16 lsf[],       /* (i) : lsf[m] normalized (range: 0.0<=val<=0.5) */
+    Word16 lsp[],       /* (o) : lsp[m] (range: -1<=val<1)                */
+    Word16 m            /* (i) : LPC order                                */
+)
+{
+    Word16 i, ind, offset;
+    Word32 L_tmp;
+
+    for (i = 0; i < m; i++)
+    {
+        ind = shr (lsf[i], 8);      /* ind    = b8-b15 of lsf[i] */
+        offset = lsf[i] & 0x00ff;   logic16 (); /* offset = b0-b7  of lsf[i] */
+
+        /* lsp[i] = table[ind]+ ((table[ind+1]-table[ind])*offset) / 256 */
+
+        L_tmp = L_mult (sub (table[ind + 1], table[ind]), offset);
+        lsp[i] = add (table[ind], extract_l (L_shr (L_tmp, 9)));
+                                    move16 (); 
+    }
+    return;
+}
+
+void Lsp_lsf (
+    Word16 lsp[],       /* (i)  : lsp[m] (range: -1<=val<1)                */
+    Word16 lsf[],       /* (o)  : lsf[m] normalized (range: 0.0<=val<=0.5) */
+    Word16 m            /* (i)  : LPC order                                */
+)
+{
+    Word16 i, ind;
+    Word32 L_tmp;
+
+    ind = 63;                       /* begin at end of table -1 */
+
+    for (i = m - 1; i >= 0; i--)
+    {
+        /* find value in table that is just greater than lsp[i] */
+        test (); 
+        while (sub (table[ind], lsp[i]) < 0)
+        {
+            ind--;
+            test (); 
+        }
+
+        /* acos(lsp[i])= ind*256 + ( ( lsp[i]-table[ind] ) *
+           slope[ind] )/4096 */
+
+        L_tmp = L_mult (sub (lsp[i], table[ind]), slope[ind]);
+        /*(lsp[i]-table[ind])*slope[ind])>>12*/
+        lsf[i] = round (L_shl (L_tmp, 3));      move16 (); 
+        lsf[i] = add (lsf[i], shl (ind, 8));    move16 (); 
+    }
+    return;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgsmefr/oper_32b.c	Fri Nov 25 16:18:21 2022 +0000
@@ -0,0 +1,208 @@
+/*****************************************************************************
+ *                                                                           *
+ *  This file contains operations in double precision.                       *
+ *  These operations are not standard double precision operations.           *
+ *  They are used where single precision is not enough but the full 32 bits  *
+ *  precision is not necessary. For example, the function Div_32() has a     *
+ *  24 bits precision which is enough for our purposes.                      *
+ *                                                                           *
+ *  The double precision numbers use a special representation:               *
+ *                                                                           *
+ *     L_32 = hi<<16 + lo<<1                                                 *
+ *                                                                           *
+ *  L_32 is a 32 bit integer.                                                *
+ *  hi and lo are 16 bit signed integers.                                    *
+ *  As the low part also contains the sign, this allows fast multiplication. *
+ *                                                                           *
+ *      0x8000 0000 <= L_32 <= 0x7fff fffe.                                  *
+ *                                                                           *
+ *  We will use DPF (Double Precision Format )in this file to specify        *
+ *  this special format.                                                     *
+ *****************************************************************************
+*/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "oper_32b.h"
+#include "count.h"
+
+/*****************************************************************************
+ *                                                                           *
+ *  Function L_Extract()                                                     *
+ *                                                                           *
+ *  Extract from a 32 bit integer two 16 bit DPF.                            *
+ *                                                                           *
+ *  Arguments:                                                               *
+ *                                                                           *
+ *   L_32      : 32 bit integer.                                             *
+ *               0x8000 0000 <= L_32 <= 0x7fff ffff.                         *
+ *   hi        : b16 to b31 of L_32                                          *
+ *   lo        : (L_32 - hi<<16)>>1                                          *
+ *****************************************************************************
+*/
+
+void L_Extract (Word32 L_32, Word16 *hi, Word16 *lo)
+{
+    *hi = extract_h (L_32);
+    *lo = extract_l (L_msu (L_shr (L_32, 1), *hi, 16384));
+    return;
+}
+
+/*****************************************************************************
+ *                                                                           *
+ *  Function L_Comp()                                                        *
+ *                                                                           *
+ *  Compose from two 16 bit DPF a 32 bit integer.                            *
+ *                                                                           *
+ *     L_32 = hi<<16 + lo<<1                                                 *
+ *                                                                           *
+ *  Arguments:                                                               *
+ *                                                                           *
+ *   hi        msb                                                           *
+ *   lo        lsf (with sign)                                               *
+ *                                                                           *
+ *   Return Value :                                                          *
+ *                                                                           *
+ *             32 bit long signed integer (Word32) whose value falls in the  *
+ *             range : 0x8000 0000 <= L_32 <= 0x7fff fff0.                   *
+ *                                                                           *
+ *****************************************************************************
+*/
+
+Word32 L_Comp (Word16 hi, Word16 lo)
+{
+    Word32 L_32;
+
+    L_32 = L_deposit_h (hi);
+    return (L_mac (L_32, lo, 1));       /* = hi<<16 + lo<<1 */
+}
+
+/*****************************************************************************
+ * Function Mpy_32()                                                         *
+ *                                                                           *
+ *   Multiply two 32 bit integers (DPF). The result is divided by 2**31      *
+ *                                                                           *
+ *   L_32 = (hi1*hi2)<<1 + ( (hi1*lo2)>>15 + (lo1*hi2)>>15 )<<1              *
+ *                                                                           *
+ *   This operation can also be viewed as the multiplication of two Q31      *
+ *   number and the result is also in Q31.                                   *
+ *                                                                           *
+ * Arguments:                                                                *
+ *                                                                           *
+ *  hi1         hi part of first number                                      *
+ *  lo1         lo part of first number                                      *
+ *  hi2         hi part of second number                                     *
+ *  lo2         lo part of second number                                     *
+ *                                                                           *
+ *****************************************************************************
+*/
+
+Word32 Mpy_32 (Word16 hi1, Word16 lo1, Word16 hi2, Word16 lo2)
+{
+    Word32 L_32;
+
+    L_32 = L_mult (hi1, hi2);
+    L_32 = L_mac (L_32, mult (hi1, lo2), 1);
+    L_32 = L_mac (L_32, mult (lo1, hi2), 1);
+
+    return (L_32);
+}
+
+/*****************************************************************************
+ * Function Mpy_32_16()                                                      *
+ *                                                                           *
+ *   Multiply a 16 bit integer by a 32 bit (DPF). The result is divided      *
+ *   by 2**15                                                                *
+ *                                                                           *
+ *                                                                           *
+ *   L_32 = (hi1*lo2)<<1 + ((lo1*lo2)>>15)<<1                                *
+ *                                                                           *
+ * Arguments:                                                                *
+ *                                                                           *
+ *  hi          hi part of 32 bit number.                                    *
+ *  lo          lo part of 32 bit number.                                    *
+ *  n           16 bit number.                                               *
+ *                                                                           *
+ *****************************************************************************
+*/
+
+Word32 Mpy_32_16 (Word16 hi, Word16 lo, Word16 n)
+{
+    Word32 L_32;
+
+    L_32 = L_mult (hi, n);
+    L_32 = L_mac (L_32, mult (lo, n), 1);
+
+    return (L_32);
+}
+
+/*****************************************************************************
+ *                                                                           *
+ *   Function Name : Div_32                                                  *
+ *                                                                           *
+ *   Purpose :                                                               *
+ *             Fractional integer division of two 32 bit numbers.            *
+ *             L_num / L_denom.                                              *
+ *             L_num and L_denom must be positive and L_num < L_denom.       *
+ *             L_denom = denom_hi<<16 + denom_lo<<1                          *
+ *             denom_hi is a normalize number.                               *
+ *                                                                           *
+ *   Inputs :                                                                *
+ *                                                                           *
+ *    L_num                                                                  *
+ *             32 bit long signed integer (Word32) whose value falls in the  *
+ *             range : 0x0000 0000 < L_num < L_denom                         *
+ *                                                                           *
+ *    L_denom = denom_hi<<16 + denom_lo<<1      (DPF)                        *
+ *                                                                           *
+ *       denom_hi                                                            *
+ *             16 bit positive normalized integer whose value falls in the   *
+ *             range : 0x4000 < hi < 0x7fff                                  *
+ *       denom_lo                                                            *
+ *             16 bit positive integer whose value falls in the              *
+ *             range : 0 < lo < 0x7fff                                       *
+ *                                                                           *
+ *   Return Value :                                                          *
+ *                                                                           *
+ *    L_div                                                                  *
+ *             32 bit long signed integer (Word32) whose value falls in the  *
+ *             range : 0x0000 0000 <= L_div <= 0x7fff ffff.                  *
+ *                                                                           *
+ *  Algorithm:                                                               *
+ *                                                                           *
+ *  - find = 1/L_denom.                                                      *
+ *      First approximation: approx = 1 / denom_hi                           *
+ *      1/L_denom = approx * (2.0 - L_denom * approx )                       *
+ *                                                                           *
+ *  -  result = L_num * (1/L_denom)                                          *
+ *****************************************************************************
+*/
+
+Word32 Div_32 (Word32 L_num, Word16 denom_hi, Word16 denom_lo)
+{
+    Word16 approx, hi, lo, n_hi, n_lo;
+    Word32 L_32;
+
+    /* First approximation: 1 / L_denom = 1/denom_hi */
+
+    approx = div_s ((Word16) 0x3fff, denom_hi);
+
+    /* 1/L_denom = approx * (2.0 - L_denom * approx) */
+
+    L_32 = Mpy_32_16 (denom_hi, denom_lo, approx);
+
+    L_32 = L_sub ((Word32) 0x7fffffffL, L_32);
+
+    L_Extract (L_32, &hi, &lo);
+
+    L_32 = Mpy_32_16 (hi, lo, approx);
+
+    /* L_num * (1/L_denom) */
+
+    L_Extract (L_32, &hi, &lo);
+    L_Extract (L_num, &n_hi, &n_lo);
+    L_32 = Mpy_32 (n_hi, n_lo, hi, lo);
+    L_32 = L_shl (L_32, 2);
+
+    return (L_32);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgsmefr/pitch_f6.c	Fri Nov 25 16:18:21 2022 +0000
@@ -0,0 +1,227 @@
+/*************************************************************************
+ *
+ *  FUNCTION:   Pitch_fr6()
+ *
+ *  PURPOSE: Find the pitch period with 1/6 subsample resolution (closed loop).
+ *
+ *  DESCRIPTION:
+ *        - find the normalized correlation between the target and filtered
+ *          past excitation in the search range.
+ *        - select the delay with maximum normalized correlation.
+ *        - interpolate the normalized correlation at fractions -3/6 to 3/6
+ *          with step 1/6 around the chosen delay.
+ *        - The fraction which gives the maximum interpolated value is chosen.
+ *
+ *************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "oper_32b.h"
+#include "count.h"
+#include "sig_proc.h"
+#include "codec.h"
+
+ /* L_inter = Length for fractional interpolation = nb.coeff/2 */
+
+#define L_inter 4
+
+ /* Local functions */
+
+void Norm_Corr (Word16 exc[], Word16 xn[], Word16 h[], Word16 L_subfr,
+                Word16 t_min, Word16 t_max, Word16 corr_norm[]);
+
+Word16 Pitch_fr6 (    /* (o)     : pitch period.                          */
+    Word16 exc[],     /* (i)     : excitation buffer                      */
+    Word16 xn[],      /* (i)     : target vector                          */
+    Word16 h[],       /* (i)     : impulse response of synthesis and
+                                    weighting filters                     */
+    Word16 L_subfr,   /* (i)     : Length of subframe                     */
+    Word16 t0_min,    /* (i)     : minimum value in the searched range.   */
+    Word16 t0_max,    /* (i)     : maximum value in the searched range.   */
+    Word16 i_subfr,   /* (i)     : indicator for first subframe.          */
+    Word16 *pit_frac  /* (o)     : chosen fraction.                       */
+)
+{
+    Word16 i;
+    Word16 t_min, t_max;
+    Word16 max, lag, frac;
+    Word16 *corr;
+    Word16 corr_int;
+    Word16 corr_v[40];          /* Total length = t0_max-t0_min+1+2*L_inter */
+
+    /* Find interval to compute normalized correlation */
+
+    t_min = sub (t0_min, L_inter);
+    t_max = add (t0_max, L_inter);
+
+    corr = &corr_v[-t_min];                    move16 (); 
+
+    /* Compute normalized correlation between target and filtered excitation */
+
+    Norm_Corr (exc, xn, h, L_subfr, t_min, t_max, corr);
+
+    /* Find integer pitch */
+
+    max = corr[t0_min];                        move16 (); 
+    lag = t0_min;                              move16 (); 
+
+    for (i = t0_min + 1; i <= t0_max; i++)
+    {
+        test (); 
+        if (sub (corr[i], max) >= 0)
+        {
+            max = corr[i];                     move16 (); 
+            lag = i;                           move16 (); 
+        }
+    }
+
+    /* If first subframe and lag > 94 do not search fractional pitch */
+
+    test (); test (); 
+    if ((i_subfr == 0) && (sub (lag, 94) > 0))
+    {
+        *pit_frac = 0;                         move16 (); 
+        return (lag);
+    }
+    /* Test the fractions around T0 and choose the one which maximizes   */
+    /* the interpolated normalized correlation.                          */
+
+    max = Interpol_6 (&corr[lag], -3);
+    frac = -3;                                 move16 (); 
+
+    for (i = -2; i <= 3; i++)
+    {
+        corr_int = Interpol_6 (&corr[lag], i); move16 (); 
+        test (); 
+        if (sub (corr_int, max) > 0)
+        {
+            max = corr_int;                    move16 (); 
+            frac = i;                          move16 (); 
+        }
+    }
+
+    /* Limit the fraction value in the interval [-2,-1,0,1,2,3] */
+
+    test (); 
+    if (sub (frac, -3) == 0)
+    {
+        frac = 3;                              move16 (); 
+        lag = sub (lag, 1);
+    }
+    *pit_frac = frac;                          move16 ();
+    
+    return (lag);
+}
+
+/*************************************************************************
+ *
+ *  FUNCTION:   Norm_Corr()
+ *
+ *  PURPOSE: Find the normalized correlation between the target vector
+ *           and the filtered past excitation.
+ *
+ *  DESCRIPTION:
+ *     The normalized correlation is given by the correlation between the
+ *     target and filtered past excitation divided by the square root of
+ *     the energy of filtered excitation.
+ *                   corr[k] = <x[], y_k[]>/sqrt(y_k[],y_k[])
+ *     where x[] is the target vector and y_k[] is the filtered past
+ *     excitation at delay k.
+ *
+ *************************************************************************/
+
+void 
+Norm_Corr (Word16 exc[], Word16 xn[], Word16 h[], Word16 L_subfr,
+           Word16 t_min, Word16 t_max, Word16 corr_norm[])
+{
+    Word16 i, j, k;
+    Word16 corr_h, corr_l, norm_h, norm_l;
+    Word32 s;
+
+    /* Usally dynamic allocation of (L_subfr) */
+    Word16 excf[80];
+    Word16 scaling, h_fac, *s_excf, scaled_excf[80];
+
+    k = -t_min;                                move16 (); 
+
+    /* compute the filtered excitation for the first delay t_min */
+
+    Convolve (&exc[k], h, excf, L_subfr);
+
+    /* scale "excf[]" to avoid overflow */
+
+    for (j = 0; j < L_subfr; j++)
+    {
+        scaled_excf[j] = shr (excf[j], 2);     move16 (); 
+    }
+
+    /* Compute 1/sqrt(energy of excf[]) */
+
+    s = 0;                                     move32 (); 
+    for (j = 0; j < L_subfr; j++)
+    {
+        s = L_mac (s, excf[j], excf[j]);
+    }
+    test (); 
+    if (L_sub (s, 67108864L) <= 0)             /* if (s <= 2^26) */
+    {
+        s_excf = excf;                         move16 (); 
+        h_fac = 15 - 12;                       move16 (); 
+        scaling = 0;                           move16 (); 
+    }
+    else
+    {
+        /* "excf[]" is divided by 2 */
+        s_excf = scaled_excf;                  move16 (); 
+        h_fac = 15 - 12 - 2;                   move16 (); 
+        scaling = 2;                           move16 (); 
+    }
+
+    /* loop for every possible period */
+
+    for (i = t_min; i <= t_max; i++)
+    {
+        /* Compute 1/sqrt(energy of excf[]) */
+
+        s = 0;                                 move32 (); 
+        for (j = 0; j < L_subfr; j++)
+        {
+            s = L_mac (s, s_excf[j], s_excf[j]);
+        }
+
+        s = Inv_sqrt (s);                      move16 (); 
+        L_Extract (s, &norm_h, &norm_l);
+
+        /* Compute correlation between xn[] and excf[] */
+
+        s = 0;                                  move32 (); 
+        for (j = 0; j < L_subfr; j++)
+        {
+            s = L_mac (s, xn[j], s_excf[j]);
+        }
+        L_Extract (s, &corr_h, &corr_l);
+
+        /* Normalize correlation = correlation * (1/sqrt(energy)) */
+
+        s = Mpy_32 (corr_h, corr_l, norm_h, norm_l);
+
+        corr_norm[i] = extract_h (L_shl (s, 16));
+                                                move16 (); 
+
+        /* modify the filtered excitation excf[] for the next iteration */
+
+        test (); 
+        if (sub (i, t_max) != 0)
+        {
+            k--;
+            for (j = L_subfr - 1; j > 0; j--)
+            {
+                s = L_mult (exc[k], h[j]);
+                s = L_shl (s, h_fac);
+                s_excf[j] = add (extract_h (s), s_excf[j - 1]); move16 (); 
+            }
+            s_excf[0] = shr (exc[k], scaling);  move16 (); 
+        }
+    }
+    return;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgsmefr/pitch_ol.c	Fri Nov 25 16:18:21 2022 +0000
@@ -0,0 +1,214 @@
+/*************************************************************************
+ *
+ *  FUNCTION:  Pitch_ol
+ *
+ *  PURPOSE: Compute the open loop pitch lag.
+ *
+ *  DESCRIPTION:
+ *      The open-loop pitch lag is determined based on the perceptually
+ *      weighted speech signal. This is done in the following steps:
+ *        - find three maxima of the correlation <sw[n],sw[n-T]> in the
+ *          follwing three ranges of T : [18,35], [36,71], and [72, 143]
+ *        - divide each maximum by <sw[n-t], sw[n-t]> where t is the delay at
+ *          that maximum correlation.
+ *        - select the delay of maximum normalized correlation (among the
+ *          three candidates) while favoring the lower delay ranges.
+ *
+ *************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "oper_32b.h"
+#include "count.h"
+#include "sig_proc.h"
+
+#define THRESHOLD 27853
+
+/* local function */
+
+static Word16 Lag_max (   /* output: lag found                              */
+    Word16 scal_sig[],    /* input : scaled signal                          */
+    Word16 scal_fac,      /* input : scaled signal factor                   */
+    Word16 L_frame,       /* input : length of frame to compute pitch       */
+    Word16 lag_max,       /* input : maximum lag                            */
+    Word16 lag_min,       /* input : minimum lag                            */
+    Word16 *cor_max);     /* output: normalized correlation of selected lag */
+
+Word16 Pitch_ol (      /* output: open loop pitch lag                        */
+    Word16 signal[],   /* input : signal used to compute the open loop pitch */
+                       /*     signal[-pit_max] to signal[-1] should be known */
+    Word16 pit_min,    /* input : minimum pitch lag                          */
+    Word16 pit_max,    /* input : maximum pitch lag                          */
+    Word16 L_frame     /* input : length of frame to compute pitch           */
+)
+{
+    Word16 i, j;
+    Word16 max1, max2, max3;
+    Word16 p_max1, p_max2, p_max3;
+    Word32 t0;
+
+    /* Scaled signal                                                */
+    /* Can be allocated with memory allocation of(pit_max+L_frame)  */
+
+    Word16 scaled_signal[512];
+    Word16 *scal_sig, scal_fac;
+
+    scal_sig = &scaled_signal[pit_max]; move16 (); 
+
+    t0 = 0L;                            move32 (); 
+    for (i = -pit_max; i < L_frame; i++)
+    {
+        t0 = L_mac (t0, signal[i], signal[i]);
+    }
+    /*--------------------------------------------------------*
+     * Scaling of input signal.                               *
+     *                                                        *
+     *   if Overflow        -> scal_sig[i] = signal[i]>>2     *
+     *   else if t0 < 1^22  -> scal_sig[i] = signal[i]<<2     *
+     *   else               -> scal_sig[i] = signal[i]        *
+     *--------------------------------------------------------*/
+
+    /*--------------------------------------------------------*
+     *  Verification for risk of overflow.                    *
+     *--------------------------------------------------------*/
+
+    test (); test (); 
+    if (L_sub (t0, MAX_32) == 0L)               /* Test for overflow */
+    {
+        for (i = -pit_max; i < L_frame; i++)
+        {
+            scal_sig[i] = shr (signal[i], 3);   move16 (); 
+        }
+        scal_fac = 3;                           move16 (); 
+    }
+    else if (L_sub (t0, (Word32) 1048576L) < (Word32) 0)
+        /* if (t0 < 2^20) */
+    {
+        for (i = -pit_max; i < L_frame; i++)
+        {
+            scal_sig[i] = shl (signal[i], 3);   move16 (); 
+        }
+        scal_fac = -3;                          move16 (); 
+    }
+    else
+    {
+        for (i = -pit_max; i < L_frame; i++)
+        {
+            scal_sig[i] = signal[i];            move16 (); 
+        }
+        scal_fac = 0;                           move16 (); 
+    }
+
+    /*--------------------------------------------------------------------*
+     *  The pitch lag search is divided in three sections.                *
+     *  Each section cannot have a pitch multiple.                        *
+     *  We find a maximum for each section.                               *
+     *  We compare the maximum of each section by favoring small lags.    *
+     *                                                                    *
+     *  First section:  lag delay = pit_max     downto 4*pit_min          *
+     *  Second section: lag delay = 4*pit_min-1 downto 2*pit_min          *
+     *  Third section:  lag delay = 2*pit_min-1 downto pit_min            *
+     *-------------------------------------------------------------------*/
+    
+    j = shl (pit_min, 2);
+    p_max1 = Lag_max (scal_sig, scal_fac, L_frame, pit_max, j, &max1);
+
+    i = sub (j, 1);
+    j = shl (pit_min, 1);
+    p_max2 = Lag_max (scal_sig, scal_fac, L_frame, i, j, &max2);
+
+    i = sub (j, 1);
+    p_max3 = Lag_max (scal_sig, scal_fac, L_frame, i, pit_min, &max3);
+
+    /*--------------------------------------------------------------------*
+     * Compare the 3 sections maximum, and favor small lag.               *
+     *-------------------------------------------------------------------*/
+    
+    test (); 
+    if (sub (mult (max1, THRESHOLD), max2) < 0)
+    {
+        max1 = max2;                       move16 (); 
+        p_max1 = p_max2;                   move16 (); 
+    }
+    test (); 
+    if (sub (mult (max1, THRESHOLD), max3) < 0)
+    {
+        p_max1 = p_max3;                   move16 (); 
+    }
+    return (p_max1);
+}
+
+/*************************************************************************
+ *
+ *  FUNCTION:  Lag_max
+ *
+ *  PURPOSE: Find the lag that has maximum correlation of scal_sig[] in a
+ *           given delay range.
+ *
+ *  DESCRIPTION:
+ *      The correlation is given by
+ *           cor[t] = <scal_sig[n],scal_sig[n-t]>,  t=lag_min,...,lag_max
+ *      The functions outputs the maximum correlation after normalization
+ *      and the corresponding lag.
+ *
+ *************************************************************************/
+
+static Word16 Lag_max ( /* output: lag found                               */
+    Word16 scal_sig[],  /* input : scaled signal.                          */
+    Word16 scal_fac,    /* input : scaled signal factor.                   */
+    Word16 L_frame,     /* input : length of frame to compute pitch        */
+    Word16 lag_max,     /* input : maximum lag                             */
+    Word16 lag_min,     /* input : minimum lag                             */
+    Word16 *cor_max)    /* output: normalized correlation of selected lag  */
+{
+    Word16 i, j;
+    Word16 *p, *p1;
+    Word32 max, t0;
+    Word16 max_h, max_l, ener_h, ener_l;
+    Word16 p_max;
+
+    max = MIN_32;               move32 (); 
+
+    for (i = lag_max; i >= lag_min; i--)
+    {
+        p = scal_sig;           move16 (); 
+        p1 = &scal_sig[-i];     move16 (); 
+        t0 = 0;                 move32 (); 
+
+        for (j = 0; j < L_frame; j++, p++, p1++)
+        {
+            t0 = L_mac (t0, *p, *p1);
+        }
+        test (); 
+        if (L_sub (t0, max) >= 0)
+        {
+            max = t0;           move32 (); 
+            p_max = i;          move16 (); 
+        }
+    }
+
+    /* compute energy */
+
+    t0 = 0;                     move32 (); 
+    p = &scal_sig[-p_max];      move16 (); 
+    for (i = 0; i < L_frame; i++, p++)
+    {
+        t0 = L_mac (t0, *p, *p);
+    }
+    /* 1/sqrt(energy) */
+
+    t0 = Inv_sqrt (t0);
+    t0 = L_shl (t0, 1);
+
+    /* max = max/sqrt(energy)  */
+
+    L_Extract (max, &max_h, &max_l);
+    L_Extract (t0, &ener_h, &ener_l);
+
+    t0 = Mpy_32 (max_h, max_l, ener_h, ener_l);
+    t0 = L_shr (t0, scal_fac);
+
+    *cor_max = extract_h (L_shl (t0, 15));      move16 (); /* divide by 2 */
+
+    return (p_max);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgsmefr/pow2.c	Fri Nov 25 16:18:21 2022 +0000
@@ -0,0 +1,45 @@
+/*************************************************************************
+ *
+ *   FUNCTION:  Pow2()
+ *
+ *   PURPOSE: computes  L_x = pow(2.0, exponent.fraction)
+ *
+ *   DESCRIPTION:
+ *       The function Pow2(L_x) is approximated by a table and linear
+ *       interpolation.
+ *          1- i = bit10-b15 of fraction,   0 <= i <= 31
+ *          2- a = bit0-b9   of fraction   
+ *          3- L_x = table[i]<<16 - (table[i] - table[i+1]) * a * 2
+ *          4- L_x = L_x >> (30-exponent)     (with rounding)
+ *
+ *************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "count.h"
+
+#include "pow2.tab"     /* Table for Pow2() */
+
+Word32 Pow2 (           /* (o)  : result       (range: 0<=val<=0x7fffffff) */
+    Word16 exponent,    /* (i)  : Integer part.      (range: 0<=val<=30)   */
+    Word16 fraction     /* (i)  : Fractional part.  (range: 0.0<=val<1.0) */
+)
+{
+    Word16 exp, i, a, tmp;
+    Word32 L_x;
+
+    L_x = L_mult (fraction, 32);/* L_x = fraction<<6           */
+    i = extract_h (L_x);        /* Extract b10-b16 of fraction */
+    L_x = L_shr (L_x, 1);
+    a = extract_l (L_x);        /* Extract b0-b9   of fraction */
+    a = a & (Word16) 0x7fff;    logic16 (); 
+
+    L_x = L_deposit_h (table[i]);       /* table[i] << 16        */
+    tmp = sub (table[i], table[i + 1]); /* table[i] - table[i+1] */
+    L_x = L_msu (L_x, tmp, a);  /* L_x -= tmp*a*2        */
+
+    exp = sub (30, exponent);
+    L_x = L_shr_r (L_x, exp);
+
+    return (L_x);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgsmefr/pre_proc.c	Fri Nov 25 16:18:21 2022 +0000
@@ -0,0 +1,80 @@
+/*************************************************************************
+ *
+ *  FUNCTION:  Pre_Process()
+ *
+ *  PURPOSE: Preprocessing of input speech.
+ *
+ *  DESCRIPTION:
+ *     - 2nd order high pass filtering with cut off frequency at 80 Hz.
+ *     - Divide input by two.
+ *
+ *************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "oper_32b.h"
+#include "count.h"
+
+/*------------------------------------------------------------------------*
+ *                                                                        *
+ * Algorithm:                                                             *
+ *                                                                        *
+ *  y[i] = b[0]*x[i]/2 + b[1]*x[i-1]/2 + b[2]*x[i-2]/2                    *
+ *                     + a[1]*y[i-1]   + a[2]*y[i-2];                     *
+ *                                                                        *
+ *                                                                        *
+ *  Input is divided by two in the filtering process.                     *
+ *------------------------------------------------------------------------*/
+
+/* filter coefficients (fc = 80 Hz, coeff. b[] is divided by 2) */
+
+static const Word16 b[3] = {1899, -3798, 1899};
+static const Word16 a[3] = {4096, 7807, -3733};
+
+/* Static values to be preserved between calls */
+/* y[] values are kept in double precision     */
+
+static Word16 y2_hi, y2_lo, y1_hi, y1_lo, x0, x1;
+
+/* Initialization of static values */
+
+void Init_Pre_Process (void)
+{
+    y2_hi = 0;
+    y2_lo = 0;
+    y1_hi = 0;
+    y1_lo = 0;
+    x0 = 0;
+    x1 = 0;
+}
+
+void Pre_Process (
+    Word16 signal[], /* input/output signal */
+    Word16 lg)       /* lenght of signal    */
+{
+    Word16 i, x2;
+    Word32 L_tmp;
+
+    for (i = 0; i < lg; i++)
+    {
+        x2 = x1;                   move16 (); 
+        x1 = x0;                   move16 (); 
+        x0 = signal[i];            move16 (); 
+
+        /*  y[i] = b[0]*x[i]/2 + b[1]*x[i-1]/2 + b140[2]*x[i-2]/2  */
+        /*                     + a[1]*y[i-1] + a[2] * y[i-2];      */
+
+        L_tmp = Mpy_32_16 (y1_hi, y1_lo, a[1]);
+        L_tmp = L_add (L_tmp, Mpy_32_16 (y2_hi, y2_lo, a[2]));
+        L_tmp = L_mac (L_tmp, x0, b[0]);
+        L_tmp = L_mac (L_tmp, x1, b[1]);
+        L_tmp = L_mac (L_tmp, x2, b[2]);
+        L_tmp = L_shl (L_tmp, 3);
+        signal[i] = round (L_tmp); move16 (); 
+
+        y2_hi = y1_hi;             move16 (); 
+        y2_lo = y1_lo;             move16 (); 
+        L_Extract (L_tmp, &y1_hi, &y1_lo);
+    }
+    return;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgsmefr/pred_lt6.c	Fri Nov 25 16:18:21 2022 +0000
@@ -0,0 +1,80 @@
+/*************************************************************************
+ *
+ *  FUNCTION:   Pred_lt_6()
+ *
+ *  PURPOSE:  Compute the result of long term prediction with fractional
+ *            interpolation of resolution 1/6. (Interpolated past excitation).
+ *
+ *  DESCRIPTION:
+ *       The past excitation signal at the given delay is interpolated at
+ *       the given fraction to build the adaptive codebook excitation.
+ *       On return exc[0..L_subfr-1] contains the interpolated signal
+ *       (adaptive codebook excitation).
+ *
+ *************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "count.h"
+
+#define UP_SAMP      6
+#define L_INTERPOL   10
+#define FIR_SIZE     (UP_SAMP*L_INTERPOL+1)
+
+/* 1/6 resolution interpolation filter  (-3 dB at 3600 Hz) */
+
+static const Word16 inter_6[FIR_SIZE] =
+{
+    29443,
+    28346, 25207, 20449, 14701, 8693, 3143,
+    -1352, -4402, -5865, -5850, -4673, -2783,
+    -672, 1211, 2536, 3130, 2991, 2259,
+    1170, 0, -1001, -1652, -1868, -1666,
+    -1147, -464, 218, 756, 1060, 1099,
+    904, 550, 135, -245, -514, -634,
+    -602, -451, -231, 0, 191, 308,
+    340, 296, 198, 78, -36, -120,
+    -163, -165, -132, -79, -19, 34,
+    73, 91, 89, 70, 38, 0
+};
+
+void Pred_lt_6 (
+    Word16 exc[],     /* in/out: excitation buffer */
+    Word16 T0,        /* input : integer pitch lag */
+    Word16 frac,      /* input : fraction of lag   */
+    Word16 L_subfr    /* input : subframe size     */
+)
+{
+    Word16 i, j, k;
+    Word16 *x0, *x1, *x2;
+    const Word16 *c1, *c2;
+    Word32 s;
+
+    x0 = &exc[-T0];             move16 (); 
+
+    frac = negate (frac);
+    test (); 
+    if (frac < 0)
+    {
+        frac = add (frac, UP_SAMP);
+        x0--;
+    }
+    for (j = 0; j < L_subfr; j++)
+    {
+        x1 = x0++;              move16 (); 
+        x2 = x0;                move16 (); 
+        c1 = &inter_6[frac];
+        c2 = &inter_6[sub (UP_SAMP, frac)];
+
+        s = 0;                  move32 (); 
+        for (i = 0, k = 0; i < L_INTERPOL; i++, k += UP_SAMP)
+        {
+            s = L_mac (s, x1[-i], c1[k]);
+            s = L_mac (s, x2[i], c2[k]);
+        }
+
+        exc[j] = round (s);     move16 (); 
+    }
+
+    return;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgsmefr/preemph.c	Fri Nov 25 16:18:21 2022 +0000
@@ -0,0 +1,36 @@
+/*---------------------------------------------------------------------*
+ * routine preemphasis()                                               *
+ * ~~~~~~~~~~~~~~~~~~~~~                                               *
+ * Preemphasis: filtering through 1 - g z^-1                           *
+ *---------------------------------------------------------------------*/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "count.h"
+
+Word16 mem_pre;
+
+void preemphasis (
+    Word16 *signal, /* (i/o)   : input signal overwritten by the output */
+    Word16 g,       /* (i)     : preemphasis coefficient                */
+    Word16 L        /* (i)     : size of filtering                      */
+)
+{
+    Word16 *p1, *p2, temp, i;
+
+    p1 = signal + L - 1;                    move16 (); 
+    p2 = p1 - 1;                            move16 (); 
+    temp = *p1;                             move16 (); 
+
+    for (i = 0; i <= L - 2; i++)
+    {
+        *p1 = sub (*p1, mult (g, *p2--));   move16 (); 
+        p1--;
+    }
+
+    *p1 = sub (*p1, mult (g, mem_pre));     move16 (); 
+
+    mem_pre = temp;                         move16 (); 
+
+    return;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgsmefr/pstfilt2.c	Fri Nov 25 16:18:21 2022 +0000
@@ -0,0 +1,182 @@
+/*************************************************************************
+ *
+ *  FILE NAME:   pstfilt2.c
+ *
+ * Performs adaptive postfiltering on the synthesis speech
+ *
+ *  FUNCTIONS INCLUDED:  Init_Post_Filter()  and Post_Filter()
+ *
+ *************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "sig_proc.h"
+#include "count.h"
+#include "codec.h"
+#include "cnst.h"
+
+/*---------------------------------------------------------------*
+ *    Postfilter constant parameters (defined in "cnst.h")       *
+ *---------------------------------------------------------------*
+ *   L_FRAME     : Frame size.                                   *
+ *   L_SUBFR     : Sub-frame size.                               *
+ *   M           : LPC order.                                    *
+ *   MP1         : LPC order+1                                   *
+ *   MU          : Factor for tilt compensation filter           *
+ *   AGC_FAC     : Factor for automatic gain control             *
+ *---------------------------------------------------------------*/
+
+#define L_H 22  /* size of truncated impulse response of A(z/g1)/A(z/g2) */
+
+/*------------------------------------------------------------*
+ *   static vectors                                           *
+ *------------------------------------------------------------*/
+
+ /* inverse filtered synthesis */
+
+static Word16 res2[L_SUBFR];
+
+ /* memory of filter 1/A(z/0.75) */
+
+static Word16 mem_syn_pst[M];
+
+ /* Spectral expansion factors */
+
+const Word16 F_gamma3[M] =
+{
+    22938, 16057, 11240, 7868, 5508,
+    3856, 2699, 1889, 1322, 925
+};
+const Word16 F_gamma4[M] =
+{
+    24576, 18432, 13824, 10368, 7776,
+    5832, 4374, 3281, 2461, 1846
+};
+
+/*************************************************************************
+ *
+ *  FUNCTION:   Init_Post_Filter
+ *
+ *  PURPOSE: Initializes the postfilter parameters.
+ *
+ *************************************************************************/
+
+void Init_Post_Filter (void)
+{
+    Set_zero (mem_syn_pst, M);
+
+    Set_zero (res2, L_SUBFR);
+
+    return;
+}
+
+/*************************************************************************
+ *  FUNCTION:  Post_Filter()
+ *
+ *  PURPOSE:  postfiltering of synthesis speech.
+ *
+ *  DESCRIPTION:
+ *      The postfiltering process is described as follows:
+ *
+ *          - inverse filtering of syn[] through A(z/0.7) to get res2[]
+ *          - tilt compensation filtering; 1 - MU*k*z^-1
+ *          - synthesis filtering through 1/A(z/0.75)
+ *          - adaptive gain control
+ *
+ *************************************************************************/
+
+void Post_Filter (
+    Word16 *syn,    /* in/out: synthesis speech (postfiltered is output)    */
+    Word16 *Az_4    /* input: interpolated LPC parameters in all subframes  */
+)
+{
+    /*-------------------------------------------------------------------*
+     *           Declaration of parameters                               *
+     *-------------------------------------------------------------------*/
+
+    Word16 syn_pst[L_FRAME];    /* post filtered synthesis speech   */
+    Word16 Ap3[MP1], Ap4[MP1];  /* bandwidth expanded LP parameters */
+    Word16 *Az;                 /* pointer to Az_4:                 */
+                                /*  LPC parameters in each subframe */
+    Word16 i_subfr;             /* index for beginning of subframe  */
+    Word16 h[L_H];
+
+    Word16 i;
+    Word16 temp1, temp2;
+    Word32 L_tmp;
+
+    /*-----------------------------------------------------*
+     * Post filtering                                      *
+     *-----------------------------------------------------*/
+
+    Az = Az_4;
+
+    for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)
+    {
+        /* Find weighted filter coefficients Ap3[] and ap[4] */
+
+        Weight_Ai (Az, F_gamma3, Ap3);
+        Weight_Ai (Az, F_gamma4, Ap4);
+
+        /* filtering of synthesis speech by A(z/0.7) to find res2[] */
+
+        Residu (Ap3, &syn[i_subfr], res2, L_SUBFR);
+
+        /* tilt compensation filter */
+
+        /* impulse response of A(z/0.7)/A(z/0.75) */
+
+        Copy (Ap3, h, M + 1);
+        Set_zero (&h[M + 1], L_H - M - 1);
+        Syn_filt (Ap4, h, h, L_H, &h[M + 1], 0);
+
+        /* 1st correlation of h[] */
+
+        L_tmp = L_mult (h[0], h[0]);
+        for (i = 1; i < L_H; i++)
+        {
+            L_tmp = L_mac (L_tmp, h[i], h[i]);
+        }
+        temp1 = extract_h (L_tmp);
+
+        L_tmp = L_mult (h[0], h[1]);
+        for (i = 1; i < L_H - 1; i++)
+        {
+            L_tmp = L_mac (L_tmp, h[i], h[i + 1]);
+        }
+        temp2 = extract_h (L_tmp);
+
+        test (); 
+        if (temp2 <= 0)
+        {
+            temp2 = 0;          move16 (); 
+        }
+        else
+        {
+            temp2 = mult (temp2, MU);
+            temp2 = div_s (temp2, temp1);
+        }
+
+        preemphasis (res2, temp2, L_SUBFR);
+
+        /* filtering through  1/A(z/0.75) */
+
+        Syn_filt (Ap4, res2, &syn_pst[i_subfr], L_SUBFR, mem_syn_pst, 1);
+
+        /* scale output to input */
+
+        agc (&syn[i_subfr], &syn_pst[i_subfr], AGC_FAC, L_SUBFR);
+
+        Az += MP1;
+    }
+
+    /* update syn[] buffer */
+
+    Copy (&syn[L_FRAME - M], &syn[-M], M);
+
+    /* overwrite synthesis speech by postfiltered synthesis speech */
+
+    Copy (syn_pst, syn, L_FRAME);
+
+    return;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgsmefr/q_gains.c	Fri Nov 25 16:18:21 2022 +0000
@@ -0,0 +1,218 @@
+/*--------------------------------------------------------------------------*
+ * Function q_gain_pitch(), q_gain_code()                                  *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                                  *
+ * Scalar quantization of the pitch gain and the innovative codebook gain.  *
+ *                                                                          *
+ * MA prediction is performed on the innovation energy                      *
+ * (in dB/(20*log10(2))) with mean removed.                                 *
+ *-------------------------------------------------------------------------*/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "oper_32b.h"
+#include "count.h"
+#include "sig_proc.h"
+
+#include "gains_tb.h"
+
+#include "cnst.h"
+#include "dtx.h"
+
+/* past quantized energies.                               */
+/* initialized to -14.0/constant, constant = 20*Log10(2)   */
+Word16 past_qua_en[4];
+
+/* MA prediction coeff */
+Word16 pred[4];
+
+extern Word16 CN_excitation_gain, gain_code_old_tx[4 * DTX_HANGOVER];
+
+Word16 q_gain_pitch (   /* Return index of quantization */
+    Word16 *gain        /* (i)  :  Pitch gain to quantize  */
+)
+{
+    Word16 i, index, gain_q14, err, err_min;
+
+    gain_q14 = shl (*gain, 2);
+
+    err_min = abs_s (sub (gain_q14, qua_gain_pitch[0]));
+    index = 0;                                  move16 (); 
+
+    for (i = 1; i < NB_QUA_PITCH; i++)
+    {
+        err = abs_s (sub (gain_q14, qua_gain_pitch[i]));
+
+        test (); 
+        if (sub (err, err_min) < 0)
+        {
+            err_min = err;                      move16 (); 
+            index = i;                          move16 (); 
+        }
+    }
+
+    *gain = shr (qua_gain_pitch[index], 2);     move16 (); 
+
+    return index;
+}
+
+/* average innovation energy.                             */
+/* MEAN_ENER  = 36.0/constant, constant = 20*Log10(2)     */
+
+#define MEAN_ENER  783741L      /* 36/(20*log10(2))       */
+
+Word16 q_gain_code (    /* Return quantization index                  */
+    Word16 code[],      /* (i)      : fixed codebook excitation       */
+    Word16 lcode,       /* (i)      : codevector size                 */
+    Word16 *gain,       /* (i/o)    : quantized fixed codebook gain   */
+    Word16 txdtx_ctrl,
+    Word16 i_subfr
+)
+{
+    Word16 i, index;
+    Word16 gcode0, err, err_min, exp, frac;
+    Word32 ener, ener_code;
+    Word16 aver_gain;
+    static Word16 gcode0_CN;
+
+    logic16 (); test (); 
+    if ((txdtx_ctrl & TX_SP_FLAG) != 0)
+    {
+
+        /*-------------------------------------------------------------------*
+         *  energy of code:                                                   *
+         *  ~~~~~~~~~~~~~~~                                                   *
+         *  ener_code(Q17) = 10 * Log10(energy/lcode) / constant              *
+         *                 = 1/2 * Log2(energy/lcode)                         *
+         *                                           constant = 20*Log10(2)   *
+         *-------------------------------------------------------------------*/
+
+        /* ener_code = log10(ener_code/lcode) / (20*log10(2))       */
+        ener_code = 0;                          move32 (); 
+        for (i = 0; i < lcode; i++)
+        {
+            ener_code = L_mac (ener_code, code[i], code[i]);
+        }
+        /* ener_code = ener_code / lcode */
+        ener_code = L_mult (round (ener_code), 26214);
+
+        /* ener_code = 1/2 * Log2(ener_code) */
+        Log2 (ener_code, &exp, &frac);
+        ener_code = L_Comp (sub (exp, 30), frac);
+
+        /* predicted energy */
+
+        ener = MEAN_ENER;                       move32 (); 
+        for (i = 0; i < 4; i++)
+        {
+            ener = L_mac (ener, past_qua_en[i], pred[i]);
+        }
+
+        /*-------------------------------------------------------------------*
+         *  predicted codebook gain                                           *
+         *  ~~~~~~~~~~~~~~~~~~~~~~~                                           *
+         *  gcode0(Qx) = Pow10( (ener*constant - ener_code*constant) / 20 )   *
+         *             = Pow2(ener-ener_code)                                 *
+         *                                           constant = 20*Log10(2)   *
+         *-------------------------------------------------------------------*/
+
+        ener = L_shr (L_sub (ener, ener_code), 1);
+        L_Extract (ener, &exp, &frac);
+
+        gcode0 = extract_l (Pow2 (exp, frac));  /* predicted gain */
+
+        gcode0 = shl (gcode0, 4);
+
+        /*-------------------------------------------------------------------*
+         *                   Search for best quantizer                        *
+         *-------------------------------------------------------------------*/
+
+        err_min = abs_s (sub (*gain, mult (gcode0, qua_gain_code[0])));
+        index = 0;              move16 (); 
+
+        for (i = 1; i < NB_QUA_CODE; i++)
+        {
+            err = abs_s (sub (*gain, mult (gcode0, qua_gain_code[i])));
+
+            test (); 
+            if (sub (err, err_min) < 0)
+            {
+                err_min = err;                  move16 (); 
+                index = i;                      move16 (); 
+            }
+        }
+
+        *gain = mult (gcode0, qua_gain_code[index]);
+                                                move16 (); 
+
+        /*------------------------------------------------------------------*
+         *  update table of past quantized energies                         *
+         *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                         *
+         *  past_qua_en(Q12) = 20 * Log10(qua_gain_code) / constant         *
+         *                   = Log2(qua_gain_code)                          *
+         *                                           constant = 20*Log10(2) *
+         *------------------------------------------------------------------*/
+
+        for (i = 3; i > 0; i--)
+        {
+            past_qua_en[i] = past_qua_en[i - 1];move16 (); 
+        }
+        Log2 (L_deposit_l (qua_gain_code[index]), &exp, &frac);
+
+        past_qua_en[0] = shr (frac, 5);         move16 (); 
+        past_qua_en[0] = add (past_qua_en[0], shl (sub (exp, 11), 10));
+                                                move16 (); 
+
+        update_gain_code_history_tx (*gain, gain_code_old_tx);
+    }
+    else
+    {
+        logic16 (); test (); test (); 
+        if ((txdtx_ctrl & TX_PREV_HANGOVER_ACTIVE) != 0 && (i_subfr == 0))
+        {
+            gcode0_CN = update_gcode0_CN (gain_code_old_tx);
+            gcode0_CN = shl (gcode0_CN, 4);
+        }
+        *gain = CN_excitation_gain;             move16 (); 
+
+        logic16 (); test (); test (); 
+        if ((txdtx_ctrl & TX_SID_UPDATE) != 0)
+        {
+            aver_gain = aver_gain_code_history (CN_excitation_gain,
+                                                gain_code_old_tx);
+
+            /*---------------------------------------------------------------*
+             *                   Search for best quantizer                    *
+             *---------------------------------------------------------------*/
+
+            err_min = abs_s (sub (aver_gain, 
+                                  mult (gcode0_CN, qua_gain_code[0])));
+            index = 0;                          move16 (); 
+
+            for (i = 1; i < NB_QUA_CODE; i++)
+            {
+                err = abs_s (sub (aver_gain, 
+                                  mult (gcode0_CN, qua_gain_code[i])));
+
+                test (); 
+                if (sub (err, err_min) < 0)
+                {
+                    err_min = err;              move16 (); 
+                    index = i;                  move16 (); 
+                }
+            }
+        }
+        update_gain_code_history_tx (*gain, gain_code_old_tx);
+
+        /*-------------------------------------------------------------------*
+         *  reset table of past quantized energies                            *
+         *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                            *
+         *-------------------------------------------------------------------*/
+
+        for (i = 0; i < 4; i++)
+        {
+            past_qua_en[i] = -2381;             move16 (); 
+        }
+    }
+
+    return index;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgsmefr/q_plsf_5.c	Fri Nov 25 16:18:21 2022 +0000
@@ -0,0 +1,448 @@
+/*************************************************************************
+ *   FUNCTION:  Q_plsf_5()
+ *
+ *   PURPOSE:  Quantization of 2 sets of LSF parameters using 1st order MA
+ *             prediction and split by 5 matrix quantization (split-MQ)
+ *
+ *   DESCRIPTION:
+ *
+ *        p[i] = pred_factor*past_r2q[i];   i=0,...,m-1
+ *        r1[i]= lsf1[i] - p[i];      i=0,...,m-1
+ *        r2[i]= lsf2[i] - p[i];      i=0,...,m-1
+ *   where:
+ *        lsf1[i]           1st mean-removed LSF vector.
+ *        lsf2[i]           2nd mean-removed LSF vector.
+ *        r1[i]             1st residual prediction vector.
+ *        r2[i]             2nd residual prediction vector.
+ *        past_r2q[i]       Past quantized residual (2nd vector).
+ *
+ *   The residual vectors r1[i] and r2[i] are jointly quantized using
+ *   split-MQ with 5 codebooks. Each 4th dimension submatrix contains 2
+ *   elements from each residual vector. The 5 submatrices are as follows:
+ *     {r1[0], r1[1], r2[0], r2[1]};  {r1[2], r1[3], r2[2], r2[3]};
+ *     {r1[4], r1[5], r2[4], r2[5]};  {r1[6], r1[7], r2[6], r2[7]};
+ *                    {r1[8], r1[9], r2[8], r2[9]};
+ *
+ *************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "count.h"
+#include "sig_proc.h"
+
+#include "cnst.h"
+#include "dtx.h"
+
+/* Locals functions */
+
+void Lsf_wt (
+    Word16 *lsf,       /* input : LSF vector                    */
+     Word16 *wf2       /* output: square of weighting factors   */
+);
+
+Word16 Vq_subvec (     /* output: return quantization index     */
+    Word16 *lsf_r1,    /* input : 1st LSF residual vector       */
+    Word16 *lsf_r2,    /* input : and LSF residual vector       */
+    const Word16 *dico,/* input : quantization codebook         */
+    Word16 *wf1,       /* input : 1st LSF weighting factors     */
+    Word16 *wf2,       /* input : 2nd LSF weighting factors     */
+    Word16 dico_size   /* input : size of quantization codebook */
+);
+Word16 Vq_subvec_s (   /* output: return quantization index     */
+    Word16 *lsf_r1,    /* input : 1st LSF residual vector       */
+    Word16 *lsf_r2,    /* input : and LSF residual vector       */
+    const Word16 *dico,/* input : quantization codebook         */
+    Word16 *wf1,       /* input : 1st LSF weighting factors     */
+    Word16 *wf2,       /* input : 2nd LSF weighting factors     */
+    Word16 dico_size   /* input : size of quantization codebook */
+);
+/* M  ->order of linear prediction filter                      */
+/* LSF_GAP  -> Minimum distance between LSF after quantization */
+/*             50 Hz = 205                                     */
+/* PRED_FAC -> Predcition factor                               */
+
+#define M         10
+#define LSF_GAP   205
+#define PRED_FAC  21299
+
+#include "q_plsf_5.tab"         /* Codebooks of LSF prediction residual */
+
+ /* Past quantized prediction error */
+
+Word16 past_r2_q[M];
+
+extern Word16 lsf_old_tx[DTX_HANGOVER][M];
+
+void Q_plsf_5 (
+    Word16 *lsp1,      /* input : 1st LSP vector                     */
+    Word16 *lsp2,      /* input : 2nd LSP vector                     */
+    Word16 *lsp1_q,    /* output: quantized 1st LSP vector           */
+    Word16 *lsp2_q,    /* output: quantized 2nd LSP vector           */
+    Word16 *indice,    /* output: quantization indices of 5 matrices */
+    Word16 txdtx_ctrl  /* input : tx dtx control word                */
+)
+{
+    Word16 i;
+    Word16 lsf1[M], lsf2[M], wf1[M], wf2[M], lsf_p[M], lsf_r1[M], lsf_r2[M];
+    Word16 lsf1_q[M], lsf2_q[M];
+    Word16 lsf_aver[M];
+    static Word16 lsf_p_CN[M];
+
+    /* convert LSFs to normalize frequency domain 0..16384  */
+
+    Lsp_lsf (lsp1, lsf1, M);
+    Lsp_lsf (lsp2, lsf2, M);
+
+    /* Update LSF CN quantizer "memory" */
+
+    logic16 (); logic16 (); test (); test (); 
+    if ((txdtx_ctrl & TX_SP_FLAG) == 0
+        && (txdtx_ctrl & TX_PREV_HANGOVER_ACTIVE) != 0)
+    {
+        update_lsf_p_CN (lsf_old_tx, lsf_p_CN);
+    }
+    logic16 (); test (); 
+    if ((txdtx_ctrl & TX_SID_UPDATE) != 0)
+    {
+        /* New SID frame is to be sent:
+        Compute average of the current LSFs and the LSFs in the history */
+
+        aver_lsf_history (lsf_old_tx, lsf1, lsf2, lsf_aver);
+    }
+    /* Update LSF history with unquantized LSFs when no speech activity
+    is present */
+
+    logic16 (); test (); 
+    if ((txdtx_ctrl & TX_SP_FLAG) == 0)
+    {
+        update_lsf_history (lsf1, lsf2, lsf_old_tx);
+    }
+    logic16 (); test (); 
+    if ((txdtx_ctrl & TX_SID_UPDATE) != 0)
+    {
+        /* Compute LSF weighting factors for lsf2, using averaged LSFs */
+        /* Set LSF weighting factors for lsf1 to zero */
+        /* Replace lsf1 and lsf2 by the averaged LSFs */
+
+        Lsf_wt (lsf_aver, wf2);
+        for (i = 0; i < M; i++)
+        {
+            wf1[i] = 0;                                 move16 (); 
+            lsf1[i] = lsf_aver[i];                      move16 (); 
+            lsf2[i] = lsf_aver[i];                      move16 (); 
+        }
+    }
+    else
+    {
+        /* Compute LSF weighting factors */
+
+        Lsf_wt (lsf1, wf1);
+        Lsf_wt (lsf2, wf2);
+    }
+
+    /* Compute predicted LSF and prediction error */
+
+    logic16 (); test (); 
+    if ((txdtx_ctrl & TX_SP_FLAG) != 0)
+    {
+        for (i = 0; i < M; i++)
+        {
+            lsf_p[i] = add (mean_lsf[i], mult (past_r2_q[i], PRED_FAC));
+                                                        move16 (); 
+            lsf_r1[i] = sub (lsf1[i], lsf_p[i]);        move16 (); 
+            lsf_r2[i] = sub (lsf2[i], lsf_p[i]);        move16 (); 
+        }
+    }
+    else
+    {
+        for (i = 0; i < M; i++)
+        {
+            lsf_r1[i] = sub (lsf1[i], lsf_p_CN[i]);     move16 (); 
+            lsf_r2[i] = sub (lsf2[i], lsf_p_CN[i]);     move16 (); 
+        }
+    }
+
+    /*---- Split-VQ of prediction error ----*/
+
+    indice[0] = Vq_subvec (&lsf_r1[0], &lsf_r2[0], dico1_lsf,
+                           &wf1[0], &wf2[0], DICO1_SIZE);
+                                                        move16 (); 
+
+    indice[1] = Vq_subvec (&lsf_r1[2], &lsf_r2[2], dico2_lsf,
+                           &wf1[2], &wf2[2], DICO2_SIZE);
+                                                        move16 (); 
+
+    indice[2] = Vq_subvec_s (&lsf_r1[4], &lsf_r2[4], dico3_lsf,
+                             &wf1[4], &wf2[4], DICO3_SIZE);
+                                                        move16 (); 
+
+    indice[3] = Vq_subvec (&lsf_r1[6], &lsf_r2[6], dico4_lsf,
+                           &wf1[6], &wf2[6], DICO4_SIZE);
+                                                        move16 (); 
+
+    indice[4] = Vq_subvec (&lsf_r1[8], &lsf_r2[8], dico5_lsf,
+                           &wf1[8], &wf2[8], DICO5_SIZE);
+                                                        move16 (); 
+
+    /* Compute quantized LSFs and update the past quantized residual */
+    /* In case of no speech activity, skip computing the quantized LSFs,
+       and set past_r2_q to zero (initial value) */
+
+    logic16 (); test (); 
+    if ((txdtx_ctrl & TX_SP_FLAG) != 0)
+    {
+        for (i = 0; i < M; i++)
+        {
+            lsf1_q[i] = add (lsf_r1[i], lsf_p[i]);      move16 (); 
+            lsf2_q[i] = add (lsf_r2[i], lsf_p[i]);      move16 (); 
+            past_r2_q[i] = lsf_r2[i];                   move16 (); 
+        }
+
+        /* verification that LSFs has minimum distance of LSF_GAP */
+
+        Reorder_lsf (lsf1_q, LSF_GAP, M);
+        Reorder_lsf (lsf2_q, LSF_GAP, M);
+
+        /* Update LSF history with quantized LSFs
+        when hangover period is active */
+
+        logic16 (); test (); 
+        if ((txdtx_ctrl & TX_HANGOVER_ACTIVE) != 0)
+        {
+            update_lsf_history (lsf1_q, lsf2_q, lsf_old_tx);
+        }
+        /*  convert LSFs to the cosine domain */
+
+        Lsf_lsp (lsf1_q, lsp1_q, M);
+        Lsf_lsp (lsf2_q, lsp2_q, M);
+    }
+    else
+    {
+        for (i = 0; i < M; i++)
+        {
+            past_r2_q[i] = 0;                           move16 (); 
+        }
+    }
+
+    return;
+}
+
+/* Quantization of a 4 dimensional subvector */
+
+Word16 Vq_subvec (      /* output: return quantization index     */
+    Word16 *lsf_r1,     /* input : 1st LSF residual vector       */
+    Word16 *lsf_r2,     /* input : and LSF residual vector       */
+    const Word16 *dico, /* input : quantization codebook         */
+    Word16 *wf1,        /* input : 1st LSF weighting factors     */
+    Word16 *wf2,        /* input : 2nd LSF weighting factors     */
+    Word16 dico_size    /* input : size of quantization codebook */
+)
+{
+    Word16 i, index, temp;
+    const Word16 *p_dico;
+    Word32 dist_min, dist;
+
+    dist_min = MAX_32;                                  move32 (); 
+    p_dico = dico;                                      move16 (); 
+
+    for (i = 0; i < dico_size; i++)
+    {
+        temp = sub (lsf_r1[0], *p_dico++);
+        temp = mult (wf1[0], temp);
+        dist = L_mult (temp, temp);
+
+        temp = sub (lsf_r1[1], *p_dico++);
+        temp = mult (wf1[1], temp);
+        dist = L_mac (dist, temp, temp);
+
+        temp = sub (lsf_r2[0], *p_dico++);
+        temp = mult (wf2[0], temp);
+        dist = L_mac (dist, temp, temp);
+
+        temp = sub (lsf_r2[1], *p_dico++);
+        temp = mult (wf2[1], temp);
+        dist = L_mac (dist, temp, temp);
+
+        test (); 
+        if (L_sub (dist, dist_min) < (Word32) 0)
+        {
+            dist_min = dist;                            move32 (); 
+            index = i;                                  move16 (); 
+        }
+    }
+
+    /* Reading the selected vector */
+
+    p_dico = &dico[shl (index, 2)];                     move16 (); 
+    lsf_r1[0] = *p_dico++;                              move16 (); 
+    lsf_r1[1] = *p_dico++;                              move16 (); 
+    lsf_r2[0] = *p_dico++;                              move16 (); 
+    lsf_r2[1] = *p_dico++;                              move16 (); 
+
+    return index;
+
+}
+
+/* Quantization of a 4 dimensional subvector with a signed codebook */
+
+Word16 Vq_subvec_s (    /* output: return quantization index     */
+    Word16 *lsf_r1,     /* input : 1st LSF residual vector       */
+    Word16 *lsf_r2,     /* input : and LSF residual vector       */
+    const Word16 *dico, /* input : quantization codebook         */
+    Word16 *wf1,        /* input : 1st LSF weighting factors     */
+    Word16 *wf2,        /* input : 2nd LSF weighting factors     */
+    Word16 dico_size)   /* input : size of quantization codebook */
+{
+    Word16 i, index, sign, temp;
+    const Word16 *p_dico;
+    Word32 dist_min, dist;
+
+    dist_min = MAX_32;                                  move32 (); 
+    p_dico = dico;                                      move16 (); 
+
+    for (i = 0; i < dico_size; i++)
+    {
+        /* test positive */
+
+        temp = sub (lsf_r1[0], *p_dico++);
+        temp = mult (wf1[0], temp);
+        dist = L_mult (temp, temp);
+
+        temp = sub (lsf_r1[1], *p_dico++);
+        temp = mult (wf1[1], temp);
+        dist = L_mac (dist, temp, temp);
+
+        temp = sub (lsf_r2[0], *p_dico++);
+        temp = mult (wf2[0], temp);
+        dist = L_mac (dist, temp, temp);
+
+        temp = sub (lsf_r2[1], *p_dico++);
+        temp = mult (wf2[1], temp);
+        dist = L_mac (dist, temp, temp);
+
+        test (); 
+        if (L_sub (dist, dist_min) < (Word32) 0)
+        {
+            dist_min = dist;                            move32 (); 
+            index = i;                                  move16 (); 
+            sign = 0;                                   move16 (); 
+        }
+        /* test negative */
+
+        p_dico -= 4;                                    move16 (); 
+        temp = add (lsf_r1[0], *p_dico++);
+        temp = mult (wf1[0], temp);
+        dist = L_mult (temp, temp);
+
+        temp = add (lsf_r1[1], *p_dico++);
+        temp = mult (wf1[1], temp);
+        dist = L_mac (dist, temp, temp);
+
+        temp = add (lsf_r2[0], *p_dico++);
+        temp = mult (wf2[0], temp);
+        dist = L_mac (dist, temp, temp);
+
+        temp = add (lsf_r2[1], *p_dico++);
+        temp = mult (wf2[1], temp);
+        dist = L_mac (dist, temp, temp);
+
+        test (); 
+        if (L_sub (dist, dist_min) < (Word32) 0)
+        {
+            dist_min = dist;                            move32 (); 
+            index = i;                                  move16 (); 
+            sign = 1;                                   move16 (); 
+        }
+    }
+
+    /* Reading the selected vector */
+
+    p_dico = &dico[shl (index, 2)];                     move16 (); 
+    test (); 
+    if (sign == 0)
+    {
+        lsf_r1[0] = *p_dico++;                          move16 (); 
+        lsf_r1[1] = *p_dico++;                          move16 (); 
+        lsf_r2[0] = *p_dico++;                          move16 (); 
+        lsf_r2[1] = *p_dico++;                          move16 (); 
+    }
+    else
+    {
+        lsf_r1[0] = negate (*p_dico++);                 move16 (); 
+        lsf_r1[1] = negate (*p_dico++);                 move16 (); 
+        lsf_r2[0] = negate (*p_dico++);                 move16 (); 
+        lsf_r2[1] = negate (*p_dico++);                 move16 (); 
+    }
+
+    index = shl (index, 1);
+    index = add (index, sign);
+
+    return index;
+
+}
+
+/****************************************************
+ * FUNCTION  Lsf_wt                                                         *
+ *                                                                          *
+ ****************************************************
+ * Compute LSF weighting factors                                            *
+ *                                                                          *
+ *  d[i] = lsf[i+1] - lsf[i-1]                                              *
+ *                                                                          *
+ *  The weighting factors are approximated by two line segment.             *
+ *                                                                          *
+ *  First segment passes by the following 2 points:                         *
+ *                                                                          *
+ *     d[i] = 0Hz     wf[i] = 3.347                                         *
+ *     d[i] = 450Hz   wf[i] = 1.8                                           *
+ *                                                                          *
+ *  Second segment passes by the following 2 points:                        *
+ *                                                                          *
+ *     d[i] = 450Hz   wf[i] = 1.8                                           *
+ *     d[i] = 1500Hz  wf[i] = 1.0                                           *
+ *                                                                          *
+ *  if( d[i] < 450Hz )                                                      *
+ *    wf[i] = 3.347 - ( (3.347-1.8) / (450-0)) *  d[i]                      *
+ *  else                                                                    *
+ *    wf[i] = 1.8 - ( (1.8-1.0) / (1500-450)) *  (d[i] - 450)               *
+ *                                                                          *
+ *                                                                          *
+ *  if( d[i] < 1843)                                                        *
+ *    wf[i] = 3427 - (28160*d[i])>>15                                       *
+ *  else                                                                    *
+ *    wf[i] = 1843 - (6242*(d[i]-1843))>>15                                 *
+ *                                                                          *
+ *--------------------------------------------------------------------------*/
+
+void Lsf_wt (
+    Word16 *lsf,         /* input : LSF vector                  */
+    Word16 *wf)          /* output: square of weighting factors */
+{
+    Word16 temp;
+    Word16 i;
+    /* wf[0] = lsf[1] - 0  */
+    wf[0] = lsf[1];                                     move16 (); 
+    for (i = 1; i < 9; i++)
+    {
+        wf[i] = sub (lsf[i + 1], lsf[i - 1]);           move16 (); 
+    }
+    /* wf[9] = 0.5 - lsf[8] */    
+    wf[9] = sub (16384, lsf[8]);move16 ();      
+
+    for (i = 0; i < 10; i++)
+    {
+        temp = sub (wf[i], 1843);
+        test (); 
+        if (temp < 0)
+        {
+            wf[i] = sub (3427, mult (wf[i], 28160));    move16 (); 
+        }
+        else
+        {
+            wf[i] = sub (1843, mult (temp, 6242));      move16 (); 
+        }
+
+        wf[i] = shl (wf[i], 3); move16 (); 
+    }
+    return;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgsmefr/reorder.c	Fri Nov 25 16:18:21 2022 +0000
@@ -0,0 +1,34 @@
+/*************************************************************************
+ *
+ *  FUNCTION:  Reorder_lsf()
+ *
+ *  PURPOSE: To make sure that the LSFs are properly ordered and to keep a
+ *           certain minimum distance between adjacent LSFs.                               *
+ *           The LSFs are in the frequency range 0-0.5 and represented in Q15
+ *
+ *************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "count.h"
+
+void Reorder_lsf (
+    Word16 *lsf,        /* (i/o)     : vector of LSFs   (range: 0<=val<=0.5) */
+    Word16 min_dist,    /* (i)       : minimum required distance             */
+    Word16 n            /* (i)       : LPC order                             */
+)
+{
+    Word16 i;
+    Word16 lsf_min;
+
+    lsf_min = min_dist;         move16 (); 
+    for (i = 0; i < n; i++)
+    {
+        test (); 
+        if (sub (lsf[i], lsf_min) < 0)
+        {
+            lsf[i] = lsf_min;   move16 (); 
+        }
+        lsf_min = add (lsf[i], min_dist);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgsmefr/residu.c	Fri Nov 25 16:18:21 2022 +0000
@@ -0,0 +1,41 @@
+/*************************************************************************
+ *
+ *  FUNCTION:  Residu
+ *
+ *  PURPOSE:  Computes the LP residual.
+ *
+ *  DESCRIPTION:
+ *     The LP residual is computed by filtering the input speech through
+ *     the LP inverse filter A(z).
+ *
+ *************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "count.h"
+
+/* m = LPC order == 10 */
+#define m 10
+
+void Residu (
+    Word16 a[], /* (i)     : prediction coefficients                      */
+    Word16 x[], /* (i)     : speech signal                                */
+    Word16 y[], /* (o)     : residual signal                              */
+    Word16 lg   /* (i)     : size of filtering                            */
+)
+{
+    Word16 i, j;
+    Word32 s;
+
+    for (i = 0; i < lg; i++)
+    {
+        s = L_mult (x[i], a[0]);
+        for (j = 1; j <= m; j++)
+        {
+            s = L_mac (s, a[j], x[i - j]);
+        }
+        s = L_shl (s, 3);
+        y[i] = round (s);       move16 (); 
+    }
+    return;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgsmefr/syn_filt.c	Fri Nov 25 16:18:21 2022 +0000
@@ -0,0 +1,68 @@
+/*************************************************************************
+ *
+ *  FUNCTION:  Syn_filt:
+ *
+ *  PURPOSE:  Perform synthesis filtering through 1/A(z).
+ *
+ *************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "count.h"
+
+/* m = LPC order == 10 */
+#define m 10
+
+void Syn_filt (
+    Word16 a[],     /* (i)     : a[m+1] prediction coefficients   (m=10)  */
+    Word16 x[],     /* (i)     : input signal                             */
+    Word16 y[],     /* (o)     : output signal                            */
+    Word16 lg,      /* (i)     : size of filtering                        */
+    Word16 mem[],   /* (i/o)   : memory associated with this filtering.   */
+    Word16 update   /* (i)     : 0=no update, 1=update of memory.         */
+)
+{
+    Word16 i, j;
+    Word32 s;
+    Word16 tmp[80];   /* This is usually done by memory allocation (lg+m) */
+    Word16 *yy;
+
+    /* Copy mem[] to yy[] */
+
+    yy = tmp;                           move16 (); 
+
+    for (i = 0; i < m; i++)
+    {
+        *yy++ = mem[i];                 move16 (); 
+    } 
+
+    /* Do the filtering. */
+
+    for (i = 0; i < lg; i++)
+    {
+        s = L_mult (x[i], a[0]);
+        for (j = 1; j <= m; j++)
+        {
+            s = L_msu (s, a[j], yy[-j]);
+        }
+        s = L_shl (s, 3);
+        *yy++ = round (s);              move16 (); 
+    }
+
+    for (i = 0; i < lg; i++)
+    {
+        y[i] = tmp[i + m];              move16 (); 
+    }
+
+    /* Update of memory if update==1 */
+
+    test (); 
+    if (update != 0)
+    {
+        for (i = 0; i < m; i++)
+        {
+            mem[i] = y[lg - m + i];     move16 (); 
+        }
+    }
+    return;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgsmefr/weight_a.c	Fri Nov 25 16:18:21 2022 +0000
@@ -0,0 +1,34 @@
+/*************************************************************************
+ *
+ *  FUNCTION:  Weight_Ai
+ *
+ *  PURPOSE: Spectral expansion of LP coefficients.  (order==10)
+ *
+ *  DESCRIPTION:
+ *      a_exp[i] = a[i] * fac[i-1]    ,i=1,10
+ *
+ *************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "count.h"
+
+/* m = LPC order == 10 */
+#define m 10
+
+void Weight_Ai (
+    Word16 a[],         /* (i)     : a[m+1]  LPC coefficients   (m=10)    */
+    Word16 fac[],       /* (i)     : Spectral expansion factors.          */
+    Word16 a_exp[]      /* (o)     : Spectral expanded LPC coefficients   */
+)
+{
+    Word16 i;
+
+    a_exp[0] = a[0];                                    move16 (); 
+    for (i = 1; i <= m; i++)
+    {
+        a_exp[i] = round (L_mult (a[i], fac[i - 1]));   move16 (); 
+    }
+
+    return;
+}