changeset 0:56410792419a

src: original EFR source from ETSI
author Mychaela Falconia <falcon@freecalypso.org>
date Wed, 03 Apr 2024 05:31:37 +0000
parents
children cd1a63963fa4
files src/agc.c src/autocorr.c src/az_lsp.c src/basic_op.h src/basicop2.c src/bits2prm.c src/c1035pf.c src/cnst.h src/cod_12k2.c src/codec.h src/coder.c src/convolve.c src/copy.c src/count.c src/count.h src/d1035pf.c src/d_gains.c src/d_homing.c src/d_homing.h src/d_plsf_5.c src/dec_12k2.c src/dec_lag6.c src/decoder.c src/dtx.c src/dtx.h src/e_homing.c src/e_homing.h src/ed_iface.c src/enc_lag6.c src/g_code.c src/g_pitch.c src/gains_tb.h src/grid.tab src/int_lpc.c src/inter_6.c src/inv_sqrt.c src/inv_sqrt.tab src/lag_wind.c src/lag_wind.tab src/levinson.c src/log2.c src/log2.tab src/lsp_az.c src/lsp_lsf.c src/lsp_lsf.tab src/n_proc.c src/n_stack.h src/oper_32b.c src/oper_32b.h src/pitch_f6.c src/pitch_ol.c src/pow2.c src/pow2.tab src/pre_proc.c src/pred_lt6.c src/preemph.c src/prm2bits.c src/pstfilt2.c src/q_gains.c src/q_plsf_5.c src/q_plsf_5.tab src/reorder.c src/residu.c src/set_zero.c src/sig_proc.h src/syn_filt.c src/typedef.h src/vad.c src/vad.h src/weight_a.c src/window2.tab
diffstat 71 files changed, 14955 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/agc.c	Wed Apr 03 05:31:37 2024 +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/src/autocorr.c	Wed Apr 03 05:31:37 2024 +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/src/az_lsp.c	Wed Apr 03 05:31:37 2024 +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/src/basic_op.h	Wed Apr 03 05:31:37 2024 +0000
@@ -0,0 +1,62 @@
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Constants and Globals                                                   |
+ |___________________________________________________________________________|
+*/
+extern Flag Overflow;
+extern Flag Carry;
+
+#define MAX_32 (Word32)0x7fffffffL
+#define MIN_32 (Word32)0x80000000L
+
+#define MAX_16 (Word16)0x7fff
+#define MIN_16 (Word16)0x8000
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Prototypes for basic arithmetic operators                               |
+ |___________________________________________________________________________|
+*/
+
+Word16 add (Word16 var1, Word16 var2);    /* Short add,           1   */
+Word16 sub (Word16 var1, Word16 var2);    /* Short sub,           1   */
+Word16 abs_s (Word16 var1);               /* Short abs,           1   */
+Word16 shl (Word16 var1, Word16 var2);    /* Short shift left,    1   */
+Word16 shr (Word16 var1, Word16 var2);    /* Short shift right,   1   */
+Word16 mult (Word16 var1, Word16 var2);   /* Short mult,          1   */
+Word32 L_mult (Word16 var1, Word16 var2); /* Long mult,           1   */
+Word16 negate (Word16 var1);              /* Short negate,        1   */
+Word16 extract_h (Word32 L_var1);         /* Extract high,        1   */
+Word16 extract_l (Word32 L_var1);         /* Extract low,         1   */
+Word16 round (Word32 L_var1);             /* Round,               1   */
+Word32 L_mac (Word32 L_var3, Word16 var1, Word16 var2);   /* Mac,  1  */
+Word32 L_msu (Word32 L_var3, Word16 var1, Word16 var2);   /* Msu,  1  */
+Word32 L_macNs (Word32 L_var3, Word16 var1, Word16 var2); /* Mac without
+                                                             sat, 1   */
+Word32 L_msuNs (Word32 L_var3, Word16 var1, Word16 var2); /* Msu without
+                                                             sat, 1   */
+Word32 L_add (Word32 L_var1, Word32 L_var2);    /* Long add,        2 */
+Word32 L_sub (Word32 L_var1, Word32 L_var2);    /* Long sub,        2 */
+Word32 L_add_c (Word32 L_var1, Word32 L_var2);  /* Long add with c, 2 */
+Word32 L_sub_c (Word32 L_var1, Word32 L_var2);  /* Long sub with c, 2 */
+Word32 L_negate (Word32 L_var1);                /* Long negate,     2 */
+Word16 mult_r (Word16 var1, Word16 var2);       /* Mult with round, 2 */
+Word32 L_shl (Word32 L_var1, Word16 var2);      /* Long shift left, 2 */
+Word32 L_shr (Word32 L_var1, Word16 var2);      /* Long shift right, 2*/
+Word16 shr_r (Word16 var1, Word16 var2);        /* Shift right with
+                                                   round, 2           */
+Word16 mac_r (Word32 L_var3, Word16 var1, Word16 var2); /* Mac with
+                                                           rounding,2 */
+Word16 msu_r (Word32 L_var3, Word16 var1, Word16 var2); /* Msu with
+                                                           rounding,2 */
+Word32 L_deposit_h (Word16 var1);        /* 16 bit var1 -> MSB,     2 */
+Word32 L_deposit_l (Word16 var1);        /* 16 bit var1 -> LSB,     2 */
+
+Word32 L_shr_r (Word32 L_var1, Word16 var2); /* Long shift right with
+                                                round,  3             */
+Word32 L_abs (Word32 L_var1);            /* Long abs,              3  */
+Word32 L_sat (Word32 L_var1);            /* Long saturation,       4  */
+Word16 norm_s (Word16 var1);             /* Short norm,           15  */
+Word16 div_s (Word16 var1, Word16 var2); /* Short division,       18  */
+Word16 norm_l (Word32 L_var1);           /* Long norm,            30  */   
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/basicop2.c	Wed Apr 03 05:31:37 2024 +0000
@@ -0,0 +1,2126 @@
+/*___________________________________________________________________________
+ |                                                                           |
+ | Basic arithmetic operators.                                               |
+ |___________________________________________________________________________|
+*/
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Include-Files                                                           |
+ |___________________________________________________________________________|
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "typedef.h"
+#include "basic_op.h"
+
+#if (WMOPS)
+#include "count.h"
+extern BASIC_OP counter;
+
+#endif
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Local Functions                                                         |
+ |___________________________________________________________________________|
+*/
+Word16 saturate (Word32 L_var1);
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Constants and Globals                                                   |
+ |___________________________________________________________________________|
+*/
+Flag Overflow = 0;
+Flag Carry = 0;
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Functions                                                               |
+ |___________________________________________________________________________|
+*/
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : saturate                                                |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |    Limit the 32 bit input to the range of a 16 bit word.                  |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    L_var1                                                                 |
+ |             32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.                 |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    var_out                                                                |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var_out <= 0x0000 7fff.                |
+ |___________________________________________________________________________|
+*/
+
+Word16 
+saturate (Word32 L_var1)
+{
+    Word16 var_out;
+
+    if (L_var1 > 0X00007fffL)
+    {
+        Overflow = 1;
+        var_out = MAX_16;
+    }
+    else if (L_var1 < (Word32) 0xffff8000L)
+    {
+        Overflow = 1;
+        var_out = MIN_16;
+    }
+    else
+    {
+        Overflow = 0;
+        var_out = extract_l (L_var1);
+#if (WMOPS)
+        counter.extract_l--;
+#endif
+    }
+
+    return (var_out);
+}
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : add                                                     |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |    Performs the addition (var1+var2) with overflow control and saturation;|
+ |    the 16 bit result is set at +32767 when overflow occurs or at -32768   |
+ |    when underflow occurs.                                                 |
+ |                                                                           |
+ |   Complexity weight : 1                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    var1                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |    var2                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    var_out                                                                |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var_out <= 0x0000 7fff.                |
+ |___________________________________________________________________________|
+*/
+
+Word16 add (Word16 var1, Word16 var2)
+{
+    Word16 var_out;
+    Word32 L_sum;
+
+    L_sum = (Word32) var1 + var2;
+    var_out = saturate (L_sum);
+#if (WMOPS)
+    counter.add++;
+#endif
+    return (var_out);
+}
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : sub                                                     |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |    Performs the subtraction (var1+var2) with overflow control and satu-   |
+ |    ration; the 16 bit result is set at +32767 when overflow occurs or at  |
+ |    -32768 when underflow occurs.                                          |
+ |                                                                           |
+ |   Complexity weight : 1                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    var1                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |    var2                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    var_out                                                                |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var_out <= 0x0000 7fff.                |
+ |___________________________________________________________________________|
+*/
+
+Word16 sub (Word16 var1, Word16 var2)
+{
+    Word16 var_out;
+    Word32 L_diff;
+
+    L_diff = (Word32) var1 - var2;
+    var_out = saturate (L_diff);
+#if (WMOPS)
+    counter.sub++;
+#endif
+    return (var_out);
+}
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : abs_s                                                   |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |    Absolute value of var1; abs_s(-32768) = 32767.                         |
+ |                                                                           |
+ |   Complexity weight : 1                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    var1                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    var_out                                                                |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0x0000 0000 <= var_out <= 0x0000 7fff.                |
+ |___________________________________________________________________________|
+*/
+
+Word16 abs_s (Word16 var1)
+{
+    Word16 var_out;
+
+    if (var1 == (Word16) 0X8000)
+    {
+        var_out = MAX_16;
+    }
+    else
+    {
+        if (var1 < 0)
+        {
+            var_out = -var1;
+        }
+        else
+        {
+            var_out = var1;
+        }
+    }
+#if (WMOPS)
+    counter.abs_s++;
+#endif
+    return (var_out);
+}
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : shl                                                     |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   Arithmetically shift the 16 bit input var1 left var2 positions.Zero fill|
+ |   the var2 LSB of the result. If var2 is negative, arithmetically shift   |
+ |   var1 right by -var2 with sign extension. Saturate the result in case of |
+ |   underflows or overflows.                                                |
+ |                                                                           |
+ |   Complexity weight : 1                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    var1                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |    var2                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    var_out                                                                |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var_out <= 0x0000 7fff.                |
+ |___________________________________________________________________________|
+*/
+
+Word16 shl (Word16 var1, Word16 var2)
+{
+    Word16 var_out;
+    Word32 result;
+
+    if (var2 < 0)
+    {
+        var_out = shr (var1, -var2);
+#if (WMOPS)
+        counter.shr--;
+#endif
+    }
+    else
+    {
+        result = (Word32) var1 *((Word32) 1 << var2);
+
+        if ((var2 > 15 && var1 != 0) || (result != (Word32) ((Word16) result)))
+        {
+            Overflow = 1;
+            var_out = (var1 > 0) ? MAX_16 : MIN_16;
+        }
+        else
+        {
+            var_out = extract_l (result);
+#if (WMOPS)
+            counter.extract_l--;
+#endif
+        }
+    }
+#if (WMOPS)
+    counter.shl++;
+#endif
+    return (var_out);
+}
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : shr                                                     |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   Arithmetically shift the 16 bit input var1 right var2 positions with    |
+ |   sign extension. If var2 is negative, arithmetically shift var1 left by  |
+ |   -var2 with sign extension. Saturate the result in case of underflows or |
+ |   overflows.                                                              |
+ |                                                                           |
+ |   Complexity weight : 1                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    var1                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |    var2                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    var_out                                                                |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var_out <= 0x0000 7fff.                |
+ |___________________________________________________________________________|
+*/
+
+Word16 shr (Word16 var1, Word16 var2)
+{
+    Word16 var_out;
+
+    if (var2 < 0)
+    {
+        var_out = shl (var1, -var2);
+#if (WMOPS)
+        counter.shl--;
+#endif
+    }
+    else
+    {
+        if (var2 >= 15)
+        {
+            var_out = (var1 < 0) ? -1 : 0;
+        }
+        else
+        {
+            if (var1 < 0)
+            {
+                var_out = ~((~var1) >> var2);
+            }
+            else
+            {
+                var_out = var1 >> var2;
+            }
+        }
+    }
+
+#if (WMOPS)
+    counter.shr++;
+#endif
+    return (var_out);
+}
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : mult                                                    |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |    Performs the multiplication of var1 by var2 and gives a 16 bit result  |
+ |    which is scaled i.e.:                                                  |
+ |             mult(var1,var2) = extract_l(L_shr((var1 times var2),15)) and  |
+ |             mult(-32768,-32768) = 32767.                                  |
+ |                                                                           |
+ |   Complexity weight : 1                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    var1                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |    var2                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    var_out                                                                |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var_out <= 0x0000 7fff.                |
+ |___________________________________________________________________________|
+*/
+
+Word16 mult (Word16 var1, Word16 var2)
+{
+    Word16 var_out;
+    Word32 L_product;
+
+    L_product = (Word32) var1 *(Word32) var2;
+
+    L_product = (L_product & (Word32) 0xffff8000L) >> 15;
+
+    if (L_product & (Word32) 0x00010000L)
+        L_product = L_product | (Word32) 0xffff0000L;
+
+    var_out = saturate (L_product);
+#if (WMOPS)
+    counter.mult++;
+#endif
+    return (var_out);
+}
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : L_mult                                                  |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   L_mult is the 32 bit result of the multiplication of var1 times var2    |
+ |   with one shift left i.e.:                                               |
+ |        L_mult(var1,var2) = L_shl((var1 times var2),1) and                   |
+ |        L_mult(-32768,-32768) = 2147483647.                                |
+ |                                                                           |
+ |   Complexity weight : 1                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    var1                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |    var2                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    L_var_out                                                              |
+ |             32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.              |
+ |___________________________________________________________________________|
+*/
+
+Word32 L_mult (Word16 var1, Word16 var2)
+{
+    Word32 L_var_out;
+
+    L_var_out = (Word32) var1 *(Word32) var2;
+
+    if (L_var_out != (Word32) 0x40000000L)
+    {
+        L_var_out *= 2;
+    }
+    else
+    {
+        Overflow = 1;
+        L_var_out = MAX_32;
+    }
+
+#if (WMOPS)
+    counter.L_mult++;
+#endif
+    return (L_var_out);
+}
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : negate                                                  |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   Negate var1 with saturation, saturate in the case where input is -32768:|
+ |                negate(var1) = sub(0,var1).                                |
+ |                                                                           |
+ |   Complexity weight : 1                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    var1                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    var_out                                                                |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var_out <= 0x0000 7fff.                |
+ |___________________________________________________________________________|
+*/
+
+Word16 negate (Word16 var1)
+{
+    Word16 var_out;
+
+    var_out = (var1 == MIN_16) ? MAX_16 : -var1;
+#if (WMOPS)
+    counter.negate++;
+#endif
+    return (var_out);
+}
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : extract_h                                               |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   Return the 16 MSB of L_var1.                                            |
+ |                                                                           |
+ |   Complexity weight : 1                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    L_var1                                                                 |
+ |             32 bit long signed integer (Word32 ) whose value falls in the |
+ |             range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.                 |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    var_out                                                                |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var_out <= 0x0000 7fff.                |
+ |___________________________________________________________________________|
+*/
+
+Word16 extract_h (Word32 L_var1)
+{
+    Word16 var_out;
+
+    var_out = (Word16) (L_var1 >> 16);
+#if (WMOPS)
+    counter.extract_h++;
+#endif
+    return (var_out);
+}
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : extract_l                                               |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   Return the 16 LSB of L_var1.                                            |
+ |                                                                           |
+ |   Complexity weight : 1                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    L_var1                                                                 |
+ |             32 bit long signed integer (Word32 ) whose value falls in the |
+ |             range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.                 |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    var_out                                                                |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var_out <= 0x0000 7fff.                |
+ |___________________________________________________________________________|
+*/
+
+Word16 extract_l (Word32 L_var1)
+{
+    Word16 var_out;
+
+    var_out = (Word16) L_var1;
+#if (WMOPS)
+    counter.extract_l++;
+#endif
+    return (var_out);
+}
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : round                                                   |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   Round the lower 16 bits of the 32 bit input number into the MS 16 bits  |
+ |   with saturation. Shift the resulting bits right by 16 and return the 16 |
+ |   bit number:                                                             |
+ |               round(L_var1) = extract_h(L_add(L_var1,32768))              |
+ |                                                                           |
+ |   Complexity weight : 1                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    L_var1                                                                 |
+ |             32 bit long signed integer (Word32 ) whose value falls in the |
+ |             range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.                 |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    var_out                                                                |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var_out <= 0x0000 7fff.                |
+ |___________________________________________________________________________|
+*/
+
+Word16 round (Word32 L_var1)
+{
+    Word16 var_out;
+    Word32 L_rounded;
+
+    L_rounded = L_add (L_var1, (Word32) 0x00008000L);
+#if (WMOPS)
+    counter.L_add--;
+#endif
+    var_out = extract_h (L_rounded);
+#if (WMOPS)
+    counter.extract_h--;
+    counter.round++;
+#endif
+    return (var_out);
+}
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : L_mac                                                   |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   Multiply var1 by var2 and shift the result left by 1. Add the 32 bit    |
+ |   result to L_var3 with saturation, return a 32 bit result:               |
+ |        L_mac(L_var3,var1,var2) = L_add(L_var3,L_mult(var1,var2)).         |
+ |                                                                           |
+ |   Complexity weight : 1                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    L_var3   32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.                 |
+ |                                                                           |
+ |    var1                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |    var2                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    L_var_out                                                              |
+ |             32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.              |
+ |___________________________________________________________________________|
+*/
+
+Word32 L_mac (Word32 L_var3, Word16 var1, Word16 var2)
+{
+    Word32 L_var_out;
+    Word32 L_product;
+
+    L_product = L_mult (var1, var2);
+#if (WMOPS)
+    counter.L_mult--;
+#endif
+    L_var_out = L_add (L_var3, L_product);
+#if (WMOPS)
+    counter.L_add--;
+    counter.L_mac++;
+#endif
+    return (L_var_out);
+}
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : L_msu                                                   |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   Multiply var1 by var2 and shift the result left by 1. Subtract the 32   |
+ |   bit result to L_var3 with saturation, return a 32 bit result:           |
+ |        L_msu(L_var3,var1,var2) = L_sub(L_var3,L_mult(var1,var2)).         |
+ |                                                                           |
+ |   Complexity weight : 1                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    L_var3   32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.                 |
+ |                                                                           |
+ |    var1                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |    var2                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    L_var_out                                                              |
+ |             32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.              |
+ |___________________________________________________________________________|
+*/
+
+Word32 L_msu (Word32 L_var3, Word16 var1, Word16 var2)
+{
+    Word32 L_var_out;
+    Word32 L_product;
+
+    L_product = L_mult (var1, var2);
+#if (WMOPS)
+    counter.L_mult--;
+#endif
+    L_var_out = L_sub (L_var3, L_product);
+#if (WMOPS)
+    counter.L_sub--;
+    counter.L_msu++;
+#endif
+    return (L_var_out);
+}
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : L_macNs                                                 |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   Multiply var1 by var2 and shift the result left by 1. Add the 32 bit    |
+ |   result to L_var3 without saturation, return a 32 bit result. Generate   |
+ |   carry and overflow values :                                             |
+ |        L_macNs(L_var3,var1,var2) = L_add_c(L_var3,L_mult(var1,var2)).     |
+ |                                                                           |
+ |   Complexity weight : 1                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    L_var3   32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.                 |
+ |                                                                           |
+ |    var1                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |    var2                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    L_var_out                                                              |
+ |             32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.              |
+ |                                                                           |
+ |   Caution :                                                               |
+ |                                                                           |
+ |    In some cases the Carry flag has to be cleared or set before using     |
+ |    operators which take into account its value.                           |
+ |___________________________________________________________________________|
+*/
+
+Word32 L_macNs (Word32 L_var3, Word16 var1, Word16 var2)
+{
+    Word32 L_var_out;
+
+    L_var_out = L_mult (var1, var2);
+#if (WMOPS)
+    counter.L_mult--;
+#endif
+    L_var_out = L_add_c (L_var3, L_var_out);
+#if (WMOPS)
+    counter.L_add_c--;
+    counter.L_macNs++;
+#endif
+    return (L_var_out);
+}
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : L_msuNs                                                 |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   Multiply var1 by var2 and shift the result left by 1. Subtract the 32   |
+ |   bit result from L_var3 without saturation, return a 32 bit result. Ge-  |
+ |   nerate carry and overflow values :                                      |
+ |        L_msuNs(L_var3,var1,var2) = L_sub_c(L_var3,L_mult(var1,var2)).     |
+ |                                                                           |
+ |   Complexity weight : 1                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    L_var3   32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.                 |
+ |                                                                           |
+ |    var1                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |    var2                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    L_var_out                                                              |
+ |             32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.              |
+ |                                                                           |
+ |   Caution :                                                               |
+ |                                                                           |
+ |    In some cases the Carry flag has to be cleared or set before using     |
+ |    operators which take into account its value.                           |
+ |___________________________________________________________________________|
+*/
+
+Word32 L_msuNs (Word32 L_var3, Word16 var1, Word16 var2)
+{
+    Word32 L_var_out;
+
+    L_var_out = L_mult (var1, var2);
+#if (WMOPS)
+    counter.L_mult--;
+#endif
+    L_var_out = L_sub_c (L_var3, L_var_out);
+#if (WMOPS)
+    counter.L_sub_c--;
+    counter.L_msuNs++;
+#endif
+    return (L_var_out);
+}
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : L_add                                                   |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   32 bits addition of the two 32 bits variables (L_var1+L_var2) with      |
+ |   overflow control and saturation; the result is set at +2147483647 when  |
+ |   overflow occurs or at -2147483648 when underflow occurs.                |
+ |                                                                           |
+ |   Complexity weight : 2                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    L_var1   32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.                 |
+ |                                                                           |
+ |    L_var2   32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.                 |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    L_var_out                                                              |
+ |             32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.              |
+ |___________________________________________________________________________|
+*/
+
+Word32 L_add (Word32 L_var1, Word32 L_var2)
+{
+    Word32 L_var_out;
+
+    L_var_out = L_var1 + L_var2;
+
+    if (((L_var1 ^ L_var2) & MIN_32) == 0)
+    {
+        if ((L_var_out ^ L_var1) & MIN_32)
+        {
+            L_var_out = (L_var1 < 0) ? MIN_32 : MAX_32;
+            Overflow = 1;
+        }
+    }
+#if (WMOPS)
+    counter.L_add++;
+#endif
+    return (L_var_out);
+}
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : L_sub                                                   |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   32 bits subtraction of the two 32 bits variables (L_var1-L_var2) with   |
+ |   overflow control and saturation; the result is set at +2147483647 when  |
+ |   overflow occurs or at -2147483648 when underflow occurs.                |
+ |                                                                           |
+ |   Complexity weight : 2                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    L_var1   32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.                 |
+ |                                                                           |
+ |    L_var2   32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.                 |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    L_var_out                                                              |
+ |             32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.              |
+ |___________________________________________________________________________|
+*/
+
+Word32 L_sub (Word32 L_var1, Word32 L_var2)
+{
+    Word32 L_var_out;
+
+    L_var_out = L_var1 - L_var2;
+
+    if (((L_var1 ^ L_var2) & MIN_32) != 0)
+    {
+        if ((L_var_out ^ L_var1) & MIN_32)
+        {
+            L_var_out = (L_var1 < 0L) ? MIN_32 : MAX_32;
+            Overflow = 1;
+        }
+    }
+#if (WMOPS)
+    counter.L_sub++;
+#endif
+    return (L_var_out);
+}
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : L_add_c                                                 |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   Performs 32 bits addition of the two 32 bits variables (L_var1+L_var2+C)|
+ |   with carry. No saturation. Generate carry and Overflow values. The car- |
+ |   ry and overflow values are binary variables which can be tested and as- |
+ |   signed values.                                                          |
+ |                                                                           |
+ |   Complexity weight : 2                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    L_var1   32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.                 |
+ |                                                                           |
+ |    L_var2   32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.                 |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    L_var_out                                                              |
+ |             32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.              |
+ |                                                                           |
+ |   Caution :                                                               |
+ |                                                                           |
+ |    In some cases the Carry flag has to be cleared or set before using     |
+ |    operators which take into account its value.                           |
+ |___________________________________________________________________________|
+*/
+Word32 L_add_c (Word32 L_var1, Word32 L_var2)
+{
+    Word32 L_var_out;
+    Word32 L_test;
+    Flag carry_int = 0;
+
+    L_var_out = L_var1 + L_var2 + Carry;
+
+    L_test = L_var1 + L_var2;
+
+    if ((L_var1 > 0) && (L_var2 > 0) && (L_test < 0))
+    {
+        Overflow = 1;
+        carry_int = 0;
+    }
+    else
+    {
+        if ((L_var1 < 0) && (L_var2 < 0))
+        {
+            if (L_test >= 0)
+	    {
+                Overflow = 1;
+                carry_int = 1;
+	    }
+            else
+	    {
+                Overflow = 0;
+                carry_int = 1;
+	    }
+        }
+        else
+        {
+            if (((L_var1 ^ L_var2) < 0) && (L_test >= 0))
+            {
+                Overflow = 0;
+                carry_int = 1;
+            }
+            else
+            {
+                Overflow = 0;
+                carry_int = 0;
+            }
+        }
+    }
+
+    if (Carry)
+    {
+        if (L_test == MAX_32)
+        {
+            Overflow = 1;
+            Carry = carry_int;
+        }
+        else
+        {
+            if (L_test == (Word32) 0xFFFFFFFFL)
+            {
+                Carry = 1;
+            }
+            else
+            {
+                Carry = carry_int;
+            }
+        }
+    }
+    else
+    {
+        Carry = carry_int;
+    }
+
+#if (WMOPS)
+    counter.L_add_c++;
+#endif
+    return (L_var_out);
+}
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : L_sub_c                                                 |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   Performs 32 bits subtraction of the two 32 bits variables with carry    |
+ |   (borrow) : L_var1-L_var2-C. No saturation. Generate carry and Overflow  |
+ |   values. The carry and overflow values are binary variables which can    |
+ |   be tested and assigned values.                                          |
+ |                                                                           |
+ |   Complexity weight : 2                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    L_var1   32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.                 |
+ |                                                                           |
+ |    L_var2   32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.                 |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    L_var_out                                                              |
+ |             32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.              |
+ |                                                                           |
+ |   Caution :                                                               |
+ |                                                                           |
+ |    In some cases the Carry flag has to be cleared or set before using     |
+ |    operators which take into account its value.                           |
+ |___________________________________________________________________________|
+*/
+
+Word32 L_sub_c (Word32 L_var1, Word32 L_var2)
+{
+    Word32 L_var_out;
+    Word32 L_test;
+    Flag carry_int = 0;
+
+    if (Carry)
+    {
+        Carry = 0;
+        if (L_var2 != MIN_32)
+        {
+            L_var_out = L_add_c (L_var1, -L_var2);
+#if (WMOPS)
+            counter.L_add_c--;
+#endif
+        }
+        else
+        {
+            L_var_out = L_var1 - L_var2;
+            if (L_var1 > 0L)
+            {
+                Overflow = 1;
+                Carry = 0;
+            }
+        }
+    }
+    else
+    {
+        L_var_out = L_var1 - L_var2 - (Word32) 0X00000001L;
+        L_test = L_var1 - L_var2;
+
+        if ((L_test < 0) && (L_var1 > 0) && (L_var2 < 0))
+        {
+            Overflow = 1;
+            carry_int = 0;
+        }
+        else if ((L_test > 0) && (L_var1 < 0) && (L_var2 > 0))
+        {
+            Overflow = 1;
+            carry_int = 1;
+        }
+        else if ((L_test > 0) && ((L_var1 ^ L_var2) > 0))
+        {
+            Overflow = 0;
+            carry_int = 1;
+        }
+        if (L_test == MIN_32)
+        {
+            Overflow = 1;
+            Carry = carry_int;
+        }
+        else
+        {
+            Carry = carry_int;
+        }
+    }
+
+#if (WMOPS)
+    counter.L_sub_c++;
+#endif
+    return (L_var_out);
+}
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : L_negate                                                |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   Negate the 32 bit variable L_var1 with saturation; saturate in the case |
+ |   where input is -2147483648 (0x8000 0000).                               |
+ |                                                                           |
+ |   Complexity weight : 2                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    L_var1   32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.                 |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    L_var_out                                                              |
+ |             32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.              |
+ |___________________________________________________________________________|
+*/
+
+Word32 L_negate (Word32 L_var1)
+{
+    Word32 L_var_out;
+
+    L_var_out = (L_var1 == MIN_32) ? MAX_32 : -L_var1;
+#if (WMOPS)
+    counter.L_negate++;
+#endif
+    return (L_var_out);
+}
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : mult_r                                                  |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   Same as mult with rounding, i.e.:                                       |
+ |     mult_r(var1,var2) = extract_l(L_shr(((var1 * var2) + 16384),15)) and  |
+ |     mult_r(-32768,-32768) = 32767.                                        |
+ |                                                                           |
+ |   Complexity weight : 2                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    var1                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |    var2                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    var_out                                                                |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var_out <= 0x0000 7fff.                |
+ |___________________________________________________________________________|
+*/
+
+Word16 mult_r (Word16 var1, Word16 var2)
+{
+    Word16 var_out;
+    Word32 L_product_arr;
+
+    L_product_arr = (Word32) var1 *(Word32) var2;       /* product */
+    L_product_arr += (Word32) 0x00004000L;      /* round */
+    L_product_arr &= (Word32) 0xffff8000L;
+    L_product_arr >>= 15;       /* shift */
+
+    if (L_product_arr & (Word32) 0x00010000L)   /* sign extend when necessary */
+    {
+        L_product_arr |= (Word32) 0xffff0000L;
+    }
+    var_out = saturate (L_product_arr);
+#if (WMOPS)
+    counter.mult_r++;
+#endif
+    return (var_out);
+}
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : L_shl                                                   |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   Arithmetically shift the 32 bit input L_var1 left var2 positions. Zero  |
+ |   fill the var2 LSB of the result. If var2 is negative, arithmetically    |
+ |   shift L_var1 right by -var2 with sign extension. Saturate the result in |
+ |   case of underflows or overflows.                                        |
+ |                                                                           |
+ |   Complexity weight : 2                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    L_var1   32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.                 |
+ |                                                                           |
+ |    var2                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    L_var_out                                                              |
+ |             32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.              |
+ |___________________________________________________________________________|
+*/
+
+Word32 L_shl (Word32 L_var1, Word16 var2)
+{
+    Word32 L_var_out;
+
+    if (var2 <= 0)
+    {
+        L_var_out = L_shr (L_var1, -var2);
+#if (WMOPS)
+        counter.L_shr--;
+#endif
+    }
+    else
+    {
+        for (; var2 > 0; var2--)
+        {
+            if (L_var1 > (Word32) 0X3fffffffL)
+            {
+                Overflow = 1;
+                L_var_out = MAX_32;
+                break;
+            }
+            else
+            {
+                if (L_var1 < (Word32) 0xc0000000L)
+                {
+                    Overflow = 1;
+                    L_var_out = MIN_32;
+                    break;
+                }
+            }
+            L_var1 *= 2;
+            L_var_out = L_var1;
+        }
+    }
+#if (WMOPS)
+    counter.L_shl++;
+#endif
+    return (L_var_out);
+}
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : L_shr                                                   |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   Arithmetically shift the 32 bit input L_var1 right var2 positions with  |
+ |   sign extension. If var2 is negative, arithmetically shift L_var1 left   |
+ |   by -var2 and zero fill the -var2 LSB of the result. Saturate the result |
+ |   in case of underflows or overflows.                                     |
+ |                                                                           |
+ |   Complexity weight : 2                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    L_var1   32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.                 |
+ |                                                                           |
+ |    var2                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    L_var_out                                                              |
+ |             32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.              |
+ |___________________________________________________________________________|
+*/
+
+Word32 L_shr (Word32 L_var1, Word16 var2)
+{
+    Word32 L_var_out;
+
+    if (var2 < 0)
+    {
+        L_var_out = L_shl (L_var1, -var2);
+#if (WMOPS)
+        counter.L_shl--;
+#endif
+    }
+    else
+    {
+        if (var2 >= 31)
+        {
+            L_var_out = (L_var1 < 0L) ? -1 : 0;
+        }
+        else
+        {
+            if (L_var1 < 0)
+            {
+                L_var_out = ~((~L_var1) >> var2);
+            }
+            else
+            {
+                L_var_out = L_var1 >> var2;
+            }
+        }
+    }
+#if (WMOPS)
+    counter.L_shr++;
+#endif
+    return (L_var_out);
+}
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : shr_r                                                   |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   Same as shr(var1,var2) but with rounding. Saturate the result in case of|
+ |   underflows or overflows :                                               |
+ |    - If var2 is greater than zero :                                       |
+ |          if (sub(shl(shr(var1,var2),1),shr(var1,sub(var2,1))))            |
+ |          is equal to zero                                                 |
+ |                     then                                                  |
+ |                     shr_r(var1,var2) = shr(var1,var2)                     |
+ |                     else                                                  |
+ |                     shr_r(var1,var2) = add(shr(var1,var2),1)              |
+ |    - If var2 is less than or equal to zero :                              |
+ |                     shr_r(var1,var2) = shr(var1,var2).                    |
+ |                                                                           |
+ |   Complexity weight : 2                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    var1                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |    var2                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    var_out                                                                |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var_out <= 0x0000 7fff.                |
+ |___________________________________________________________________________|
+*/
+
+Word16 shr_r (Word16 var1, Word16 var2)
+{
+    Word16 var_out;
+
+    if (var2 > 15)
+    {
+        var_out = 0;
+    }
+    else
+    {
+        var_out = shr (var1, var2);
+#if (WMOPS)
+        counter.shr--;
+#endif
+
+        if (var2 > 0)
+        {
+            if ((var1 & ((Word16) 1 << (var2 - 1))) != 0)
+            {
+                var_out++;
+            }
+        }
+    }
+#if (WMOPS)
+    counter.shr_r++;
+#endif
+    return (var_out);
+}
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : mac_r                                                   |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   Multiply var1 by var2 and shift the result left by 1. Add the 32 bit    |
+ |   result to L_var3 with saturation. Round the LS 16 bits of the result    |
+ |   into the MS 16 bits with saturation and shift the result right by 16.   |
+ |   Return a 16 bit result.                                                 |
+ |            mac_r(L_var3,var1,var2) = round(L_mac(L_var3,var1,var2))       |
+ |                                                                           |
+ |   Complexity weight : 2                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    L_var3   32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.                 |
+ |                                                                           |
+ |    var1                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |    var2                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    var_out                                                                |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0x0000 8000 <= L_var_out <= 0x0000 7fff.              |
+ |___________________________________________________________________________|
+*/
+
+Word16 mac_r (Word32 L_var3, Word16 var1, Word16 var2)
+{
+    Word16 var_out;
+
+    L_var3 = L_mac (L_var3, var1, var2);
+#if (WMOPS)
+    counter.L_mac--;
+#endif
+    L_var3 = L_add (L_var3, (Word32) 0x00008000L);
+#if (WMOPS)
+    counter.L_add--;
+#endif
+    var_out = extract_h (L_var3);
+#if (WMOPS)
+    counter.extract_h--;
+    counter.mac_r++;
+#endif
+    return (var_out);
+}
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : msu_r                                                   |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   Multiply var1 by var2 and shift the result left by 1. Subtract the 32   |
+ |   bit result to L_var3 with saturation. Round the LS 16 bits of the res-  |
+ |   ult into the MS 16 bits with saturation and shift the result right by   |
+ |   16. Return a 16 bit result.                                             |
+ |            msu_r(L_var3,var1,var2) = round(L_msu(L_var3,var1,var2))       |
+ |                                                                           |
+ |   Complexity weight : 2                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    L_var3   32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.                 |
+ |                                                                           |
+ |    var1                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |    var2                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    var_out                                                                |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0x0000 8000 <= L_var_out <= 0x0000 7fff.              |
+ |___________________________________________________________________________|
+*/
+
+Word16 msu_r (Word32 L_var3, Word16 var1, Word16 var2)
+{
+    Word16 var_out;
+
+    L_var3 = L_msu (L_var3, var1, var2);
+#if (WMOPS)
+    counter.L_msu--;
+#endif
+    L_var3 = L_add (L_var3, (Word32) 0x00008000L);
+#if (WMOPS)
+    counter.L_add--;
+#endif
+    var_out = extract_h (L_var3);
+#if (WMOPS)
+    counter.extract_h--;
+    counter.msu_r++;
+#endif
+    return (var_out);
+}
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : L_deposit_h                                             |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   Deposit the 16 bit var1 into the 16 MS bits of the 32 bit output. The   |
+ |   16 LS bits of the output are zeroed.                                    |
+ |                                                                           |
+ |   Complexity weight : 2                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    var1                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    L_var_out                                                              |
+ |             32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= var_out <= 0x7fff 0000.                |
+ |___________________________________________________________________________|
+*/
+
+Word32 L_deposit_h (Word16 var1)
+{
+    Word32 L_var_out;
+
+    L_var_out = (Word32) var1 << 16;
+#if (WMOPS)
+    counter.L_deposit_h++;
+#endif
+    return (L_var_out);
+}
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : L_deposit_l                                             |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   Deposit the 16 bit var1 into the 16 LS bits of the 32 bit output. The   |
+ |   16 MS bits of the output are sign extended.                             |
+ |                                                                           |
+ |   Complexity weight : 2                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    var1                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    L_var_out                                                              |
+ |             32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0xFFFF 8000 <= var_out <= 0x0000 7fff.                |
+ |___________________________________________________________________________|
+*/
+
+Word32 L_deposit_l (Word16 var1)
+{
+    Word32 L_var_out;
+
+    L_var_out = (Word32) var1;
+#if (WMOPS)
+    counter.L_deposit_l++;
+#endif
+    return (L_var_out);
+}
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : L_shr_r                                                 |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   Same as L_shr(L_var1,var2) but with rounding. Saturate the result in    |
+ |   case of underflows or overflows :                                       |
+ |    - If var2 is greater than zero :                                       |
+ |          if (L_sub(L_shl(L_shr(L_var1,var2),1),L_shr(L_var1,sub(var2,1))))|
+ |          is equal to zero                                                 |
+ |                     then                                                  |
+ |                     L_shr_r(L_var1,var2) = L_shr(L_var1,var2)             |
+ |                     else                                                  |
+ |                     L_shr_r(L_var1,var2) = L_add(L_shr(L_var1,var2),1)    |
+ |    - If var2 is less than or equal to zero :                              |
+ |                     L_shr_r(L_var1,var2) = L_shr(L_var1,var2).            |
+ |                                                                           |
+ |   Complexity weight : 3                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    L_var1                                                                 |
+ |             32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= var1 <= 0x7fff ffff.                   |
+ |                                                                           |
+ |    var2                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    L_var_out                                                              |
+ |             32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= var_out <= 0x7fff ffff.                |
+ |___________________________________________________________________________|
+*/
+
+Word32 L_shr_r (Word32 L_var1, Word16 var2)
+{
+    Word32 L_var_out;
+
+    if (var2 > 31)
+    {
+        L_var_out = 0;
+    }
+    else
+    {
+        L_var_out = L_shr (L_var1, var2);
+#if (WMOPS)
+        counter.L_shr--;
+#endif
+        if (var2 > 0)
+        {
+            if ((L_var1 & ((Word32) 1 << (var2 - 1))) != 0)
+            {
+                L_var_out++;
+            }
+        }
+    }
+#if (WMOPS)
+    counter.L_shr_r++;
+#endif
+    return (L_var_out);
+}
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : L_abs                                                   |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |    Absolute value of L_var1; Saturate in case where the input is          |
+ |                                                               -214783648  |
+ |                                                                           |
+ |   Complexity weight : 3                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    L_var1                                                                 |
+ |             32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= var1 <= 0x7fff ffff.                   |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    L_var_out                                                              |
+ |             32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x0000 0000 <= var_out <= 0x7fff ffff.                |
+ |___________________________________________________________________________|
+*/
+
+Word32 L_abs (Word32 L_var1)
+{
+    Word32 L_var_out;
+
+    if (L_var1 == MIN_32)
+    {
+        L_var_out = MAX_32;
+    }
+    else
+    {
+        if (L_var1 < 0)
+        {
+            L_var_out = -L_var1;
+        }
+        else
+        {
+            L_var_out = L_var1;
+        }
+    }
+
+#if (WMOPS)
+    counter.L_abs++;
+#endif
+    return (L_var_out);
+}
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : L_sat                                                   |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |    32 bit L_var1 is set to 2147483647 if an overflow occured or to        |
+ |    -2147483648 if an underflow occured on the most recent L_add_c,        |
+ |    L_sub_c, L_macNs or L_msuNs operations. The carry and overflow values  |
+ |    are binary values which can be tested and assigned values.             |
+ |                                                                           |
+ |   Complexity weight : 4                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    L_var1                                                                 |
+ |             32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= var1 <= 0x7fff ffff.                   |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    L_var_out                                                              |
+ |             32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= var_out <= 0x7fff ffff.                |
+ |___________________________________________________________________________|
+*/
+
+Word32 L_sat (Word32 L_var1)
+{
+    Word32 L_var_out;
+
+    L_var_out = L_var1;
+
+    if (Overflow)
+    {
+
+        if (Carry)
+        {
+            L_var_out = MIN_32;
+        }
+        else
+        {
+            L_var_out = MAX_32;
+        }
+
+        Carry = 0;
+        Overflow = 0;
+    }
+#if (WMOPS)
+    counter.L_sat++;
+#endif
+    return (L_var_out);
+}
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : norm_s                                                  |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   Produces the number of left shift needed to normalize the 16 bit varia- |
+ |   ble var1 for positive values on the interval with minimum of 16384 and  |
+ |   maximum of 32767, and for negative values on the interval with minimum  |
+ |   of -32768 and maximum of -16384; in order to normalize the result, the  |
+ |   following operation must be done :                                      |
+ |                    norm_var1 = shl(var1,norm_s(var1)).                    |
+ |                                                                           |
+ |   Complexity weight : 15                                                  |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    var1                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    var_out                                                                |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0x0000 0000 <= var_out <= 0x0000 000f.                |
+ |___________________________________________________________________________|
+*/
+
+Word16 norm_s (Word16 var1)
+{
+    Word16 var_out;
+
+    if (var1 == 0)
+    {
+        var_out = 0;
+    }
+    else
+    {
+        if (var1 == (Word16) 0xffff)
+        {
+            var_out = 15;
+        }
+        else
+        {
+            if (var1 < 0)
+            {
+                var1 = ~var1;
+            }
+            for (var_out = 0; var1 < 0x4000; var_out++)
+            {
+                var1 <<= 1;
+            }
+        }
+    }
+
+#if (WMOPS)
+    counter.norm_s++;
+#endif
+    return (var_out);
+}
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : div_s                                                   |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   Produces a result which is the fractional integer division of var1  by  |
+ |   var2; var1 and var2 must be positive and var2 must be greater or equal  |
+ |   to var1; the result is positive (leading bit equal to 0) and truncated  |
+ |   to 16 bits.                                                             |
+ |   If var1 = var2 then div(var1,var2) = 32767.                             |
+ |                                                                           |
+ |   Complexity weight : 18                                                  |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    var1                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0x0000 0000 <= var1 <= var2 and var2 != 0.            |
+ |                                                                           |
+ |    var2                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : var1 <= var2 <= 0x0000 7fff and var2 != 0.            |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    var_out                                                                |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0x0000 0000 <= var_out <= 0x0000 7fff.                |
+ |             It's a Q15 value (point between b15 and b14).                 |
+ |___________________________________________________________________________|
+*/
+
+Word16 div_s (Word16 var1, Word16 var2)
+{
+    Word16 var_out = 0;
+    Word16 iteration;
+    Word32 L_num;
+    Word32 L_denom;
+
+    if ((var1 > var2) || (var1 < 0) || (var2 < 0))
+    {
+        printf ("Division Error var1=%d  var2=%d\n", var1, var2);
+        exit (0);
+    }
+    if (var2 == 0)
+    {
+        printf ("Division by 0, Fatal error \n");
+        exit (0);
+    }
+    if (var1 == 0)
+    {
+        var_out = 0;
+    }
+    else
+    {
+        if (var1 == var2)
+        {
+            var_out = MAX_16;
+        }
+        else
+        {
+            L_num = L_deposit_l (var1);
+#if (WMOPS)
+            counter.L_deposit_l--;
+#endif
+            L_denom = L_deposit_l (var2);
+#if (WMOPS)
+            counter.L_deposit_l--;
+#endif
+
+            for (iteration = 0; iteration < 15; iteration++)
+            {
+                var_out <<= 1;
+                L_num <<= 1;
+
+                if (L_num >= L_denom)
+                {
+                    L_num = L_sub (L_num, L_denom);
+#if (WMOPS)
+                    counter.L_sub--;
+#endif
+                    var_out = add (var_out, 1);
+#if (WMOPS)
+                    counter.add--;
+#endif
+                }
+            }
+        }
+    }
+
+#if (WMOPS)
+    counter.div_s++;
+#endif
+    return (var_out);
+}
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : norm_l                                                  |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   Produces the number of left shifts needed to normalize the 32 bit varia-|
+ |   ble L_var1 for positive values on the interval with minimum of          |
+ |   1073741824 and maximum of 2147483647, and for negative values on the in-|
+ |   terval with minimum of -2147483648 and maximum of -1073741824; in order |
+ |   to normalize the result, the following operation must be done :         |
+ |                   norm_L_var1 = L_shl(L_var1,norm_l(L_var1)).             |
+ |                                                                           |
+ |   Complexity weight : 30                                                  |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    L_var1                                                                 |
+ |             32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= var1 <= 0x7fff ffff.                   |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    var_out                                                                |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0x0000 0000 <= var_out <= 0x0000 001f.                |
+ |___________________________________________________________________________|
+*/
+
+Word16 norm_l (Word32 L_var1)
+{
+    Word16 var_out;
+
+    if (L_var1 == 0)
+    {
+        var_out = 0;
+    }
+    else
+    {
+        if (L_var1 == (Word32) 0xffffffffL)
+        {
+            var_out = 31;
+        }
+        else
+        {
+            if (L_var1 < 0)
+            {
+                L_var1 = ~L_var1;
+            }
+            for (var_out = 0; L_var1 < (Word32) 0x40000000L; var_out++)
+            {
+                L_var1 <<= 1;
+            }
+        }
+    }
+
+#if (WMOPS)
+    counter.norm_l++;
+#endif
+    return (var_out);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/bits2prm.c	Wed Apr 03 05:31:37 2024 +0000
@@ -0,0 +1,99 @@
+/*************************************************************************
+ *
+ *  FUNCTION:  Bits2prm_12k2
+ *
+ *  PURPOSE: Retrieves the vector of encoder parameters from the received
+ *           serial bits in a frame.
+ *
+ *  DESCRIPTION: The encoder parameters are:
+ *
+ *     BFI      bad frame indicator      1 bit
+ *
+ *     LPC:
+ *              1st codebook             7 bit
+ *              2nd codebook             8 bit
+ *              3rd codebook             8+1 bit
+ *              4th codebook             8 bit
+ *              5th codebook             6 bit
+ *
+ *     1st and 3rd subframes:
+ *           pitch period                9 bit
+ *           pitch gain                  4 bit
+ *           codebook index              35 bit
+ *           codebook gain               5 bit
+ *
+ *     2nd and 4th subframes:
+ *           pitch period                6 bit
+ *           pitch gain                  4 bit
+ *           codebook index              35 bit
+ *           codebook gain               5 bit
+ *
+ *************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "count.h"
+
+/* Local function */
+
+Word16 Bin2int (        /* Reconstructed parameter                      */
+    Word16 no_of_bits,  /* input : number of bits associated with value */
+    Word16 *bitstream   /* output: address where bits are written       */
+);
+
+#define BIT_0     0
+#define BIT_1     1
+#define PRM_NO    57
+
+void Bits2prm_12k2 (
+    Word16 bits[],      /* input : serial bits (244 + bfi)                */
+    Word16 prm[]        /* output: analysis parameters  (57+1 parameters) */
+)
+{
+    Word16 i;
+
+    static const Word16 bitno[PRM_NO] =
+    {
+        7, 8, 9, 8, 6,                          /* LSP VQ          */
+        9, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 5,  /* first subframe  */
+        6, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 5,  /* second subframe */
+        9, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 5,  /* third subframe  */
+        6, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 5}; /* fourth subframe */
+
+    *prm++ = *bits++;                           move16 (); /* read BFI */
+
+    for (i = 0; i < PRM_NO; i++)
+    {
+        prm[i] = Bin2int (bitno[i], bits);      move16 (); 
+        bits += bitno[i];
+    }
+    return;
+}
+
+/*************************************************************************
+ *
+ *  FUNCTION:  Bin2int                   
+ *
+ *  PURPOSE: Read "no_of_bits" bits from the array bitstream[] and convert
+ *           to integer.
+ *
+ *************************************************************************/
+
+Word16 Bin2int (        /* Reconstructed parameter                      */
+    Word16 no_of_bits,  /* input : number of bits associated with value */
+    Word16 *bitstream   /* output: address where bits are written       */
+)
+{
+    Word16 value, i, bit;
+
+    value = 0;                                  move16 (); 
+    for (i = 0; i < no_of_bits; i++)
+    {
+        value = shl (value, 1);
+        bit = *bitstream++;                     move16 (); 
+        test (); 
+        if (sub (bit, BIT_1) == 0)
+            value = add (value, 1);
+    }
+    return (value);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/c1035pf.c	Wed Apr 03 05:31:37 2024 +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/src/cnst.h	Wed Apr 03 05:31:37 2024 +0000
@@ -0,0 +1,21 @@
+/*--------------------------------------------------------------------------*
+*       Codec constant parameters (coder, decoder, and postfilter)          *
+*---------------------------------------------------------------------------*/
+
+#define  L_TOTAL      320       /* Total size of speech buffer.             */
+#define  L_WINDOW     240       /* Window size in LP analysis               */
+#define  L_FRAME      160       /* Frame size                               */
+#define  L_FRAME_BY2  80        /* Frame size divided by 2                  */
+#define  L_SUBFR      40        /* Subframe size                            */
+#define  M            10        /* Order of LP filter                       */
+#define  MP1          (M+1)     /* Order of LP filter + 1                   */
+#define  AZ_SIZE      (4*M+4)   /* Size of array of LP filters in 4 subfr.s */
+#define  PIT_MIN      18        /* Minimum pitch lag                        */
+#define  PIT_MAX      143       /* Maximum pitch lag                        */
+#define  L_INTERPOL   (10+1)    /* Length of filter for interpolation       */
+
+#define  PRM_SIZE     57        /* Size of vector of analysis parameters    */
+#define  SERIAL_SIZE  (244+1)   /* bits per frame + bfi                     */
+
+#define  MU       26214         /* Factor for tilt compensation filter 0.8  */
+#define  AGC_FAC  29491         /* Factor for automatic gain control 0.9    */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cod_12k2.c	Wed Apr 03 05:31:37 2024 +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/src/codec.h	Wed Apr 03 05:31:37 2024 +0000
@@ -0,0 +1,170 @@
+void Init_Coder_12k2 (void);
+
+void Coder_12k2 (
+    Word16 ana[],      /* output  : Analysis parameters */
+    Word16 synth[]     /* output  : Local synthesis     */
+);
+
+void Init_Decoder_12k2 (void);
+
+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
+);
+
+void Init_Post_Filter (void);
+
+void Post_Filter (
+    Word16 *syn,       /* in/out: synthesis speech (postfiltered is output) */
+    Word16 *Az_4       /* input : interpolated LPC parameters in all subfr. */
+);
+
+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                                    */
+    Word16 cod[],      /* (o)   : algebraic (fixed) codebook excitation     */
+    Word16 y[],        /* (o)   : filtered fixed codebook excitation        */
+    Word16 indx[]      /* (o)   : index of 10 pulses (sign + position)      */
+);
+void dec_10i40_35bits (
+    Word16 index[],    /* (i)   : index of 10 pulses (sign+position)        */
+    Word16 cod[]       /* (o)   : algebraic (fixed) codebook excitation     */
+);
+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 d_gain_pitch (  /* out      : quantized pitch gain                   */
+    Word16 index,      /* in       : index of quantization                  */
+    Word16 bfi,        /* in       : bad frame indicator (good = 0)         */
+    Word16 state,      /* in       : state of the state machine             */
+    Word16 prev_bf,    /* Previous bf                                       */
+    Word16 rxdtx_ctrl
+
+);
+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,      /* in    : state of the state machine                */
+    Word16 prev_bf,    /* Previous bf                                       */
+    Word16 rxdtx_ctrl,
+    Word16 i_subfr,
+    Word16 rx_dtx_state
+
+);
+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,
+    Word16 rx_dtx_state
+);
+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 q_gain_pitch (  /* Return index of quantization                      */
+    Word16 *gain       /* (i)    :  Pitch gain to quantize                  */
+);
+
+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 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 G_code (        /* out      : Gain of innovation code.               */
+    Word16 xn[],       /* in       : target vector                          */
+    Word16 y2[]        /* in       : filtered inovation vector              */
+);
+
+Word16 Interpol_6 (    /* (o)  : interpolated value                         */
+    Word16 *x,         /* (i)  : input vector                               */
+    Word16 frac        /* (i)  : fraction                                   */
+);
+void Int_lpc (
+    Word16 lsp_old[],  /* input: LSP vector at the 4th subfr. of past frame */
+    Word16 lsp_mid[],  /* input: LSP vector at the 2nd subfr. of
+                          present frame                                     */
+    Word16 lsp_new[],  /* input: LSP vector at the 4th subfr. of
+                          present frame                                     */
+    Word16 Az[]        /* output: interpolated LP parameters in all subfr.  */
+);
+void Int_lpc2 (
+    Word16 lsp_old[],  /* input: LSP vector at the 4th subfr. 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 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 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          */
+);
+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                             */
+);
+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                       */
+);
+void Bits2prm_12k2 (
+    Word16 bits[],     /* input : serial bits                               */
+    Word16 prm[]       /* output: analysis parameters                       */
+);
+void Prm2bits_12k2 (
+    Word16 prm[],      /* input : analysis parameters                       */
+    Word16 bits[]      /* output: serial bits                               */
+);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/coder.c	Wed Apr 03 05:31:37 2024 +0000
@@ -0,0 +1,209 @@
+/***************************************************************************
+ *
+ *  FILE NAME:  CODER.C
+ *
+ *  Main program of the EFR coder at 12.2 kbit/s.
+ *
+ *    Usage : coder speech_file  bitstream_file
+ *
+ *    Format for speech_file:
+ *      Speech is read from a binary file of 16 bits data.
+ *
+ *    Format for bitstream_file:
+ *      244  words (2-byte) containing 244 bits.
+ *          Bit 0 = 0x0000 and Bit 1 = 0x0001
+ *      One word (2-byte) for voice activity decision (VAD) flag bit
+ *          0x0000 -> inactive (no detected speech activity);
+ *          0x0001 -> active
+ *      One word (2-byte) for speech (SP) flag bit
+ *          0x0000 -> inactive (no transmission of speech frames);
+ *          0x0001 -> active
+ *
+ ***************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "typedef.h"
+#include "basic_op.h"
+#include "sig_proc.h"
+#include "count.h"
+#include "codec.h"
+#include "cnst.h"
+#include "n_stack.h"
+#include "e_homing.h"
+
+#include "dtx.h"
+
+Word16 dtx_mode;
+extern Word16 txdtx_ctrl;
+
+/* L_FRAME, M, PRM_SIZE, AZ_SIZE, SERIAL_SIZE: defined in "cnst.h" */
+
+int main (int argc, char *argv[])
+{
+    FILE *f_speech;             /* File of speech data                   */
+    FILE *f_serial;             /* File of serial bits for transmission  */
+
+    extern Word16 *new_speech;  /* Pointer to new speech data            */
+
+    Word16 prm[PRM_SIZE];       /* Analysis parameters.                  */
+    Word16 serial[SERIAL_SIZE-1];/* Output bitstream buffer               */
+    Word16 syn[L_FRAME];        /* Buffer for synthesis speech           */
+
+    Word16 frame;
+
+    Word16 vad, sp;
+
+    Word16 reset_flag;
+    Word16 i;
+
+    proc_head ("Encoder");
+
+    /*----------------------------------------------------------------------*
+     * Open speech file and result file (output serial bit stream)          *
+     *----------------------------------------------------------------------*/
+
+    if ((argc < 3) || (argc > 4))
+    {
+        fprintf (stderr,
+               "   Usage:\n\n   coder  speech_file  bitstream_file  <dtx|nodtx>\n");
+        fprintf (stderr, "\n");
+        exit (1);
+    }
+    if ((f_speech = fopen (argv[1], "rb")) == NULL)
+    {
+        fprintf (stderr, "Error opening input file  %s !!\n", argv[1]);
+        exit (0);
+    }
+    fprintf (stderr, " Input speech file:  %s\n", argv[1]);
+
+    if ((f_serial = fopen (argv[2], "wb")) == NULL)
+    {
+        fprintf (stderr,"Error opening output bitstream file %s !!\n",argv[2]);
+        exit (0);
+    }
+    fprintf (stderr, " Output bitstream file:  %s\n", argv[2]);
+
+    dtx_mode = 0;               /* DTX disabled by default */
+
+    if (argc == 4)
+    {
+        if (strcmp (argv[3], "nodtx") == 0)
+        {
+            dtx_mode = 0;
+        }
+        else if (strcmp (argv[3], "dtx") == 0)
+        {
+            dtx_mode = 1;
+        }
+        else
+        {
+            fprintf (stderr, "\nWrong DTX switch:  %s !!\n", argv[3]);
+            exit (1);
+        }
+    }
+    if (dtx_mode == 1)
+    {
+        fprintf (stderr, " DTX:  enabled\n");
+    }
+    else
+    {
+        fprintf (stderr, " DTX:  disabled\n");
+    }
+
+    /*-----------------------------------------------------------------------*
+     * Initialisation of the coder.                                          *
+     *-----------------------------------------------------------------------*/
+
+    reset_enc (); /* Bring the encoder, VAD and DTX to the initial state */
+
+    Init_WMOPS_counter ();
+
+    /* Loop for each "L_FRAME" speech data. */
+
+    frame = 0;
+    while (fread (new_speech, sizeof (Word16), L_FRAME, f_speech) == L_FRAME)
+    {
+#if(WMOPS)
+        fprintf (stderr, "frame=%d  ", ++frame);
+#else
+        fprintf (stderr, "\nframe=%d  ", ++frame);
+#endif
+
+        /* Check whether this frame is an encoder homing frame */
+        reset_flag = encoder_homing_frame_test (new_speech);
+
+#if (WMOPS)
+        Reset_WMOPS_counter (); /* reset WMOPS counter for the new frame */
+#endif
+
+        for (i = 0; i < L_FRAME; i++)   /* Delete the 3 LSBs (13-bit input) */
+        {
+            new_speech[i] = new_speech[i] & 0xfff8;  logic16 (); move16 (); 
+        }
+
+        Pre_Process (new_speech, L_FRAME);           /* filter + downscaling */
+
+#if (WMOPS)
+        fwc ();                 /* function worst case */
+#endif
+
+        Coder_12k2 (prm, syn);  /* Find speech parameters   */
+
+        test (); logic16 (); 
+        if ((txdtx_ctrl & TX_SP_FLAG) == 0)
+        {
+            /* Write comfort noise parameters into the parameter frame.
+            Use old parameters in case SID frame is not to be updated */
+            CN_encoding (prm, txdtx_ctrl);
+        }
+        Prm2bits_12k2 (prm, &serial[0]); /* Parameters to serial bits */
+
+#if (WMOPS)
+        fwc ();                 /* function worst case */
+#endif
+
+        test (); logic16 (); 
+        if ((txdtx_ctrl & TX_SP_FLAG) == 0)
+        {
+            /* Insert SID codeword into the serial parameter frame */
+            sid_codeword_encoding (&serial[0]);
+        }
+
+#if (WMOPS)
+        fwc ();                 /* function worst case */
+#endif
+
+#if (WMOPS)
+        WMOPS_output (dtx_mode);/* output speech encoder WMOPS values
+        for current frame */
+#endif
+
+        /* Write the bit stream to file */
+        fwrite (serial, sizeof (Word16), (SERIAL_SIZE-1), f_serial);
+
+        /* Write the VAD- and SP-flags to file after the speech
+        parameter bit stream */
+        vad = 0;
+        sp = 0;
+
+        if ((txdtx_ctrl & TX_VAD_FLAG) != 0)
+        {
+            vad = 1;
+        }
+        if ((txdtx_ctrl & TX_SP_FLAG) != 0)
+        {
+            sp = 1;
+        }
+        fwrite (&vad, sizeof (Word16), 1, f_serial);
+        fwrite (&sp, sizeof (Word16), 1, f_serial);
+
+        if (reset_flag != 0)
+        {
+            reset_enc (); /*Bring the encoder, VAD and DTX to the home state */
+        }
+    }
+
+    return (0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/convolve.c	Wed Apr 03 05:31:37 2024 +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/src/copy.c	Wed Apr 03 05:31:37 2024 +0000
@@ -0,0 +1,28 @@
+/*************************************************************************
+ *
+ *   FUNCTION:   Copy
+ *
+ *   PURPOSE:   Copy vector x[] to y[]
+ *
+ *
+ *************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "count.h"
+
+void Copy (
+    Word16 x[],         /* (i)   : input vector   */
+    Word16 y[],         /* (o)   : output vector  */
+    Word16 L            /* (i)   : vector length  */
+)
+{
+    Word16 i;
+
+    for (i = 0; i < L; i++)
+    {
+        y[i] = x[i];            move16 (); 
+    }
+
+    return;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/count.c	Wed Apr 03 05:31:37 2024 +0000
@@ -0,0 +1,153 @@
+/***********************************************************************
+ *
+ *   This file contains functions for the automatic complexity calculation
+ *
+*************************************************************************/
+
+#include <stdio.h>
+#include "typedef.h"
+#include "count.h"
+
+/* Global counter variable for calculation of complexity weight */
+
+BASIC_OP counter;
+
+const BASIC_OP op_weight =
+{
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+    3, 3, 3, 4, 15, 18, 30, 1, 2, 1, 2, 2
+};
+
+/* local variable */
+
+#define NbFuncMax  1024
+
+static Word16 funcid, nbframe;
+static Word32 glob_wc, wc[NbFuncMax];
+static float total_wmops;
+
+static Word32 LastWOper;
+
+Word32 TotalWeightedOperation ()
+{
+    Word16 i;
+    Word32 tot, *ptr, *ptr2;
+
+    tot = 0;
+    ptr = (Word32 *) &counter;
+    ptr2 = (Word32 *) &op_weight;
+    for (i = 0; i < (sizeof (counter) / sizeof (Word32)); i++)
+
+    {
+        tot += ((*ptr++) * (*ptr2++));
+    }
+
+    return ((Word32) tot);
+}
+
+Word32 DeltaWeightedOperation ()
+{
+    Word32 NewWOper, delta;
+
+    NewWOper = TotalWeightedOperation ();
+    delta = NewWOper - LastWOper;
+    LastWOper = NewWOper;
+    return (delta);
+}
+
+void move16 (void)
+{
+    counter.DataMove16++;
+}
+
+void move32 (void)
+{
+    counter.DataMove32++;
+}
+
+void test (void)
+{
+    counter.Test++;
+}
+
+void logic16 (void)
+{
+    counter.Logic16++;
+}
+
+void logic32 (void)
+{
+    counter.Logic32++;
+}
+
+void Init_WMOPS_counter (void)
+{
+    Word16 i;
+
+    /* reset function weight operation counter variable */
+
+    for (i = 0; i < NbFuncMax; i++)
+        wc[i] = (Word32) 0;
+    glob_wc = 0;
+    nbframe = 0;
+    total_wmops = 0.0;
+
+}
+
+void Reset_WMOPS_counter (void)
+{
+    Word16 i;
+    Word32 *ptr;
+
+    ptr = (Word32 *) &counter;
+    for (i = 0; i < (sizeof (counter) / sizeof (Word32)); i++)
+
+    {
+        *ptr++ = 0;
+    }
+    LastWOper = 0;
+
+    funcid = 0;                 /* new frame, set function id to zero */
+}
+
+Word32 fwc (void)                      /* function worst case */
+{
+    Word32 tot;
+
+    tot = DeltaWeightedOperation ();
+    if (tot > wc[funcid])
+        wc[funcid] = tot;
+
+    funcid++;
+
+    return (tot);
+}
+
+void WMOPS_output (Word16 dtx_mode)
+{
+    Word16 i;
+    Word32 tot, tot_wc;
+
+    tot = TotalWeightedOperation ();
+    if (tot > glob_wc)
+        glob_wc = tot;
+
+    fprintf (stderr, "WMOPS=%.2f", ((float) tot) * 0.00005);
+
+    nbframe++;
+    total_wmops += ((float) tot) * 0.00005;
+    fprintf (stderr, "  Average=%.2f", total_wmops / (float) nbframe);
+
+    fprintf (stderr, "  WorstCase=%.2f", ((float) glob_wc) * 0.00005);
+
+    /* Worst worst case printed only when not in DTX mode */
+    if (dtx_mode == 0)
+    {
+        tot_wc = 0L;
+        for (i = 0; i < funcid; i++)
+            tot_wc += wc[i];
+        fprintf (stderr, "  WorstWC=%.2f", ((float) tot_wc) * 0.00005);
+    }
+    fprintf (stderr, "\n");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/count.h	Wed Apr 03 05:31:37 2024 +0000
@@ -0,0 +1,61 @@
+/* Global counter variable for calculation of complexity weight */
+
+typedef struct
+{
+    Word32 add;        /* Complexity Weight of 1 */
+    Word32 sub;
+    Word32 abs_s;
+    Word32 shl;
+    Word32 shr;
+    Word32 extract_h;
+    Word32 extract_l;
+    Word32 mult;
+    Word32 L_mult;
+    Word32 negate;
+    Word32 round;
+    Word32 L_mac;
+    Word32 L_msu;
+    Word32 L_macNs;
+    Word32 L_msuNs;
+    Word32 L_add;      /* Complexity Weight of 2 */
+    Word32 L_sub;
+    Word32 L_add_c;
+    Word32 L_sub_c;
+    Word32 L_negate;
+    Word32 L_shl;
+    Word32 L_shr;
+    Word32 mult_r;
+    Word32 shr_r;
+    Word32 shift_r;
+    Word32 mac_r;
+    Word32 msu_r;
+    Word32 L_deposit_h;
+    Word32 L_deposit_l;
+    Word32 L_shr_r;    /* Complexity Weight of 3 */
+    Word32 L_shift_r;
+    Word32 L_abs;
+    Word32 L_sat;      /* Complexity Weight of 4 */
+    Word32 norm_s;     /* Complexity Weight of 15 */
+    Word32 div_s;      /* Complexity Weight of 18 */
+    Word32 norm_l;     /* Complexity Weight of 30 */
+    Word32 DataMove16; /* Complexity Weight of 1 */
+    Word32 DataMove32; /* Complexity Weight of 2 */
+    Word32 Logic16;    /* Complexity Weight of 1 */
+    Word32 Logic32;    /* Complexity Weight of 2 */
+    Word32 Test;       /* Complexity Weight of 2 */
+}
+BASIC_OP;
+
+Word32 TotalWeightedOperation (void);
+Word32 DeltaWeightedOperation (void);
+
+void Init_WMOPS_counter (void);
+void Reset_WMOPS_counter (void);
+void WMOPS_output (Word16 dtx_mode);
+Word32 fwc (void);
+
+void move16 (void);
+void move32 (void);
+void logic16 (void);
+void logic32 (void);
+void test (void);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/d1035pf.c	Wed Apr 03 05:31:37 2024 +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/src/d_gains.c	Wed Apr 03 05:31:37 2024 +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/src/d_homing.c	Wed Apr 03 05:31:37 2024 +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/src/d_homing.h	Wed Apr 03 05:31:37 2024 +0000
@@ -0,0 +1,20 @@
+/**************************************************************************
+ *
+ *   File Name:  d_homing.h
+ *
+ *   Purpose:   Contains the prototypes for all the functions of
+ *              decoder homing.
+ *
+ **************************************************************************/
+
+#define EHF_MASK 0x0008 /* Encoder Homing Frame pattern */
+
+#define D_HOMING
+
+/* Function Prototypes */
+
+Word16 decoder_homing_frame_test (Word16 parm[], Word16 nbr_of_params);
+
+void decoder_reset (void);
+
+void reset_dec (void);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/d_plsf_5.c	Wed Apr 03 05:31:37 2024 +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/src/dec_12k2.c	Wed Apr 03 05:31:37 2024 +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/src/dec_lag6.c	Wed Apr 03 05:31:37 2024 +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/src/decoder.c	Wed Apr 03 05:31:37 2024 +0000
@@ -0,0 +1,218 @@
+/***************************************************************************
+ *
+ *  FILE NAME:  decoder.c
+ *
+ *         Usage : decoder  bitstream_file  synth_file
+ *
+ *         Format for bitstream_file:
+ *           One word (2-byte) for bad frame indication (BFI) flag bit
+ *               0x0000 -> good frame;  0x0001 -> bad frame
+ *           244  words (2-byte) containing 244 bits.
+ *               Bit 0 = 0x0000 and Bit 1 = 0x0001
+ *           One word (2-byte) for ternary Silence Descriptor (SID) flag
+ *               0x0000 -> inactive (no detected speech activity);
+ *               0x0001 -> active
+ *           One word (2-byte) for Time Alignment Flag (TAF) bit
+ *               0x0000 -> inactive (no transmission of speech frames);
+ *               0x0001 -> active
+ *
+ *         Format for synth_file:
+ *           Synthesis is written to a binary file of 16 bits data.
+ *
+ ***************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "typedef.h"
+#include "n_stack.h"
+#include "basic_op.h"
+#include "sig_proc.h"
+#include "count.h"
+#include "codec.h"
+#include "cnst.h"
+#include "d_homing.h"
+
+
+/* These constants define the number of consecutive parameters
+   that function decoder_homing_frame_test() checks */
+
+#define WHOLE_FRAME 57
+#define TO_FIRST_SUBFRAME 18
+
+
+Word16 synth_buf[L_FRAME + M];
+
+/* L_FRAME, M, PRM_SIZE, AZ_SIZE, SERIAL_SIZE: defined in "cnst.h" */
+
+/*-----------------------------------------------------------------*
+ *             Global variables                                    *
+ *-----------------------------------------------------------------*/
+
+#if (WMOPS)
+Word16 dtx_mode = 0;
+
+#endif
+
+/*-----------------------------------------------------------------*
+ *            Main decoder routine                                 *
+ *-----------------------------------------------------------------*/
+
+int 
+main (int argc, char *argv[])
+{
+    Word16 *synth;              /* Synthesis                  */
+    Word16 parm[PRM_SIZE + 1];  /* Synthesis parameters       */
+    Word16 serial[SERIAL_SIZE+2];/* Serial stream              */
+    Word16 Az_dec[AZ_SIZE];     /* Decoded Az for post-filter */
+                                /* in 4 subframes, length= 44 */
+    Word16 i, frame, temp;
+    FILE *f_syn, *f_serial;
+
+    Word16 TAF, SID_flag;
+
+    Word16 reset_flag;
+    static Word16 reset_flag_old = 1;
+
+    proc_head ("Decoder");
+
+    /*-----------------------------------------------------------------*
+     *           Read passed arguments and open in/out files           *
+     *-----------------------------------------------------------------*/
+
+    if (argc != 3)
+    {
+        fprintf (stderr,
+                 "   Usage:\n\n   decoder  bitstream_file  synth_file\n");
+        fprintf (stderr, "\n");
+        exit (1);
+    }
+    /* Open file for synthesis and packed serial stream */
+
+    if ((f_serial = fopen (argv[1], "rb")) == NULL)
+    {
+        fprintf (stderr, "Input file '%s' does not exist !!\n", argv[1]);
+        exit (0);
+    }
+    else
+        fprintf (stderr, "Input bitstream file:   %s\n", argv[1]);
+
+    if ((f_syn = fopen (argv[2], "wb")) == NULL)
+    {
+        fprintf (stderr, "Cannot open file '%s' !!\n", argv[2]);
+        exit (0);
+    }
+    else
+        fprintf (stderr, "Synthesis speech file:   %s\n", argv[2]);
+
+    /*-----------------------------------------------------------------*
+     *           Initialization of decoder                             *
+     *-----------------------------------------------------------------*/
+
+    synth = synth_buf + M;
+
+    reset_dec (); /* Bring the decoder and receive DTX to the initial state */
+
+#if (WMOPS)
+    Init_WMOPS_counter ();
+#endif
+
+    /*-----------------------------------------------------------------*
+     *            Loop for each "L_FRAME" speech data                  *
+     *-----------------------------------------------------------------*/
+
+    frame = 0;
+
+    while (fread (serial, sizeof (Word16), 247, f_serial) == 247)
+    {
+#if (WMOPS)
+        fprintf (stderr, "frame=%d  ", ++frame);
+#else
+        fprintf (stderr, "\nframe=%d  ", ++frame);
+#endif
+
+#if (WMOPS)
+        Reset_WMOPS_counter (); /* reset WMOPS counter for the new frame */
+#endif
+
+        SID_flag = serial[245];         /* Receive SID flag */
+        TAF = serial[246];              /* Receive TAF flag */
+
+        Bits2prm_12k2 (serial, parm);   /* serial to parameters   */
+
+#if (WMOPS)
+        fwc ();                         /* function worst case */
+#endif
+
+        if (parm[0] == 0)               /* BFI == 0, perform DHF check */
+        {
+            if (reset_flag_old == 1)    /* Check for second and further
+                                           successive DHF (to first subfr.) */
+            {
+                reset_flag = decoder_homing_frame_test (&parm[1],
+                                                        TO_FIRST_SUBFRAME);
+            }
+            else
+            {
+                reset_flag = 0;
+            }
+        }
+        else                          /* BFI==1, bypass DHF check (frame
+                                           is taken as not being a DHF) */
+        {
+            reset_flag = 0;
+        }
+
+        if ((reset_flag != 0) && (reset_flag_old != 0))
+        {
+            /* Force the output to be the encoder homing frame pattern */
+
+            for (i = 0; i < L_FRAME; i++)
+            {
+                synth[i] = EHF_MASK;
+            }
+        }
+        else
+        {
+            Decoder_12k2 (parm, synth, Az_dec, TAF, SID_flag);/* Synthesis */
+
+            Post_Filter (synth, Az_dec);                      /* Post-filter */
+#if (WMOPS)
+            fwc ();             /* function worst case */
+#endif
+
+            for (i = 0; i < L_FRAME; i++) 
+                /* Upscale the 15 bit linear PCM to 16 bits,
+                   then truncate to 13 bits */
+            {
+                temp = shl (synth[i], 1);
+                synth[i] = temp & 0xfff8;       logic16 (); move16 (); 
+            }
+
+#if (WMOPS)
+            fwc ();                             /* function worst case */
+#endif
+
+#if (WMOPS)
+            WMOPS_output (dtx_mode);/* output WMOPS values for current frame */
+#endif
+        }                       /* else */
+
+        fwrite (synth, sizeof (Word16), L_FRAME, f_syn);
+
+        /* BFI == 0, perform check for first DHF (whole frame) */
+        if ((parm[0] == 0) && (reset_flag_old == 0))
+        {
+            reset_flag = decoder_homing_frame_test (&parm[1], WHOLE_FRAME);
+        }
+
+        if (reset_flag != 0)
+        {
+            /* Bring the decoder and receive DTX to the home state */
+            reset_dec ();
+        }
+        reset_flag_old = reset_flag;
+
+    }                           /* while */
+
+    return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/dtx.c	Wed Apr 03 05:31:37 2024 +0000
@@ -0,0 +1,1293 @@
+/***************************************************************************
+ *
+ *   File Name: dtx.c
+ *
+ *   Purpose:   Contains functions for performing DTX operation and comfort
+ *              noise generation.
+ *
+ *     Below is a listing of all the functions appearing in the file.
+ *     The functions are arranged according to their purpose.  Under
+ *     each heading, the ordering is hierarchical.
+ *
+ *     Resetting of static variables of TX DTX:
+ *       reset_tx_dtx()
+ *     Resetting of static variables of RX DTX:
+ *       reset_rx_dtx()
+ *
+ *     TX DTX handler (called by the speech encoder):
+ *       tx_dtx()
+ *     RX DTX handler (called by the speech decoder):
+ *       rx_dtx()
+ *     Encoding of comfort noise parameters into SID frame:
+ *       CN_encoding()
+ *     Encoding of SID codeword into SID frame:
+ *       sid_codeword_encoding()
+ *     Detecting of SID codeword from a frame:
+ *       sid_frame_detection()
+ *     Update the LSF parameter history:
+ *       update_lsf_history()
+ *     Update the reference LSF parameter vector:
+ *       update_lsf_p_CN()
+ *     Compute the averaged LSF parameter vector:
+ *       aver_lsf_history()
+ *     Update the fixed codebook gain parameter history of the encoder:
+ *       update_gain_code_history_tx()
+ *     Update the fixed codebook gain parameter history of the decoder:
+ *       update_gain_code_history_rx()
+ *     Compute the unquantized fixed codebook gain:
+ *       compute_CN_excitation_gain()
+ *     Update the reference fixed codebook gain:
+ *       update_gcode0_CN()
+ *     Compute the averaged fixed codebook gain:
+ *       aver_gain_code_history()
+ *     Compute the comfort noise fixed codebook excitation:
+ *       build_CN_code()
+ *       Generate a random integer value:
+ *         pseudonoise()
+ *     Interpolate a comfort noise parameter value over the comfort noise
+ *       update period:
+ *       interpolate_CN_param()
+ *     Interpolate comfort noise LSF pparameter values over the comfort
+ *       noise update period:
+ *       interpolate_CN_lsf()
+ *         interpolate_CN_param()
+ *
+ **************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "cnst.h"
+#include "sig_proc.h"
+#include "count.h"
+#include "dtx.h"
+
+/* Inverse values of DTX hangover period and DTX hangover period + 1 */
+
+#define INV_DTX_HANGOVER (0x7fff / DTX_HANGOVER)
+#define INV_DTX_HANGOVER_P1 (0x7fff / (DTX_HANGOVER+1))
+
+#define NB_PULSE 10 /* Number of pulses in fixed codebook excitation */
+
+/* SID frame classification thresholds */
+
+#define VALID_SID_THRESH 2
+#define INVALID_SID_THRESH 16
+
+/* Constant DTX_ELAPSED_THRESHOLD is used as threshold for allowing
+   SID frame updating without hangover period in case when elapsed
+   time measured from previous SID update is below 24 */
+
+#define DTX_ELAPSED_THRESHOLD (24 + DTX_HANGOVER - 1)
+
+/* Index map for encoding and detecting SID codeword */
+
+static const Word16 SID_codeword_bit_idx[95] =
+{
+     45,  46,  48,  49,  50,  51,  52,  53,  54,  55,
+     56,  57,  58,  59,  60,  61,  62,  63,  64,  65,
+     66,  67,  68,  94,  95,  96,  98,  99, 100, 101,
+    102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
+    112, 113, 114, 115, 116, 117, 118, 148, 149, 150,
+    151, 152, 153, 154, 155, 156, 157, 158, 159, 160,
+    161, 162, 163, 164, 165, 166, 167, 168, 169, 170,
+    171, 196, 197, 198, 199, 200, 201, 202, 203, 204,
+    205, 206, 207, 208, 209, 212, 213, 214, 215, 216,
+    217, 218, 219, 220, 221
+};
+
+Word16 txdtx_ctrl;              /* Encoder DTX control word                */
+Word16 rxdtx_ctrl;              /* Decoder DTX control word                */
+Word16 CN_excitation_gain;      /* Unquantized fixed codebook gain         */
+Word32 L_pn_seed_tx;            /* PN generator seed (encoder)             */
+Word32 L_pn_seed_rx;            /* PN generator seed (decoder)             */
+Word16 rx_dtx_state;            /* State of comfort noise insertion period */
+
+static Word16 txdtx_hangover;   /* Length of hangover period (VAD=0, SP=1) */
+static Word16 rxdtx_aver_period;/* Length of hangover period (VAD=0, SP=1) */
+static Word16 txdtx_N_elapsed;  /* Measured time from previous SID frame   */
+static Word16 rxdtx_N_elapsed;  /* Measured time from previous SID frame   */
+static Word16 old_CN_mem_tx[6]; /* The most recent CN parameters are stored*/
+static Word16 prev_SID_frames_lost; /* Counter for lost SID frames         */
+static Word16 buf_p_tx;         /* Circular buffer pointer for gain code 
+                                   history  update in tx                   */
+static Word16 buf_p_rx;         /* Circular buffer pointer for gain code 
+                                   history update in rx                    */
+
+Word16 lsf_old_tx[DTX_HANGOVER][M]; /* Comfort noise LSF averaging buffer  */
+Word16 lsf_old_rx[DTX_HANGOVER][M]; /* Comfort noise LSF averaging buffer  */
+
+Word16 gain_code_old_tx[4 * DTX_HANGOVER]; /* Comfort noise gain averaging 
+                                              buffer                       */
+Word16 gain_code_old_rx[4 * DTX_HANGOVER]; /* Comfort noise gain averaging 
+                                              buffer                       */
+
+/*************************************************************************
+ *
+ *   FUNCTION NAME: reset_tx_dtx
+ *
+ *   PURPOSE:  Resets the static variables of the TX DTX handler to their
+ *             initial values
+ *
+ *************************************************************************/
+
+void reset_tx_dtx ()
+{
+    Word16 i;
+
+    /* suppose infinitely long speech period before start */
+
+    txdtx_hangover = DTX_HANGOVER;
+    txdtx_N_elapsed = 0x7fff;
+    txdtx_ctrl = TX_SP_FLAG | TX_VAD_FLAG;
+
+    for (i = 0; i < 6; i++)
+    {
+        old_CN_mem_tx[i] = 0;
+    }
+
+    for (i = 0; i < DTX_HANGOVER; i++)
+    {
+        lsf_old_tx[i][0] = 1384;
+        lsf_old_tx[i][1] = 2077;
+        lsf_old_tx[i][2] = 3420;
+        lsf_old_tx[i][3] = 5108;
+        lsf_old_tx[i][4] = 6742;
+        lsf_old_tx[i][5] = 8122;
+        lsf_old_tx[i][6] = 9863;
+        lsf_old_tx[i][7] = 11092;
+        lsf_old_tx[i][8] = 12714;
+        lsf_old_tx[i][9] = 13701;
+    }
+
+    for (i = 0; i < 4 * DTX_HANGOVER; i++)
+    {
+        gain_code_old_tx[i] = 0;
+    }
+
+    L_pn_seed_tx = PN_INITIAL_SEED;
+
+    buf_p_tx = 0;
+    return;
+}
+
+/*************************************************************************
+ *
+ *   FUNCTION NAME: reset_rx_dtx
+ *
+ *   PURPOSE:  Resets the static variables of the RX DTX handler to their
+ *             initial values
+ *
+ *************************************************************************/
+
+void reset_rx_dtx ()
+{
+    Word16 i;
+
+    /* suppose infinitely long speech period before start */
+
+    rxdtx_aver_period = DTX_HANGOVER;
+    rxdtx_N_elapsed = 0x7fff;
+    rxdtx_ctrl = RX_SP_FLAG;
+
+    for (i = 0; i < DTX_HANGOVER; i++)
+    {
+        lsf_old_rx[i][0] = 1384;
+        lsf_old_rx[i][1] = 2077;
+        lsf_old_rx[i][2] = 3420;
+        lsf_old_rx[i][3] = 5108;
+        lsf_old_rx[i][4] = 6742;
+        lsf_old_rx[i][5] = 8122;
+        lsf_old_rx[i][6] = 9863;
+        lsf_old_rx[i][7] = 11092;
+        lsf_old_rx[i][8] = 12714;
+        lsf_old_rx[i][9] = 13701;
+    }
+
+    for (i = 0; i < 4 * DTX_HANGOVER; i++)
+    {
+        gain_code_old_rx[i] = 0;
+    }
+
+    L_pn_seed_rx = PN_INITIAL_SEED;
+    rx_dtx_state = CN_INT_PERIOD - 1;
+
+    prev_SID_frames_lost = 0;
+    buf_p_rx = 0;
+
+    return;
+}
+
+/*************************************************************************
+ *
+ *   FUNCTION NAME: tx_dtx
+ *
+ *   PURPOSE: DTX handler of the speech encoder. Determines when to add
+ *            the hangover period to the end of the speech burst, and
+ *            also determines when to use old SID parameters, and when
+ *            to update the SID parameters. This function also initializes
+ *            the pseudo noise generator shift register.
+ *
+ *            Operation of the TX DTX handler is based on the VAD flag
+ *            given as input from the speech encoder.
+ *
+ *   INPUTS:      VAD_flag      Voice activity decision
+ *                *txdtx_ctrl   Old encoder DTX control word
+ *
+ *   OUTPUTS:     *txdtx_ctrl   Updated encoder DTX control word
+ *                L_pn_seed_tx  Initialized pseudo noise generator shift
+ *                              register (global variable)
+ *
+ *   RETURN VALUE: none
+ *
+ *************************************************************************/
+
+void tx_dtx (
+    Word16 VAD_flag,
+    Word16 *txdtx_ctrl
+)
+{
+
+    /* N_elapsed (frames since last SID update) is incremented. If SID
+       is updated N_elapsed is cleared later in this function */
+
+    txdtx_N_elapsed = add (txdtx_N_elapsed, 1);
+
+    /* If voice activity was detected, reset hangover counter */
+
+    test (); 
+    if (sub (VAD_flag, 1) == 0)
+    {
+        txdtx_hangover = DTX_HANGOVER;          move16 (); 
+        *txdtx_ctrl = TX_SP_FLAG | TX_VAD_FLAG; move16 (); logic16 (); 
+    }
+    else
+    {
+        test (); 
+        if (txdtx_hangover == 0)
+        {
+            /* Hangover period is over, SID should be updated */
+
+            txdtx_N_elapsed = 0;                move16 (); 
+
+            /* Check if this is the first frame after hangover period */
+            test (); logic16 (); 
+            if ((*txdtx_ctrl & TX_HANGOVER_ACTIVE) != 0)
+            {
+                *txdtx_ctrl = TX_PREV_HANGOVER_ACTIVE
+                    | TX_SID_UPDATE;            move16 (); logic16 (); 
+                L_pn_seed_tx = PN_INITIAL_SEED; move32 (); 
+            }
+            else
+            {
+                *txdtx_ctrl = TX_SID_UPDATE;    move16 (); 
+            }
+        }
+        else
+        {
+            /* Hangover period is not over, update hangover counter */
+            txdtx_hangover = sub (txdtx_hangover, 1);
+
+            /* Check if elapsed time from last SID update is greater than
+               threshold. If not, set SP=0 (although hangover period is not
+               over) and use old SID parameters for new SID frame.
+               N_elapsed counter must be summed with hangover counter in order
+               to avoid erroneus SP=1 decision in case when N_elapsed is grown
+               bigger than threshold and hangover period is still active */
+
+            test (); 
+            if (sub (add (txdtx_N_elapsed, txdtx_hangover),
+                     DTX_ELAPSED_THRESHOLD) < 0)
+            {
+                /* old SID frame should be used */
+                *txdtx_ctrl = TX_USE_OLD_SID;   move16 (); 
+            }
+            else
+            {
+                test (); logic16 (); 
+                if ((*txdtx_ctrl & TX_HANGOVER_ACTIVE) != 0)
+                {
+                    *txdtx_ctrl = TX_PREV_HANGOVER_ACTIVE
+                        | TX_HANGOVER_ACTIVE
+                        | TX_SP_FLAG;   move16 (); logic16 (); logic16 (); 
+                }
+                else
+                {
+                    *txdtx_ctrl = TX_HANGOVER_ACTIVE
+                        | TX_SP_FLAG;           move16 (); logic16 (); 
+                }
+            }
+        }
+    }
+
+    return;
+}
+
+/*************************************************************************
+ *
+ *   FUNCTION NAME: rx_dtx
+ *
+ *   PURPOSE: DTX handler of the speech decoder. Determines when to update
+ *            the reference comfort noise parameters (LSF and gain) at the
+ *            end of the speech burst. Also classifies the incoming frames
+ *            according to SID flag and BFI flag
+ *            and determines when the transmission is active during comfort
+ *            noise insertion. This function also initializes the pseudo
+ *            noise generator shift register.
+ *
+ *            Operation of the RX DTX handler is based on measuring the
+ *            lengths of speech bursts and the lengths of the pauses between
+ *            speech bursts to determine when there exists a hangover period
+ *            at the end of a speech burst. The idea is to keep in sync with
+ *            the TX DTX handler to be able to update the reference comfort
+ *            noise parameters at the same time instances.
+ *
+ *   INPUTS:      *rxdtx_ctrl   Old decoder DTX control word
+ *                TAF           Time alignment flag
+ *                bfi           Bad frame indicator flag
+ *                SID_flag      Silence descriptor flag
+ *
+ *   OUTPUTS:     *rxdtx_ctrl   Updated decoder DTX control word
+ *                rx_dtx_state  Updated state of comfort noise interpolation
+ *                              period (global variable)
+ *                L_pn_seed_rx  Initialized pseudo noise generator shift
+ *                              register (global variable)
+ *
+ *   RETURN VALUE: none
+ *
+ *************************************************************************/
+
+void rx_dtx (
+    Word16 *rxdtx_ctrl,
+    Word16 TAF,
+    Word16 bfi,
+    Word16 SID_flag
+)
+{
+    Word16 frame_type;
+
+    /* Frame classification according to bfi-flag and ternary-valued
+       SID flag. The frames between SID updates (not actually trans-
+       mitted) are also classified here; they will be discarded later
+       and provided with "NO TRANSMISSION"-flag */
+
+    test (); test (); 
+    test (); test (); 
+    test (); test (); 
+    if ((sub (SID_flag, 2) == 0) && (bfi == 0))
+    {
+        frame_type = VALID_SID_FRAME;                   move16 (); 
+    }
+    else if ((SID_flag == 0) && (bfi == 0))
+    {
+        frame_type = GOOD_SPEECH_FRAME;                 move16 (); 
+    }
+    else if ((SID_flag == 0) && (bfi != 0))
+    {
+        frame_type = UNUSABLE_FRAME;                    move16 (); 
+    }
+    else
+    {
+        frame_type = INVALID_SID_FRAME;                 move16 (); 
+    }
+
+    /* Update of decoder state */
+    /* Previous frame was classified as a speech frame */
+    test (); logic16 (); 
+    if ((*rxdtx_ctrl & RX_SP_FLAG) != 0)
+    {
+        test (); test (); test (); test (); 
+        if (sub (frame_type, VALID_SID_FRAME) == 0)
+        {
+            *rxdtx_ctrl = RX_FIRST_SID_UPDATE;          move16 (); 
+        }
+        else if (sub (frame_type, INVALID_SID_FRAME) == 0)
+        {
+            *rxdtx_ctrl = RX_FIRST_SID_UPDATE
+                        | RX_INVALID_SID_FRAME; move16 (); logic16();
+        }
+        else if (sub (frame_type, UNUSABLE_FRAME) == 0)
+        {
+            *rxdtx_ctrl = RX_SP_FLAG;                   move16 (); 
+        }
+        else if (sub (frame_type, GOOD_SPEECH_FRAME) == 0)
+        {
+            *rxdtx_ctrl = RX_SP_FLAG;                   move16 (); 
+        }
+    }
+    else
+    {
+        test (); test (); test (); test (); 
+        if (sub (frame_type, VALID_SID_FRAME) == 0)
+        {
+            *rxdtx_ctrl = RX_CONT_SID_UPDATE;       move16 (); 
+        }
+        else if (sub (frame_type, INVALID_SID_FRAME) == 0)
+        {
+            *rxdtx_ctrl = RX_CONT_SID_UPDATE
+                        | RX_INVALID_SID_FRAME;     move16 (); logic16 ();
+        }
+        else if (sub (frame_type, UNUSABLE_FRAME) == 0)
+        {
+            *rxdtx_ctrl = RX_CNI_BFI;               move16 (); 
+        }
+        else if (sub (frame_type, GOOD_SPEECH_FRAME) == 0)
+        {
+            /* If the previous frame (during CNI period) was muted,
+               raise the RX_PREV_DTX_MUTING flag */
+            test (); logic16 ();
+            if ((*rxdtx_ctrl & RX_DTX_MUTING) != 0)
+            {
+                *rxdtx_ctrl = RX_SP_FLAG | RX_FIRST_SP_FLAG
+                            | RX_PREV_DTX_MUTING; move16 (); logic16 ();
+                                                  logic16 ();
+            }
+            else
+            {
+                *rxdtx_ctrl = RX_SP_FLAG | RX_FIRST_SP_FLAG; move16 ();
+                                                             logic16 ();
+            }
+        }
+    }
+
+
+    test ();  logic16 ();
+    if ((*rxdtx_ctrl & RX_SP_FLAG) != 0)
+    {
+        prev_SID_frames_lost = 0;                       move16 ();
+        rx_dtx_state = CN_INT_PERIOD - 1;               move16 (); 
+    }
+    else
+    {
+        /* First SID frame */
+        test ();  logic16 ();
+        if ((*rxdtx_ctrl & RX_FIRST_SID_UPDATE) != 0)
+        {
+            prev_SID_frames_lost = 0;                   move16 ();
+            rx_dtx_state = CN_INT_PERIOD - 1;           move16 (); 
+        }
+
+        /* SID frame detected, but not the first SID */
+        test ();  logic16 ();
+        if ((*rxdtx_ctrl & RX_CONT_SID_UPDATE) != 0)
+        {
+            prev_SID_frames_lost = 0;                   move16 ();
+
+            test (); test ();
+            if (sub (frame_type, VALID_SID_FRAME) == 0)
+            {
+                rx_dtx_state = 0;                       move16 ();
+            }
+            else if (sub (frame_type, INVALID_SID_FRAME) == 0)
+            {
+                test ();
+                if (sub(rx_dtx_state, (CN_INT_PERIOD - 1)) < 0)
+                {
+                    rx_dtx_state = add(rx_dtx_state, 1); move16 ();
+                }
+            }
+        }
+
+        /* Bad frame received in CNI mode */
+        test ();  logic16 ();
+        if ((*rxdtx_ctrl & RX_CNI_BFI) != 0)
+        {
+            test ();
+            if (sub (rx_dtx_state, (CN_INT_PERIOD - 1)) < 0)
+            {
+                rx_dtx_state = add (rx_dtx_state, 1);   move16 ();
+            }
+
+            /* If an unusable frame is received during CNI period
+               when TAF == 1, the frame is classified as a lost
+               SID frame */
+            test ();
+            if (sub (TAF, 1) == 0)
+            {
+                *rxdtx_ctrl = *rxdtx_ctrl | RX_LOST_SID_FRAME;
+                                         move16 ();  logic16 ();
+                prev_SID_frames_lost = add (prev_SID_frames_lost, 1);
+            }
+            else /* No transmission occurred */
+            {
+                *rxdtx_ctrl = *rxdtx_ctrl | RX_NO_TRANSMISSION;
+                                         move16 ();  logic16 ();
+            }
+
+            test ();
+            if (sub (prev_SID_frames_lost, 1) > 0)
+            {
+                *rxdtx_ctrl = *rxdtx_ctrl | RX_DTX_MUTING;
+                                         move16 ();  logic16 ();
+            }
+        }
+    }
+
+    /* N_elapsed (frames since last SID update) is incremented. If SID
+       is updated N_elapsed is cleared later in this function */
+
+    rxdtx_N_elapsed = add (rxdtx_N_elapsed, 1);
+
+    test (); logic16 (); 
+    if ((*rxdtx_ctrl & RX_SP_FLAG) != 0)
+    {
+        rxdtx_aver_period = DTX_HANGOVER;               move16 (); 
+    }
+    else
+    {
+        test (); test (); 
+        if (sub (rxdtx_N_elapsed, DTX_ELAPSED_THRESHOLD) > 0)
+        {
+            *rxdtx_ctrl |= RX_UPD_SID_QUANT_MEM;        move16 (); logic16 (); 
+            rxdtx_N_elapsed = 0;                        move16 (); 
+            rxdtx_aver_period = 0;                      move16 (); 
+            L_pn_seed_rx = PN_INITIAL_SEED;             move32 (); 
+        }
+        else if (rxdtx_aver_period == 0)
+        {
+            rxdtx_N_elapsed = 0;                        move16 (); 
+        }
+        else
+        {
+            rxdtx_aver_period = sub (rxdtx_aver_period, 1);
+        }
+    }
+
+    return;
+}
+
+/*************************************************************************
+ *
+ *   FUNCTION NAME: CN_encoding
+ *
+ *   PURPOSE:  Encoding of the comfort noise parameters into a SID frame.
+ *             Use old SID parameters if necessary. Set the parameter
+ *             indices not used by comfort noise parameters to zero.
+ *
+ *   INPUTS:      params[0..56]  Comfort noise parameter frame from the
+ *                               speech encoder
+ *                txdtx_ctrl     TX DTX handler control word
+ *
+ *   OUTPUTS:     params[0..56]  Comfort noise encoded parameter frame
+ *
+ *   RETURN VALUE: none
+ *
+ *************************************************************************/
+
+void CN_encoding (
+    Word16 params[],
+    Word16 txdtx_ctrl
+)
+{
+    Word16 i;
+
+    test (); logic16 (); 
+    if ((txdtx_ctrl & TX_SID_UPDATE) != 0)
+    {
+        /* Store new CN parameters in memory to be used later as old
+           CN parameters */
+
+        /* LPC parameter indices */
+        for (i = 0; i < 5; i++)
+        {
+            old_CN_mem_tx[i] = params[i];               move16 (); 
+        }
+        /* Codebook index computed in last subframe */
+        old_CN_mem_tx[5] = params[56];                  move16 (); 
+    }
+    test (); logic16 (); 
+    if ((txdtx_ctrl & TX_USE_OLD_SID) != 0)
+    {
+        /* Use old CN parameters previously stored in memory */
+        for (i = 0; i < 5; i++)
+        {
+            params[i] = old_CN_mem_tx[i];               move16 (); 
+        }
+        params[17] = old_CN_mem_tx[5];                  move16 (); 
+        params[30] = old_CN_mem_tx[5];                  move16 (); 
+        params[43] = old_CN_mem_tx[5];                  move16 (); 
+        params[56] = old_CN_mem_tx[5];                  move16 (); 
+    }
+    /* Set all the rest of the parameters to zero (SID codeword will
+       be written later) */
+    for (i = 0; i < 12; i++)
+    {
+        params[i + 5] = 0;                              move16 (); 
+        params[i + 18] = 0;                             move16 (); 
+        params[i + 31] = 0;                             move16 (); 
+        params[i + 44] = 0;                             move16 (); 
+    }
+
+    return;
+}
+
+/*************************************************************************
+ *
+ *   FUNCTION NAME: sid_codeword_encoding
+ *
+ *   PURPOSE:  Encoding of the SID codeword into the SID frame. The SID
+ *             codeword consists of 95 bits, all set to '1'.
+ *
+ *   INPUTS:      ser2[0..243]  Serial-mode speech parameter frame before
+ *                              writing SID codeword into it
+ *
+ *   OUTPUTS:     ser2[0..243]  Serial-mode speech parameter frame with
+ *                              SID codeword written into it
+ *
+ *   RETURN VALUE: none
+ *
+ *************************************************************************/
+
+void sid_codeword_encoding (
+    Word16 ser2[]
+)
+{
+    Word16 i;
+
+    for (i = 0; i < 95; i++)
+    {
+        ser2[SID_codeword_bit_idx[i]] = 1;              move16 (); 
+    }
+
+    return;
+}
+
+/*************************************************************************
+ *
+ *   FUNCTION NAME: sid_frame_detection
+ *
+ *   PURPOSE:  Detecting of SID codeword from a received frame. The frames
+ *             are classified into three categories based on how many bit
+ *             errors occur in the SID codeword:
+ *                 - VALID SID FRAME
+ *                 - INVALID SID FRAME
+ *                 - SPEECH FRAME
+ *
+ *   INPUTS:      ser2[0..243]  Received serial-mode speech parameter frame
+ *
+ *   OUTPUTS:     none
+ *
+ *   RETURN VALUE: Ternary-valued SID classification flag
+ *
+ *************************************************************************/
+
+Word16 sid_frame_detection (
+    Word16 ser2[]
+)
+{
+    Word16 i, nbr_errors, sid;
+
+    /* Search for bit errors in SID codeword */
+    nbr_errors = 0;                                     move16 (); 
+    for (i = 0; i < 95; i++)
+    {
+        test (); 
+        if (ser2[SID_codeword_bit_idx[i]] == 0)
+        {
+            nbr_errors = add (nbr_errors, 1);
+        }
+    }
+
+    /* Frame classification */
+    test (); test (); 
+    if (sub (nbr_errors, VALID_SID_THRESH) < 0)
+    {                                                   /* Valid SID frame */
+        sid = 2;                                        move16 (); 
+    }
+    else if (sub (nbr_errors, INVALID_SID_THRESH) < 0)
+    {                                                   /* Invalid SID frame */
+        sid = 1;                                        move16 (); 
+    }
+    else
+    {                                                   /* Speech frame */
+        sid = 0;                                        move16 (); 
+    }
+
+    return sid;
+}
+
+/*************************************************************************
+ *
+ *   FUNCTION NAME: update_lsf_history
+ *
+ *   PURPOSE: Update the LSF parameter history. The LSF parameters kept
+ *            in the buffer are used later for computing the reference
+ *            LSF parameter vector and the averaged LSF parameter vector.
+ *
+ *   INPUTS:      lsf1[0..9]    LSF vector of the 1st half of the frame
+ *                lsf2[0..9]    LSF vector of the 2nd half of the frame
+ *                lsf_old[0..DTX_HANGOVER-1][0..M-1]
+ *                              Old LSF history
+ *
+ *   OUTPUTS:     lsf_old[0..DTX_HANGOVER-1][0..M-1]
+ *                              Updated LSF history
+ *
+ *   RETURN VALUE: none
+ *
+ *************************************************************************/
+
+void update_lsf_history (
+    Word16 lsf1[M],
+    Word16 lsf2[M],
+    Word16 lsf_old[DTX_HANGOVER][M]
+)
+{
+    Word16 i, j, temp;
+
+    /* shift LSF data to make room for LSFs from current frame */
+    /* This can also be implemented by using circular buffering */
+
+    for (i = DTX_HANGOVER - 1; i > 0; i--)
+    {
+        for (j = 0; j < M; j++)
+        {
+            lsf_old[i][j] = lsf_old[i - 1][j];         move16 (); 
+        }
+    }
+
+    /* Store new LSF data to lsf_old buffer */
+
+    for (i = 0; i < M; i++)
+    {
+        temp = add (shr (lsf1[i], 1), shr (lsf2[i], 1));
+        lsf_old[0][i] = temp;                          move16 (); 
+    }
+
+    return;
+}
+
+/*************************************************************************
+ *
+ *   FUNCTION NAME: update_lsf_p_CN
+ *
+ *   PURPOSE: Update the reference LSF parameter vector. The reference
+ *            vector is computed by averaging the quantized LSF parameter
+ *            vectors which exist in the LSF parameter history.
+ *
+ *   INPUTS:      lsf_old[0..DTX_HANGOVER-1][0..M-1]
+ *                                 LSF parameter history
+ *
+ *   OUTPUTS:     lsf_p_CN[0..9]   Computed reference LSF parameter vector
+ *
+ *   RETURN VALUE: none
+ *
+ *************************************************************************/
+
+void update_lsf_p_CN (
+    Word16 lsf_old[DTX_HANGOVER][M],
+    Word16 lsf_p_CN[M]
+)
+{
+    Word16 i, j;
+    Word32 L_temp;
+
+    for (j = 0; j < M; j++)
+    {
+        L_temp = L_mult (INV_DTX_HANGOVER, lsf_old[0][j]);
+        for (i = 1; i < DTX_HANGOVER; i++)
+        {
+            L_temp = L_mac (L_temp, INV_DTX_HANGOVER, lsf_old[i][j]);
+        }
+        lsf_p_CN[j] = round (L_temp);                  move16 (); 
+    }
+
+    return;
+}
+
+/*************************************************************************
+ *
+ *   FUNCTION NAME: aver_lsf_history
+ *
+ *   PURPOSE: Compute the averaged LSF parameter vector. Computation is
+ *            performed by averaging the LSF parameter vectors which exist
+ *            in the LSF parameter history, together with the LSF
+ *            parameter vectors of the current frame.
+ *
+ *   INPUTS:      lsf_old[0..DTX_HANGOVER-1][0..M-1]
+ *                                   LSF parameter history
+ *                lsf1[0..M-1]       LSF vector of the 1st half of the frame
+ *                lsf2[0..M-1]       LSF vector of the 2nd half of the frame
+ *
+ *   OUTPUTS:     lsf_aver[0..M-1]   Averaged LSF parameter vector
+ *
+ *   RETURN VALUE: none
+ *
+ *************************************************************************/
+
+void aver_lsf_history (
+    Word16 lsf_old[DTX_HANGOVER][M],
+    Word16 lsf1[M],
+    Word16 lsf2[M],
+    Word16 lsf_aver[M]
+)
+{
+    Word16 i, j;
+    Word32 L_temp;
+
+    for (j = 0; j < M; j++)
+    {
+        L_temp = L_mult (0x3fff, lsf1[j]);
+        L_temp = L_mac (L_temp, 0x3fff, lsf2[j]);
+        L_temp = L_mult (INV_DTX_HANGOVER_P1, extract_h (L_temp));
+
+        for (i = 0; i < DTX_HANGOVER; i++)
+        {
+            L_temp = L_mac (L_temp, INV_DTX_HANGOVER_P1, lsf_old[i][j]);
+        }
+
+        lsf_aver[j] = extract_h (L_temp);              move16 (); 
+    }
+
+    return;
+}
+
+/*************************************************************************
+ *
+ *   FUNCTION NAME: update_gain_code_history_tx
+ *
+ *   PURPOSE: Update the fixed codebook gain parameter history of the
+ *            encoder. The fixed codebook gain parameters kept in the buffer
+ *            are used later for computing the reference fixed codebook
+ *            gain parameter value and the averaged fixed codebook gain
+ *            parameter value.
+ *
+ *   INPUTS:      new_gain_code   New fixed codebook gain value
+ *
+ *                gain_code_old_tx[0..4*DTX_HANGOVER-1]
+ *                                Old fixed codebook gain history of encoder
+ *
+ *   OUTPUTS:     gain_code_old_tx[0..4*DTX_HANGOVER-1]
+ *                                Updated fixed codebook gain history of encoder
+ *
+ *   RETURN VALUE: none
+ *
+ *************************************************************************/
+
+void update_gain_code_history_tx (
+    Word16 new_gain_code,
+    Word16 gain_code_old_tx[4 * DTX_HANGOVER]
+)
+{
+
+    /* Circular buffer */
+    gain_code_old_tx[buf_p_tx] = new_gain_code;        move16 (); 
+
+    test (); 
+    if (sub (buf_p_tx, (4 * DTX_HANGOVER - 1)) == 0)
+    {
+        buf_p_tx = 0;                                  move16 (); 
+    }
+    else
+    {
+        buf_p_tx = add (buf_p_tx, 1);
+    }
+
+    return;
+}
+
+/*************************************************************************
+ *
+ *   FUNCTION NAME: update_gain_code_history_rx
+ *
+ *   PURPOSE: Update the fixed codebook gain parameter history of the
+ *            decoder. The fixed codebook gain parameters kept in the buffer
+ *            are used later for computing the reference fixed codebook
+ *            gain parameter value.
+ *
+ *   INPUTS:      new_gain_code   New fixed codebook gain value
+ *
+ *                gain_code_old_tx[0..4*DTX_HANGOVER-1]
+ *                                Old fixed codebook gain history of decoder
+ *
+ *   OUTPUTS:     gain_code_old_tx[0..4*DTX_HANGOVER-1]
+ *                                Updated fixed codebk gain history of decoder
+ *
+ *   RETURN VALUE: none
+ *
+ *************************************************************************/
+
+void update_gain_code_history_rx (
+    Word16 new_gain_code,
+    Word16 gain_code_old_rx[4 * DTX_HANGOVER]
+)
+{
+
+    /* Circular buffer */
+    gain_code_old_rx[buf_p_rx] = new_gain_code;        move16 (); 
+
+    test (); 
+    if (sub (buf_p_rx, (4 * DTX_HANGOVER - 1)) == 0)
+    {
+        buf_p_rx = 0;                                  move16 (); 
+    }
+    else
+    {
+        buf_p_rx = add (buf_p_rx, 1);
+    }
+
+    return;
+}
+
+/*************************************************************************
+ *
+ *   FUNCTION NAME: compute_CN_excitation_gain
+ *
+ *   PURPOSE: Compute the unquantized fixed codebook gain. Computation is
+ *            based on the energy of the Linear Prediction residual signal.
+ *
+ *   INPUTS:      res2[0..39]   Linear Prediction residual signal
+ *
+ *   OUTPUTS:     none
+ *
+ *   RETURN VALUE: Unquantized fixed codebook gain
+ *
+ *************************************************************************/
+
+Word16 compute_CN_excitation_gain (
+    Word16 res2[L_SUBFR]
+)
+{
+    Word16 i, norm, norm1, temp, overfl;
+    Word32 L_temp;
+
+    /* Compute the energy of the LP residual signal */
+
+    norm = 0;                                          move16 (); 
+    do
+    {
+        overfl = 0;                                    move16 ();
+
+        L_temp = 0L;                                   move32 (); 
+        for (i = 0; i < L_SUBFR; i++)
+        {
+            temp = shr (res2[i], norm);
+            L_temp = L_mac (L_temp, temp, temp);
+        }
+
+        test (); 
+        if (L_sub (L_temp, MAX_32) == 0)
+        {
+            norm = add (norm, 1);
+            overfl = 1;                 move16 (); /* Set the overflow flag */
+        }
+        test (); 
+    }
+    while (overfl != 0);
+
+    L_temp = L_add (L_temp, 1L);             /* Avoid the case of all zeros */
+
+    /* Take the square root of the obtained energy value (sqroot is a 2nd
+       order Taylor series approximation) */
+
+    norm1 = norm_l (L_temp);
+    temp = extract_h (L_shl (L_temp, norm1));
+    L_temp = L_mult (temp, temp);
+    L_temp = L_sub (805306368L, L_shr (L_temp, 3));
+    L_temp = L_add (L_temp, L_mult (24576, temp));
+
+    temp = extract_h (L_temp);
+    test (); logic16 (); 
+    if ((norm1 & 0x0001) != 0)
+    {
+        temp = mult_r (temp, 23170);
+        norm1 = sub (norm1, 1);
+    }
+    /* Divide the result of sqroot operation by sqroot(10) */
+
+    temp = mult_r (temp, 10362);
+
+    /* Re-scale to get the final value */
+
+    norm1 = shr (norm1, 1);
+    norm1 = sub (norm1, norm);
+
+    test (); 
+    if (norm1 >= 0)
+    {
+        temp = shr (temp, norm1);
+    }
+    else
+    {
+        temp = shl (temp, abs_s (norm1));
+    }
+
+    return temp;
+}
+
+/*************************************************************************
+ *
+ *   FUNCTION NAME: update_gcode0_CN
+ *
+ *   PURPOSE: Update the reference fixed codebook gain parameter value.
+ *            The reference value is computed by averaging the quantized
+ *            fixed codebook gain parameter values which exist in the
+ *            fixed codebook gain parameter history.
+ *
+ *   INPUTS:      gain_code_old[0..4*DTX_HANGOVER-1]
+ *                              fixed codebook gain parameter history
+ *
+ *   OUTPUTS:     none
+ *
+ *   RETURN VALUE: Computed reference fixed codebook gain
+ *
+ *************************************************************************/
+
+Word16 update_gcode0_CN (
+    Word16 gain_code_old[4 * DTX_HANGOVER]
+)
+{
+    Word16 i, j;
+    Word32 L_temp, L_ret;
+
+    L_ret = 0L;                                        move32 (); 
+    for (i = 0; i < DTX_HANGOVER; i++)
+    {
+        L_temp = L_mult (0x1fff, gain_code_old[4 * i]);
+        for (j = 1; j < 4; j++)
+        {
+            L_temp = L_mac (L_temp, 0x1fff, gain_code_old[4 * i + j]);
+        }
+        L_ret = L_mac (L_ret, INV_DTX_HANGOVER, extract_h (L_temp));
+    }
+
+    return extract_h (L_ret);
+}
+
+/*************************************************************************
+ *
+ *   FUNCTION NAME: aver_gain_code_history
+ *
+ *   PURPOSE: Compute the averaged fixed codebook gain parameter value.
+ *            Computation is performed by averaging the fixed codebook
+ *            gain parameter values which exist in the fixed codebook
+ *            gain parameter history, together with the fixed codebook
+ *            gain parameter value of the current subframe.
+ *
+ *   INPUTS:      CN_excitation_gain
+ *                              Unquantized fixed codebook gain value
+ *                              of the current subframe
+ *                gain_code_old[0..4*DTX_HANGOVER-1]
+ *                              fixed codebook gain parameter history
+ *
+ *   OUTPUTS:     none
+ *
+ *   RETURN VALUE: Averaged fixed codebook gain value
+ *
+ *************************************************************************/
+
+Word16 aver_gain_code_history (
+    Word16 CN_excitation_gain,
+    Word16 gain_code_old[4 * DTX_HANGOVER]
+)
+{
+    Word16 i;
+    Word32 L_ret;
+
+    L_ret = L_mult (0x470, CN_excitation_gain);
+
+    for (i = 0; i < (4 * DTX_HANGOVER); i++)
+    {
+        L_ret = L_mac (L_ret, 0x470, gain_code_old[i]);
+    }
+    return extract_h (L_ret);
+}
+
+/*************************************************************************
+ *
+ *   FUNCTION NAME: build_CN_code
+ *
+ *   PURPOSE: Compute the comfort noise fixed codebook excitation. The
+ *            gains of the pulses are always +/-1.
+ *
+ *   INPUTS:      *seed         Old CN generator shift register state
+ *
+ *   OUTPUTS:     cod[0..39]    Generated comfort noise fixed codebook vector
+ *                *seed         Updated CN generator shift register state
+ *
+ *   RETURN VALUE: none
+ *
+ *************************************************************************/
+
+void build_CN_code (
+    Word16 cod[],
+    Word32 *seed
+)
+{
+    Word16 i, j, k;
+
+    for (i = 0; i < L_SUBFR; i++)
+    {
+        cod[i] = 0;                                    move16 (); 
+    }
+
+    for (k = 0; k < NB_PULSE; k++)
+    {
+        i = pseudonoise (seed, 2);      /* generate pulse position */
+        i = shr (extract_l (L_mult (i, 10)), 1);
+        i = add (i, k);
+
+        j = pseudonoise (seed, 1);      /* generate sign           */
+
+        test (); 
+        if (j > 0)
+        {
+            cod[i] = 4096;                             move16 (); 
+        }
+        else
+        {
+            cod[i] = -4096;                            move16 (); 
+        }
+    }
+
+    return;
+}
+
+/*************************************************************************
+ *
+ *   FUNCTION NAME: pseudonoise
+ *
+ *   PURPOSE: Generate a random integer value to use in comfort noise
+ *            generation. The algorithm uses polynomial x^31 + x^3 + 1
+ *            (length of PN sequence is 2^31 - 1).
+ *
+ *   INPUTS:      *shift_reg    Old CN generator shift register state
+ *
+ *
+ *   OUTPUTS:     *shift_reg    Updated CN generator shift register state
+ *
+ *   RETURN VALUE: Generated random integer value
+ *
+ *************************************************************************/
+
+Word16 pseudonoise (
+    Word32 *shift_reg,
+    Word16 no_bits
+)
+{
+    Word16 noise_bits, Sn, i;
+
+    noise_bits = 0;                                    move16 (); 
+    for (i = 0; i < no_bits; i++)
+    {
+        /* State n == 31 */
+        test (); logic32 (); 
+        if ((*shift_reg & 0x00000001L) != 0)
+        {
+            Sn = 1;                                    move16 (); 
+        }
+        else
+        {
+            Sn = 0;                                    move16 (); 
+        }
+
+        /* State n == 3 */
+        test (); logic32 (); 
+        if ((*shift_reg & 0x10000000L) != 0)
+        {
+            Sn = Sn ^ 1;                               logic16 (); 
+        }
+        else
+        {
+            Sn = Sn ^ 0;                               logic16 (); 
+        }
+
+        noise_bits = shl (noise_bits, 1);
+        noise_bits = noise_bits | (extract_l (*shift_reg) & 1);
+        logic16 (); logic16 (); 
+
+        *shift_reg = L_shr (*shift_reg, 1);            move32 (); 
+        test (); logic16 (); 
+        if (Sn & 1)
+        {
+            *shift_reg = *shift_reg | 0x40000000L;     move32 (); logic32 (); 
+        }
+    }
+
+    return noise_bits;
+}
+
+/*************************************************************************
+ *
+ *   FUNCTION NAME: interpolate_CN_param
+ *
+ *   PURPOSE: Interpolate a comfort noise parameter value over the comfort
+ *            noise update period.
+ *
+ *   INPUTS:      old_param     The older parameter of the interpolation
+ *                              (the endpoint the interpolation is started
+ *                              from)
+ *                new_param     The newer parameter of the interpolation
+ *                              (the endpoint the interpolation is ended to)
+ *                rx_dtx_state  State of the comfort noise insertion period
+ *
+ *   OUTPUTS:     none
+ *
+ *   RETURN VALUE: Interpolated CN parameter value
+ *
+ *************************************************************************/
+
+Word16 interpolate_CN_param (
+    Word16 old_param,
+    Word16 new_param,
+    Word16 rx_dtx_state
+)
+{
+    static const Word16 interp_factor[CN_INT_PERIOD] =
+    {
+        0x0555, 0x0aaa, 0x1000, 0x1555, 0x1aaa, 0x2000,
+        0x2555, 0x2aaa, 0x3000, 0x3555, 0x3aaa, 0x4000,
+        0x4555, 0x4aaa, 0x5000, 0x5555, 0x5aaa, 0x6000,
+        0x6555, 0x6aaa, 0x7000, 0x7555, 0x7aaa, 0x7fff};
+    Word16 temp;
+    Word32 L_temp;
+
+    L_temp = L_mult (interp_factor[rx_dtx_state], new_param);
+    temp = sub (0x7fff, interp_factor[rx_dtx_state]);
+    temp = add (temp, 1);
+    L_temp = L_mac (L_temp, temp, old_param);
+    temp = round (L_temp);
+
+    return temp;
+}
+
+/*************************************************************************
+ *
+ *   FUNCTION NAME:  interpolate_CN_lsf
+ *
+ *   PURPOSE: Interpolate comfort noise LSF parameter vector over the comfort
+ *            noise update period.
+ *
+ *   INPUTS:      lsf_old_CN[0..9]
+ *                              The older LSF parameter vector of the
+ *                              interpolation (the endpoint the interpolation
+ *                              is started from)
+ *                lsf_new_CN[0..9]
+ *                              The newer LSF parameter vector of the
+ *                              interpolation (the endpoint the interpolation
+ *                              is ended to)
+ *                rx_dtx_state  State of the comfort noise insertion period
+ *
+ *   OUTPUTS:     lsf_interp_CN[0..9]
+ *                              Interpolated LSF parameter vector
+ *
+ *   RETURN VALUE: none
+ *
+ *************************************************************************/
+
+void interpolate_CN_lsf (
+    Word16 lsf_old_CN[M],
+    Word16 lsf_new_CN[M],
+    Word16 lsf_interp_CN[M],
+    Word16 rx_dtx_state
+)
+{
+    Word16 i;
+
+    for (i = 0; i < M; i++)
+    {
+        lsf_interp_CN[i] = interpolate_CN_param (lsf_old_CN[i],
+                                                 lsf_new_CN[i],
+                                                 rx_dtx_state); move16 (); 
+    }
+
+    return;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/dtx.h	Wed Apr 03 05:31:37 2024 +0000
@@ -0,0 +1,140 @@
+/***************************************************************************
+ *
+ *   File Name: dtx.h
+ *
+ *   Purpose:   Contains the prototypes for all the functions of DTX.
+ *              Also contains definitions of constants used in DTX functions.
+ *
+ **************************************************************************/
+
+#define PN_INITIAL_SEED 0x70816958L   /* Pseudo noise generator seed value  */
+
+#define CN_INT_PERIOD 24              /* Comfort noise interpolation period
+                                         (nbr of frames between successive
+                                         SID updates in the decoder) */
+
+#define DTX_HANGOVER 7                /* Period when SP=1 although VAD=0.
+                                         Used for comfort noise averaging */
+
+
+/* Frame classification constants */
+
+#define VALID_SID_FRAME          1
+#define INVALID_SID_FRAME        2
+#define GOOD_SPEECH_FRAME        3
+#define UNUSABLE_FRAME           4
+
+/* Encoder DTX control flags */
+
+#define TX_SP_FLAG               0x0001
+#define TX_VAD_FLAG              0x0002
+#define TX_HANGOVER_ACTIVE       0x0004
+#define TX_PREV_HANGOVER_ACTIVE  0x0008
+#define TX_SID_UPDATE            0x0010
+#define TX_USE_OLD_SID           0x0020
+
+/* Decoder DTX control flags */
+
+#define RX_SP_FLAG               0x0001
+#define RX_UPD_SID_QUANT_MEM     0x0002
+#define RX_FIRST_SID_UPDATE      0x0004
+#define RX_CONT_SID_UPDATE       0x0008
+#define RX_LOST_SID_FRAME        0x0010
+#define RX_INVALID_SID_FRAME     0x0020
+#define RX_NO_TRANSMISSION       0x0040
+#define RX_DTX_MUTING            0x0080
+#define RX_PREV_DTX_MUTING       0x0100
+#define RX_CNI_BFI               0x0200
+#define RX_FIRST_SP_FLAG         0x0400
+
+void reset_tx_dtx (void);       /* Reset tx dtx variables */
+void reset_rx_dtx (void);       /* Reset rx dtx variables */
+
+void tx_dtx (
+    Word16 VAD_flag,
+    Word16 *txdtx_ctrl
+);
+
+void rx_dtx (
+    Word16 *rxdtx_ctrl,
+    Word16 TAF,
+    Word16 bfi,
+    Word16 SID_flag
+);
+
+void CN_encoding (
+    Word16 params[],
+    Word16 txdtx_ctrl
+);
+
+void sid_codeword_encoding (
+    Word16 ser2[]
+);
+
+Word16 sid_frame_detection (
+    Word16 ser2[]
+);
+
+void update_lsf_history (
+    Word16 lsf1[M],
+    Word16 lsf2[M],
+    Word16 lsf_old[DTX_HANGOVER][M]
+);
+
+void update_lsf_p_CN (
+    Word16 lsf_old[DTX_HANGOVER][M],
+    Word16 lsf_p_CN[M]
+);
+
+void aver_lsf_history (
+    Word16 lsf_old[DTX_HANGOVER][M],
+    Word16 lsf1[M],
+    Word16 lsf2[M],
+    Word16 lsf_aver[M]
+);
+
+void update_gain_code_history_tx (
+    Word16 new_gain_code,
+    Word16 gain_code_old_tx[4 * DTX_HANGOVER]
+);
+
+void update_gain_code_history_rx (
+    Word16 new_gain_code,
+    Word16 gain_code_old_rx[4 * DTX_HANGOVER]
+);
+
+Word16 compute_CN_excitation_gain (
+    Word16 res2[L_SUBFR]
+);
+
+Word16 update_gcode0_CN (
+    Word16 gain_code_old_tx[4 * DTX_HANGOVER]
+);
+
+Word16 aver_gain_code_history (
+    Word16 CN_excitation_gain,
+    Word16 gain_code_old[4 * DTX_HANGOVER]
+);
+
+void build_CN_code (
+    Word16 cod[],
+    Word32 *seed
+);
+
+Word16 pseudonoise (
+    Word32 *shift_reg,
+    Word16 no_bits
+);
+
+Word16 interpolate_CN_param (
+    Word16 old_param,
+    Word16 new_param,
+    Word16 rx_dtx_state
+);
+
+void interpolate_CN_lsf (
+    Word16 lsf_old_CN[M],
+    Word16 lsf_new_CN[M],
+    Word16 lsf_interp_CN[M],
+    Word16 rx_dtx_state
+);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/e_homing.c	Wed Apr 03 05:31:37 2024 +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/src/e_homing.h	Wed Apr 03 05:31:37 2024 +0000
@@ -0,0 +1,18 @@
+/**************************************************************************
+ *
+ *   File Name:  e_homing.h
+ *
+ *   Purpose:   Contains the prototypes for all the functions of
+ *              encoder homing.
+ *
+ **************************************************************************/
+
+#define EHF_MASK 0x0008 /* Encoder Homing Frame pattern */
+
+/* Function Prototypes */
+
+Word16 encoder_homing_frame_test (Word16 input_frame[]);
+
+void encoder_reset (void);
+
+void reset_enc (void);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ed_iface.c	Wed Apr 03 05:31:37 2024 +0000
@@ -0,0 +1,312 @@
+/***************************************************************************
+ *
+ *     File Name: ed_iface.c
+ *
+ *     Purpose: Speech encoder/decoder interface device
+ *
+ *     This program transforms the output file format of the GSM Enhanced
+ *     Full Rate Encoder module consisting of:
+ *         * 244 speech parameter bits (see GSM TS 06.60)
+ *         *   1 voice activity flag VAD (see GSM TS 06.82)
+ *         *   1 speech flag SP (see GSM TS 06.81)
+ *
+ *     to the input file format of the GSM Enhanced Full Rate Decoder module
+ *     requiring:
+ *         *   1 channel condition flag BFI (see GSM TS 06.61, 05.05)
+ *         * 244 speech parameter bits (see GSM TS 06.60)
+ *         *   1 SID flag (2 bits) (see GSM TS 06.81, 05.05)
+ *         *   1 time alignment flag TAF (see GSM TS 06.81)
+ *
+ *     Between SID updates the speech parameters are replaced by random
+ *     values simulating an interrupted transmission on the air interface
+ *
+ *     Below is a listing of all the functions appearing in the file,
+ *     with a short description of their purpose.
+ *
+ *     Convert single frame from encoder output format to decoder
+ *     input format:
+ *       enc_dec_interface()
+ *     Receive single encoder output parameter frame:
+ *       encoder_interface()
+ *     Send single decoder input parameter frame:
+ *       decoder_interface()
+ *     Open file for binary read or write:
+ *       open_bin_file()
+ *     Set the speech parameters to random values:
+ *       random_parameters()
+ *
+ **************************************************************************/
+
+/***************************************************************************
+ *
+ *      Include-Files
+ *
+ **************************************************************************/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include "typedef.h"
+#include "cnst.h"
+#include "dtx.h"
+
+#define OPEN_WB  "wb"
+#define OPEN_RB  "rb"
+
+/***************************************************************************
+ *
+ *      Local function prototypes
+ *
+ **************************************************************************/
+
+static Word16 enc_dec_interface (FILE *infile, FILE *outfile);
+static Word16 encoder_interface (FILE *infile, Word16 serial_in_para[]);
+static Word16 decoder_interface (Word16 serial_out_para[], FILE *outfile);
+FILE *open_bin_file (char *name, char *mode);
+static void random_parameters (Word16 serial_params[]);
+
+/***************************************************************************
+ *
+ *      Local functions
+ *
+ **************************************************************************/
+
+static Word16 enc_dec_interface (FILE *infile, FILE *outfile)
+{
+
+#define SPEECH      1
+#define CNIFIRSTSID 2
+#define CNICONT     3
+#define VALIDSID    11
+#define GOODSPEECH  33
+
+    static Word16 decoding_mode = {SPEECH};
+    static Word16 TAF_count = {1};
+    Word16 serial_in_para[246], i, frame_type;
+    Word16 serial_out_para[247];
+ 
+    if (encoder_interface (infile, serial_in_para) != 0)
+    {
+        return (1);
+    }
+
+    /* Copy input parameters to output parameters */
+    /* ------------------------------------------ */
+    for (i = 0; i < 244; i++)
+    {
+        serial_out_para[i+1] = serial_in_para[i];
+    }
+
+    /* Set channel status (BFI) flag to zero */
+    /* --------------------------------------*/
+    serial_out_para[0] = 0;     /* BFI flag */
+
+    /* Evaluate SID flag                                  */
+    /* Function sid_frame_detection() is defined in dtx.c */
+    /* -------------------------------------------------- */
+    serial_out_para[245] = sid_frame_detection (&serial_out_para[1]);
+
+    /* Evaluate TAF flag */
+    /* ----------------- */
+    if (TAF_count == 0)
+    {
+        serial_out_para[246] = 1;
+    }
+    else
+    {
+        serial_out_para[246] = 0;
+    }
+
+    TAF_count = (TAF_count + 1) % 24;
+   
+    /* Frame classification:                                                */
+    /* Since the transmission is error free, the received frames are either */
+    /* valid speech or valid SID frames                                     */
+    /* -------------------------------------------------------------------- */
+    if (serial_out_para[245] == 2)
+    {
+        frame_type = VALIDSID;
+    }
+    else if (serial_out_para[245] == 0)
+    {
+        frame_type = GOODSPEECH;
+    }
+    else {
+        fprintf (stderr, "Error in SID detection\n");
+        return (1);
+    }
+
+    /* Update of decoder state */
+    /* ----------------------- */
+    if (decoding_mode == SPEECH) /* State of previous frame */
+    {
+        if (frame_type == VALIDSID)
+        {
+            decoding_mode = CNIFIRSTSID;
+        }
+        else if (frame_type == GOODSPEECH)
+        {
+            decoding_mode = SPEECH;
+        }
+    }
+    else  /* comfort noise insertion mode */
+    {
+        if (frame_type == VALIDSID)
+        {
+            decoding_mode = CNICONT;
+        }
+        else if (frame_type == GOODSPEECH)
+        {
+            decoding_mode = SPEECH;
+        }
+    }
+
+    /* Replace parameters by random data if in CNICONT-mode and TAF=0 */
+    /* -------------------------------------------------------------- */
+    if ((decoding_mode == CNICONT) && (serial_out_para[246] == 0))
+    {
+        random_parameters (&serial_out_para[1]);
+
+        /* Set flags such that an "unusable frame" is produced */
+        serial_out_para[0] = 1;       /* BFI flag */
+        serial_out_para[245] = 0;     /* SID flag */
+    }    
+
+    if (decoder_interface (serial_out_para, outfile) != 0)
+    {
+        fprintf (stderr, "Error writing File\n");
+        return (1);
+    }
+
+    return (0);
+}
+
+static Word16 encoder_interface (FILE *infile, Word16 serial_in_para[])
+{
+    size_t lgth_read = 0;    
+    Word16 ret;
+
+    lgth_read = fread (serial_in_para, sizeof (Word16), 246, infile);
+
+    if (lgth_read == 0)
+    {
+        ret = 1;
+    }
+    else
+    {
+        ret = 0;
+    }
+
+    return (ret);
+}
+
+static Word16 decoder_interface (Word16 serial_out_file[], FILE *outfile)
+{
+    size_t lgth_written;
+    Word16 ret;
+
+    lgth_written = fwrite (serial_out_file, sizeof (Word16), 247, outfile);
+
+    if (lgth_written == 247)
+    {
+        ret = 0;
+    }
+    else
+    {
+        ret = 1;
+    }
+
+    return (ret);
+}
+
+FILE *open_bin_file (char *name, char *mode)
+{
+    FILE *fp;
+
+    if (toupper (*mode) == 'W') /* Write access */
+    {
+        if ((fp = fopen (name, OPEN_WB)) == NULL)
+        { 
+            fprintf (stderr, "Can't open output file '%s'\n", name);
+            exit (1);
+        }
+    }
+    else /* Read access */
+    {
+        if ((fp = fopen (name, OPEN_RB)) == NULL)
+        { 
+            fprintf (stderr, "Can't open file '%s'\n", name);
+            exit (1);
+        }
+    }
+
+    return (fp);
+}
+
+static void random_parameters (Word16 serial_params[])
+{
+    static Word32 L_PN_seed = 0x321CEDE2L;
+    Word16 i;
+
+    /* Set the 244 speech parameter bits to random bit values */
+    /* Function pseudonoise() is defined in dtx.c             */
+    /*--------------------------------------------------------*/
+
+    for (i = 0; i < 244; i++)
+    {
+        serial_params[i] = pseudonoise (&L_PN_seed, 1);
+    }
+
+    return;
+}
+
+/****************************************************************************
+ *
+ *          Main program of the encoder/decoder interface device
+ *
+ ***************************************************************************/
+
+int main (int argc, char *argv[])
+{
+    FILE *infile, *outfile;
+    Word16 i;
+
+    if (argc != 3)
+    {
+        fprintf (stderr, "\n   Usage:\n\n   ed_iface  input  output\n\n");
+        return (1);
+    }
+
+    fprintf (stderr, "  ____________________________________________________\n");
+    fprintf (stderr, " |                                                    |\n");
+    fprintf (stderr, " |       Speech Encoder-Decoder Interface Device      |\n");
+    fprintf (stderr, " |                                                    |\n");
+    fprintf (stderr, " |                         for                        |\n");
+    fprintf (stderr, " |                                                    |\n");
+    fprintf (stderr, " |   GSM Enhanced Full Rate Speech Codec Simulation   |\n");
+    fprintf (stderr, " |____________________________________________________|\n\n");
+
+    fprintf (stderr, "    Input File       : %s\n", argv[1]);
+    fprintf (stderr, "    Output File      : %s\n\n", argv[2]);
+
+    infile  = open_bin_file (argv[1], "r");
+    outfile = open_bin_file (argv[2], "w");
+
+    i = 0;
+    while (enc_dec_interface (infile, outfile) == 0)
+    {
+        if ((i % 50) == 0)
+        {
+            fprintf (stderr, "\r    %d", i);
+        }
+        i++;
+    }
+    fprintf (stderr, "\r    %d", i);
+
+    fclose (infile);
+    fclose (outfile);
+
+    fprintf (stderr, " Frame%s processed      \n\n", ( i != 1 ) ? "s" : "");
+
+    return (0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/enc_lag6.c	Wed Apr 03 05:31:37 2024 +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/src/g_code.c	Wed Apr 03 05:31:37 2024 +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/src/g_pitch.c	Wed Apr 03 05:31:37 2024 +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/src/gains_tb.h	Wed Apr 03 05:31:37 2024 +0000
@@ -0,0 +1,21 @@
+/*-----------------------------------------------------------------------*
+ *  Scalar quantization tables of the pitch gain and the codebook gain.  *
+ *-----------------------------------------------------------------------*/
+
+#define NB_QUA_PITCH 16
+
+static const Word16 qua_gain_pitch[NB_QUA_PITCH] =
+{
+    0, 3277, 6556, 8192, 9830, 11469, 12288, 13107,
+    13926, 14746, 15565, 16384, 17203, 18022, 18842, 19661
+};
+
+#define NB_QUA_CODE 32
+
+static const Word16 qua_gain_code[NB_QUA_CODE] =
+{
+    159, 206, 268, 349, 419, 482, 554, 637,
+    733, 842, 969, 1114, 1281, 1473, 1694, 1948,
+    2241, 2577, 2963, 3408, 3919, 4507, 5183, 5960,
+    6855, 7883, 9065, 10425, 12510, 16263, 21142, 27485
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/grid.tab	Wed Apr 03 05:31:37 2024 +0000
@@ -0,0 +1,26 @@
+/*-------------------------------------------------------------*
+ *  Table for az_lsf()                                         *
+ *                                                             *
+ * grid[0] = 1.0;                                              *
+ * grid[grid_points+1] = -1.0;                                 *
+ * for (i = 1; i < grid_points; i++)                           *
+ *   grid[i] = cos((6.283185307*i)/(2.0*grid_points));         *
+ *                                                             *
+ *-------------------------------------------------------------*/
+
+#define grid_points 60
+
+static const Word16 grid[grid_points + 1] =
+{
+    32760, 32723, 32588, 32364, 32051, 31651,
+    31164, 30591, 29935, 29196, 28377, 27481,
+    26509, 25465, 24351, 23170, 21926, 20621,
+    19260, 17846, 16384, 14876, 13327, 11743,
+    10125, 8480, 6812, 5126, 3425, 1714,
+    0, -1714, -3425, -5126, -6812, -8480,
+    -10125, -11743, -13327, -14876, -16384, -17846,
+    -19260, -20621, -21926, -23170, -24351, -25465,
+    -26509, -27481, -28377, -29196, -29935, -30591,
+    -31164, -31651, -32051, -32364, -32588, -32723,
+    -32760
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/int_lpc.c	Wed Apr 03 05:31:37 2024 +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/src/inter_6.c	Wed Apr 03 05:31:37 2024 +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/src/inv_sqrt.c	Wed Apr 03 05:31:37 2024 +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/src/inv_sqrt.tab	Wed Apr 03 05:31:37 2024 +0000
@@ -0,0 +1,13 @@
+/*-----------------------------------------------------*
+ | Table for routine Inv_sqrt().                       |
+ -----------------------------------------------------*/
+
+static const Word16 table[49] =
+{
+
+    32767, 31790, 30894, 30070, 29309, 28602, 27945, 27330, 26755, 26214,
+    25705, 25225, 24770, 24339, 23930, 23541, 23170, 22817, 22479, 22155,
+    21845, 21548, 21263, 20988, 20724, 20470, 20225, 19988, 19760, 19539,
+    19326, 19119, 18919, 18725, 18536, 18354, 18176, 18004, 17837, 17674,
+    17515, 17361, 17211, 17064, 16921, 16782, 16646, 16514, 16384
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lag_wind.c	Wed Apr 03 05:31:37 2024 +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/src/lag_wind.tab	Wed Apr 03 05:31:37 2024 +0000
@@ -0,0 +1,46 @@
+/*-----------------------------------------------------*
+ | Table of lag_window for autocorrelation.            |
+ | noise floor = 1.0001   = (0.9999  on r[1] ..r[10])  |
+ | Bandwitdh expansion = 60 Hz                         |
+ |                                                     |
+ |                                                     |
+ | lag_wind[0] =  1.00000000    (not stored)           |
+ | lag_wind[1] =  0.99879038                           |
+ | lag_wind[2] =  0.99546897                           |
+ | lag_wind[3] =  0.98995781                           |
+ | lag_wind[4] =  0.98229337                           |
+ | lag_wind[5] =  0.97252619                           |
+ | lag_wind[6] =  0.96072036                           |
+ | lag_wind[7] =  0.94695264                           |
+ | lag_wind[8] =  0.93131179                           |
+ | lag_wind[9] =  0.91389757                           |
+ | lag_wind[10]=  0.89481968                           |
+ -----------------------------------------------------*/
+
+static const Word16 lag_h[10] =
+{
+    32728,
+    32619,
+    32438,
+    32187,
+    31867,
+    31480,
+    31029,
+    30517,
+    29946,
+    29321
+};
+
+static const Word16 lag_l[10] =
+{
+    11904,
+    17280,
+    30720,
+    25856,
+    24192,
+    28992,
+    24384,
+    7360,
+    19520,
+    14784
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/levinson.c	Wed Apr 03 05:31:37 2024 +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/src/log2.c	Wed Apr 03 05:31:37 2024 +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/src/log2.tab	Wed Apr 03 05:31:37 2024 +0000
@@ -0,0 +1,11 @@
+/*-----------------------------------------------------*
+ | Table for routine Log2().                           |
+ -----------------------------------------------------*/
+
+static const Word16 table[33] =
+{
+    0, 1455, 2866, 4236, 5568, 6863, 8124, 9352, 10549, 11716,
+    12855, 13967, 15054, 16117, 17156, 18172, 19167, 20142, 21097, 22033,
+    22951, 23852, 24735, 25603, 26455, 27291, 28113, 28922, 29716, 30497,
+    31266, 32023, 32767
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lsp_az.c	Wed Apr 03 05:31:37 2024 +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/src/lsp_lsf.c	Wed Apr 03 05:31:37 2024 +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/src/lsp_lsf.tab	Wed Apr 03 05:31:37 2024 +0000
@@ -0,0 +1,34 @@
+/*-----------------------------------------------------*
+ | Tables for function Lsf_lsp() and Lsp_lsf()         |
+  -----------------------------------------------------*/
+
+/* table of cos(x) */
+
+static const Word16 table[65] =
+{
+    32767, 32729, 32610, 32413, 32138, 31786, 31357, 30853,
+    30274, 29622, 28899, 28106, 27246, 26320, 25330, 24279,
+    23170, 22006, 20788, 19520, 18205, 16846, 15447, 14010,
+    12540, 11039, 9512, 7962, 6393, 4808, 3212, 1608,
+    0, -1608, -3212, -4808, -6393, -7962, -9512, -11039,
+    -12540, -14010, -15447, -16846, -18205, -19520, -20788, -22006,
+    -23170, -24279, -25330, -26320, -27246, -28106, -28899, -29622,
+    -30274, -30853, -31357, -31786, -32138, -32413, -32610, -32729,
+    (Word16) 0x8000
+};
+
+/* 0x8000 = -32768 (used to silence the compiler) */
+
+/* slope used to compute y = acos(x) */
+
+static const Word16 slope[64] =
+{
+    -26887, -8812, -5323, -3813, -2979, -2444, -2081, -1811,
+    -1608, -1450, -1322, -1219, -1132, -1059, -998, -946,
+    -901, -861, -827, -797, -772, -750, -730, -713,
+    -699, -687, -677, -668, -662, -657, -654, -652,
+    -652, -654, -657, -662, -668, -677, -687, -699,
+    -713, -730, -750, -772, -797, -827, -861, -901,
+    -946, -998, -1059, -1132, -1219, -1322, -1450, -1608,
+    -1811, -2081, -2444, -2979, -3813, -5323, -8812, -26887
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/n_proc.c	Wed Apr 03 05:31:37 2024 +0000
@@ -0,0 +1,14 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+void proc_head (char *mes)
+{
+    fprintf(stderr, "\n/**************************************************************\n\n");
+    fprintf(stderr, "     European digital cellular telecommunications system\n");
+    fprintf(stderr, "                12200 bits/s speech codec for\n");
+    fprintf(stderr, "          enhanced full rate speech traffic channels\n\n");
+    fprintf(stderr, "     Bit-Exact C Simulation Code - %s\n", mes);
+    fprintf(stderr, "     Version 5.1.0\n");
+    fprintf(stderr, "     June 26, 1996\n\n");
+    fprintf(stderr, "**************************************************************/\n\n");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/n_stack.h	Wed Apr 03 05:31:37 2024 +0000
@@ -0,0 +1,7 @@
+#if defined(__BORLANDC__)
+#include <dos.h>
+extern unsigned _stklen = 32000U;
+
+#endif
+
+void proc_head (char *mes);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/oper_32b.c	Wed Apr 03 05:31:37 2024 +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/src/oper_32b.h	Wed Apr 03 05:31:37 2024 +0000
@@ -0,0 +1,7 @@
+/* Double precision operations */
+
+void L_Extract (Word32 L_32, Word16 *hi, Word16 *lo);
+Word32 L_Comp (Word16 hi, Word16 lo);
+Word32 Mpy_32 (Word16 hi1, Word16 lo1, Word16 hi2, Word16 lo2);
+Word32 Mpy_32_16 (Word16 hi, Word16 lo, Word16 n);
+Word32 Div_32 (Word32 L_num, Word16 denom_hi, Word16 denom_lo);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pitch_f6.c	Wed Apr 03 05:31:37 2024 +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/src/pitch_ol.c	Wed Apr 03 05:31:37 2024 +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/src/pow2.c	Wed Apr 03 05:31:37 2024 +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/src/pow2.tab	Wed Apr 03 05:31:37 2024 +0000
@@ -0,0 +1,11 @@
+/*-----------------------------------------------------*
+ | Table for routine Pow2().                           |
+ -----------------------------------------------------*/
+
+static const Word16 table[33] =
+{
+    16384, 16743, 17109, 17484, 17867, 18258, 18658, 19066, 19484, 19911,
+    20347, 20792, 21247, 21713, 22188, 22674, 23170, 23678, 24196, 24726,
+    25268, 25821, 26386, 26964, 27554, 28158, 28774, 29405, 30048, 30706,
+    31379, 32066, 32767
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pre_proc.c	Wed Apr 03 05:31:37 2024 +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/src/pred_lt6.c	Wed Apr 03 05:31:37 2024 +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/src/preemph.c	Wed Apr 03 05:31:37 2024 +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/src/prm2bits.c	Wed Apr 03 05:31:37 2024 +0000
@@ -0,0 +1,105 @@
+/*************************************************************************
+ *
+ *  FUNCTION:  Prm2bits_12k2
+ *
+ *  PURPOSE:  converts the encoder parameter vector into a vector of serial
+ *                      bits.
+ *
+ *  DESCRIPTION: The encoder parameters are:
+ *
+ *     LPC:
+ *              1st codebook             7 bit
+ *              2nd codebook             8 bit
+ *              3rd codebook             8+1 bit
+ *              4th codebook             8 bit
+ *              5th codebook             6 bit
+ *
+ *     1st and 3rd subframes:
+ *           pitch period                9 bit
+ *           pitch gain                  4 bit
+ *           codebook index              35 bit
+ *           codebook gain               5 bit
+ *
+ *     2nd and 4th subframes:
+ *           pitch period                6 bit
+ *           pitch gain                  4 bit
+ *           codebook index              35 bit
+ *           codebook gain               5 bit
+ *
+ *************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "count.h"
+
+/* Local function */
+
+void Int2bin (
+    Word16 value,       /* input : value to be converted to binary      */
+    Word16 no_of_bits,  /* input : number of bits associated with value */
+    Word16 *bitstream   /* output: address where bits are written       */
+);
+
+#define BIT_0     0
+#define BIT_1     1
+#define MASK      0x0001
+#define PRM_NO    57
+
+void Prm2bits_12k2 (
+    Word16 prm[],       /* input : analysis parameters  (57 parameters)   */
+    Word16 bits[]       /* output: 244 serial bits                        */
+)
+{
+    Word16 i;
+
+    static const Word16 bitno[PRM_NO] =
+    {
+        7, 8, 9, 8, 6,                          /* LSP VQ          */
+        9, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 5,  /* first subframe  */
+        6, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 5,  /* second subframe */
+        9, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 5,  /* third subframe  */
+        6, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 5   /* fourth subframe */
+    };
+    for (i = 0; i < PRM_NO; i++)
+    {
+        Int2bin (prm[i], bitno[i], bits);
+        bits += bitno[i];
+    }
+
+    return;
+}
+
+/*************************************************************************
+ *
+ *  FUNCTION:  Int2bin
+ *
+ *  PURPOSE:  convert integer to binary and write the bits to the array
+ *            bitstream[]. The most significant bits are written first.
+ *
+ *************************************************************************/
+
+void Int2bin (
+    Word16 value,       /* input : value to be converted to binary      */
+    Word16 no_of_bits,  /* input : number of bits associated with value */
+    Word16 *bitstream   /* output: address where bits are written       */
+)
+{
+    Word16 *pt_bitstream, i, bit;
+
+    pt_bitstream = &bitstream[no_of_bits];      move16 (); 
+
+    for (i = 0; i < no_of_bits; i++)
+    {
+        bit = value & MASK;                     logic16 (); 
+        test (); 
+        if (bit == 0)
+        {
+            *--pt_bitstream = BIT_0;            move16 (); 
+        }
+        else
+        {
+            *--pt_bitstream = BIT_1;            move16 (); 
+        }
+        value = shr (value, 1);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pstfilt2.c	Wed Apr 03 05:31:37 2024 +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/src/q_gains.c	Wed Apr 03 05:31:37 2024 +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/src/q_plsf_5.c	Wed Apr 03 05:31:37 2024 +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/src/q_plsf_5.tab	Wed Apr 03 05:31:37 2024 +0000
@@ -0,0 +1,1010 @@
+/*--------------------------------------------------------------------------*
+* Quantization tables for split_MQ of 2 sets of LSFs in a 20 ms frame.     *
+* See "q_plsf_5.c"                                                         *
+*--------------------------------------------------------------------------*/
+
+/* LSF means ->normalize frequency domain */
+
+static const Word16 mean_lsf[10] =
+{
+    1384,
+    2077,
+    3420,
+    5108,
+    6742,
+    8122,
+    9863,
+    11092,
+    12714,
+    13701
+};
+
+#ifndef D_HOMING
+
+#define DICO1_SIZE  128
+#define DICO2_SIZE  256
+#define DICO3_SIZE  256
+#define DICO4_SIZE  256
+#define DICO5_SIZE  64
+
+static const Word16 dico1_lsf[DICO1_SIZE * 4] =
+{
+    -451, -1065, -529, -1305,
+    -450, -756, -497, -863,
+    -384, -619, -413, -669,
+    -317, -538, -331, -556,
+    -414, -508, -424, -378,
+    -274, -324, -434, -614,
+    -226, -500, -232, -514,
+    -263, -377, -298, -410,
+    -151, -710, -174, -818,
+    -149, -412, -156, -429,
+    -288, -462, -186, -203,
+    -170, -302, -191, -321,
+    -131, -147, -297, -395,
+    -228, -214, -245, -192,
+    -67, -316, -71, -327,
+    -104, -205, -94, -183,
+    -143, -38, -193, -95,
+    16, -76, -124, -248,
+    23, -237, 24, -244,
+    18, -136, 44, -111,
+    -33, -24, -25, 0,
+    149, 19, 23, -143,
+    158, -169, 174, -181,
+    133, -55, 165, -26,
+    111, 84, 98, 75,
+    87, 183, -115, -11,
+    -8, 130, 11, 170,
+    254, 77, 205, 17,
+    183, 112, 262, 194,
+    202, 287, 95, 189,
+    -42, -105, 234, 179,
+    39, 186, 163, 345,
+    332, 199, 299, 161,
+    -54, 285, -78, 281,
+    -133, 141, -182, 111,
+    249, 341, 271, 364,
+    93, 403, 75, 391,
+    92, 510, -138, 220,
+    -185, -29, -34, 361,
+    -115, 320, 3, 554,
+    99, 286, 218, 591,
+    -245, 406, -268, 453,
+    0, 580, 25, 606,
+    275, 532, 148, 450,
+    -73, 739, -285, 518,
+    -288, 94, -203, 674,
+    -140, -74, 205, 714,
+    -114, 299, 176, 923,
+    182, 557, 240, 705,
+    -16, 513, 485, 593,
+    293, 384, 451, 617,
+    -38, 50, 563, 529,
+    303, 209, 459, 363,
+    433, 452, 450, 454,
+    367, 606, 477, 741,
+    432, 353, 368, 267,
+    361, 716, 273, 583,
+    453, 166, 510, 172,
+    201, 629, 274, 191,
+    568, 639, 302, 298,
+    634, 387, 643, 350,
+    587, 560, 612, 565,
+    600, 788, 487, 672,
+    512, 1015, 321, 333,
+    357, 854, -125, 413,
+    474, 712, 17, -151,
+    564, 285, 270, -241,
+    971, 889, 489, 220,
+    510, 896, 549, 924,
+    327, 825, 290, 911,
+    540, 1108, 158, 805,
+    199, 957, 511, 730,
+    100, 874, 13, 791,
+    435, 632, 676, 972,
+    249, 900, 467, 1218,
+    781, 1074, 585, 785,
+    -23, 669, 267, 1043,
+    619, 1084, 615, 1145,
+    622, 905, 916, 1049,
+    80, 331, 584, 1075,
+    89, 639, 988, 961,
+    770, 720, 798, 699,
+    492, 447, 899, 627,
+    271, 1188, 725, 1333,
+    87, 603, 832, 1603,
+    616, 1127, 890, 1505,
+    1000, 1156, 866, 1009,
+    995, 827, 1149, 858,
+    817, 1450, 773, 1320,
+    500, 1389, 312, 1153,
+    -20, 1084, 64, 1283,
+    2, 1172, 399, 1869,
+    514, 1706, 502, 1636,
+    886, 1522, 416, 600,
+    1131, 1350, 1275, 1390,
+    889, 1795, 914, 1766,
+    227, 1183, 1250, 1826,
+    505, 1854, 919, 2353,
+    -199, 431, 152, 1735,
+    -213, -28, 392, 1334,
+    -153, -52, 978, 1151,
+    -323, -400, 813, 1703,
+    -136, 84, 1449, 2015,
+    -331, -143, -137, 1192,
+    -256, 534, -157, 1031,
+    -307, -439, 542, 731,
+    -329, -420, -97, 616,
+    -362, -168, -322, 366,
+    -247, -110, -211, 89,
+    -196, -309, 20, 59,
+    -364, -463, -286, 89,
+    -336, 175, -432, 141,
+    -379, -190, -434, -196,
+    -79, 150, -278, -227,
+    -280, 166, -555, -422,
+    -155, 541, -366, 54,
+    -29, -83, -301, -774,
+    186, 628, -397, -264,
+    242, 293, -197, -585,
+    124, 410, 53, -133,
+    10, 340, -570, -1065,
+    65, -446, 68, -493,
+    383, 937, -357, -711,
+    -359, -250, -677, -1068,
+    292, -26, 363, 6,
+    607, 1313, -127, -10,
+    1513, 1886, 713, 972,
+    1469, 2181, 1443, 2016
+};
+
+static const Word16 dico2_lsf[DICO2_SIZE * 4] =
+{
+    -1631, -1600, -1796, -2290,
+    -1027, -1770, -1100, -2025,
+    -1277, -1388, -1367, -1534,
+    -947, -1461, -972, -1524,
+    -999, -1222, -1020, -1172,
+    -815, -987, -992, -1371,
+    -1216, -1006, -1289, -1094,
+    -744, -1268, -755, -1293,
+    -862, -923, -905, -984,
+    -678, -1051, -685, -1050,
+    -1087, -985, -1062, -679,
+    -989, -641, -1127, -976,
+    -762, -654, -890, -806,
+    -833, -1091, -706, -629,
+    -621, -806, -640, -812,
+    -775, -634, -779, -543,
+    -996, -565, -1075, -580,
+    -546, -611, -572, -619,
+    -760, -290, -879, -526,
+    -823, -462, -795, -253,
+    -553, -415, -589, -439,
+    -533, -340, -692, -935,
+    -505, -772, -702, -1131,
+    -263, -306, -971, -483,
+    -445, -74, -555, -548,
+    -614, -129, -693, -234,
+    -396, -246, -475, -250,
+    -265, -404, -376, -514,
+    -417, -510, -300, -313,
+    -334, -664, -463, -814,
+    -386, -704, -337, -615,
+    -234, -201, -233, -239,
+    -167, -567, -203, -619,
+    -147, -415, -115, -352,
+    -166, -750, -171, -761,
+    -270, -879, -264, -903,
+    -367, -744, 43, -475,
+    14, -653, 43, -670,
+    11, -448, -59, -521,
+    -126, -119, -155, -613,
+    -42, -863, -27, -931,
+    136, -483, 183, -468,
+    55, -298, 55, -304,
+    313, -609, 313, -720,
+    322, -167, 100, -541,
+    -3, -119, -111, -187,
+    233, -236, 260, -234,
+    26, -165, 134, -45,
+    -40, -549, 360, -203,
+    378, -388, 450, -383,
+    275, 20, 182, -103,
+    246, -111, 431, 37,
+    462, -146, 487, -157,
+    -284, -59, 503, -184,
+    24, 53, -3, 54,
+    122, 259, 333, 66,
+    484, 104, 436, 68,
+    195, 116, 190, 206,
+    269, -9, 482, 352,
+    382, 285, 399, 277,
+    452, 256, 69, 186,
+    13, 297, -13, 259,
+    -95, 30, 56, 394,
+    196, 425, 205, 456,
+    281, 577, 15, 191,
+    375, 290, 407, 576,
+    -56, 227, 544, 405,
+    0, 549, -92, 528,
+    -229, 351, -245, 338,
+    -362, 435, 167, 527,
+    -75, 302, 91, 824,
+    129, 599, 496, 679,
+    186, 749, 153, 737,
+    -281, 600, -348, 615,
+    -236, 769, 41, 881,
+    38, 890, -220, 841,
+    -357, 883, -393, 903,
+    -634, 474, -444, 850,
+    -175, 678, -493, 242,
+    -519, 785, -714, 582,
+    -541, 366, -543, 434,
+    -597, 500, -765, 222,
+    -702, 917, -743, 962,
+    -869, 501, -899, 548,
+    -379, 200, -435, 157,
+    -819, 214, -861, 157,
+    -614, 40, -632, 94,
+    -883, -54, -741, 516,
+    -501, 298, -614, -171,
+    -870, -161, -865, -23,
+    -818, 93, -1015, -267,
+    -662, -359, -549, 2,
+    -442, -121, -377, 0,
+    -227, 33, -414, -126,
+    -129, 212, -934, 34,
+    -1082, -282, -1119, -268,
+    -710, -825, -420, -191,
+    -1076, -928, -917, -93,
+    -628, -358, 97, 7,
+    -206, -393, -101, 24,
+    -203, 38, -168, 83,
+    -599, -423, -279, 426,
+    -700, 118, -75, 206,
+    -981, -673, -680, 417,
+    -367, 37, -279, 474,
+    -129, -318, 319, 296,
+    -626, -39, 343, 602,
+    -696, -39, -303, 940,
+    104, 233, -380, 137,
+    -36, 269, -75, -214,
+    120, 43, -529, -477,
+    459, 164, -202, -229,
+    -49, -167, 609, 792,
+    98, -220, 915, 148,
+    293, 283, 869, 91,
+    575, 394, 326, -78,
+    717, 67, 365, -323,
+    616, -36, 731, 27,
+    619, 238, 632, 273,
+    448, 99, 801, 476,
+    869, 273, 685, 64,
+    789, 72, 1021, 217,
+    793, 459, 734, 360,
+    646, 480, 360, 322,
+    429, 464, 638, 430,
+    756, 363, 1000, 404,
+    683, 528, 602, 615,
+    655, 413, 946, 687,
+    937, 602, 904, 604,
+    555, 737, 786, 662,
+    467, 654, 362, 589,
+    929, 710, 498, 478,
+    415, 420, 693, 883,
+    813, 683, 781, 925,
+    913, 939, 726, 732,
+    491, 853, 531, 948,
+    734, 963, 315, 808,
+    761, 755, 1144, 760,
+    655, 1076, 826, 1057,
+    1091, 838, 1003, 808,
+    1047, 1133, 659, 1101,
+    992, 1050, 1074, 1075,
+    971, 694, 1226, 1054,
+    571, 841, 884, 1404,
+    1379, 1096, 1080, 861,
+    1231, 735, 1284, 760,
+    1272, 991, 1367, 1053,
+    1257, 700, 1050, 534,
+    988, 453, 1264, 599,
+    1140, 679, 1621, 815,
+    1384, 521, 1317, 393,
+    1564, 805, 1448, 686,
+    1068, 648, 875, 307,
+    1083, 361, 1047, 317,
+    1417, 964, 675, 571,
+    1152, 79, 1114, -47,
+    1530, 311, 1721, 314,
+    1166, 689, 514, -94,
+    349, 282, 1412, 328,
+    1025, 487, -65, 57,
+    805, 970, 36, 62,
+    769, -263, 791, -346,
+    637, 699, -137, 620,
+    534, 541, -735, 194,
+    711, 300, -268, -863,
+    926, 769, -708, -428,
+    506, 174, -892, -630,
+    435, 547, -1435, -258,
+    621, 471, -1018, -1368,
+    -393, 521, -920, -686,
+    -25, 20, -982, -1156,
+    340, 9, -1558, -1135,
+    -352, 48, -1579, -402,
+    -887, 6, -1156, -888,
+    -548, -352, -1643, -1168,
+    -159, 610, -2024, -963,
+    -225, 193, -1656, -1960,
+    -245, -493, -964, -1680,
+    -936, -635, -1299, -1744,
+    -1388, -604, -1540, -835,
+    -1397, -135, -1588, -290,
+    -1670, -712, -2011, -1632,
+    -1663, -27, -2258, -811,
+    -1157, 184, -1265, 189,
+    -1367, 586, -2011, 201,
+    -790, 712, -1210, 3,
+    -1033, 808, -1251, 830,
+    -111, 635, -1636, 447,
+    -463, -949, -445, -928,
+    -504, -1162, -501, -1211,
+    144, -351, -372, -1052,
+    -283, -1059, -279, -1123,
+    -575, -1438, -587, -1614,
+    -935, -984, 229, 690,
+    -921, -719, -403, 1362,
+    -685, -465, 874, 397,
+    -509, -46, 317, 1334,
+    -485, 456, 813, 439,
+    -411, 339, 898, 1067,
+    -425, 46, 1441, 497,
+    -909, -800, 1465, 1046,
+    -254, -321, 1430, 1165,
+    68, 350, 1034, 666,
+    370, 11, 1311, 790,
+    143, 232, 1041, 1562,
+    -114, 663, 1616, 1078,
+    454, 579, 1275, 1040,
+    -76, 909, 752, 1067,
+    153, 512, 348, 1214,
+    614, 385, 1843, 808,
+    269, 1034, 203, 1086,
+    652, 1017, 1783, 1130,
+    429, 1327, 387, 1384,
+    -49, 1183, -72, 1215,
+    -416, 1001, 544, 1749,
+    -352, 1223, -502, 1199,
+    -589, 569, -227, 1630,
+    -142, 1578, -230, 1715,
+    -714, 1288, -838, 1398,
+    1131, 1357, -208, 1232,
+    437, 965, -929, 818,
+    811, 1410, 859, 1507,
+    164, 1212, 1387, 1793,
+    484, 1874, 456, 2063,
+    996, 1170, 1326, 1402,
+    1316, 1360, 1135, 1262,
+    1234, 1618, 1361, 1768,
+    1421, 1227, 1584, 1347,
+    854, 672, 1685, 1566,
+    1139, 1270, 2016, 1825,
+    1773, 1581, 1532, 1460,
+    1487, 946, 1659, 1021,
+    1744, 1212, 1392, 977,
+    1772, 1161, 1826, 1164,
+    1718, 1429, 1973, 1591,
+    1185, 864, 2132, 1061,
+    1799, 814, 1838, 757,
+    2104, 1315, 2054, 1258,
+    2113, 915, 2331, 930,
+    1467, 1147, 2590, 1439,
+    2245, 1744, 2090, 1620,
+    2358, 1454, 2666, 1506,
+    1876, 1837, 2070, 1975,
+    1739, 1577, 682, 1289,
+    1584, 2045, 1454, 2098,
+    2498, 2004, 2711, 2066,
+    726, 1588, 2756, 2336,
+    228, 847, 2456, 1659,
+    36, 301, 1942, 1957,
+    -446, -96, 2154, 1396,
+    1533, 1101, 14, 608,
+    -923, -732, 1383, 1982,
+    1345, 952, -680, 321,
+    1281, 1268, -1594, 365,
+    941, 946, -1737, -822,
+    2374, 2787, 1821, 2788
+};
+
+static const Word16 dico3_lsf[DICO3_SIZE * 4] =
+{
+    -1812, -2275, -1879, -2537,
+    -1640, -1848, -1695, -2004,
+    -1220, -1912, -1221, -2106,
+    -1559, -1588, -1573, -1556,
+    -1195, -1615, -1224, -1727,
+    -1359, -1151, -1616, -1948,
+    -1274, -1391, -1305, -1403,
+    -1607, -1179, -1676, -1311,
+    -1443, -1478, -1367, -898,
+    -1256, -1059, -1331, -1134,
+    -982, -1133, -1149, -1504,
+    -1080, -1308, -1020, -1183,
+    -980, -1486, -967, -1495,
+    -988, -922, -1047, -1077,
+    -838, -1179, -858, -1222,
+    -1131, -1041, -1064, -767,
+    -872, -1157, -701, -880,
+    -706, -906, -774, -1016,
+    -578, -1080, -801, -1478,
+    -591, -1111, -592, -1146,
+    -713, -1388, -640, -1376,
+    -597, -1059, -416, -903,
+    -686, -832, -661, -708,
+    -444, -868, -490, -921,
+    -374, -776, -619, -1170,
+    -585, -549, -769, -795,
+    -435, -659, -530, -741,
+    -498, -837, -357, -597,
+    -279, -871, -243, -887,
+    -282, -665, -280, -667,
+    -165, -560, -394, -903,
+    -362, -410, -448, -583,
+    -409, -574, -313, -357,
+    -637, -548, -570, -436,
+    -896, -504, -382, -757,
+    -58, -481, -165, -618,
+    -191, -374, -234, -382,
+    -222, -683, -25, -480,
+    -418, -359, -730, -353,
+    -324, -157, -432, -322,
+    -394, -303, -284, -104,
+    -601, -289, -556, -196,
+    -588, -150, -659, -608,
+    -473, -24, -68, -448,
+    -474, -8, -506, -45,
+    -748, -184, -844, -252,
+    -901, -91, -584, -97,
+    -652, 138, -764, -131,
+    -678, -12, -670, 165,
+    -259, -3, -840, -107,
+    -909, 37, -992, 44,
+    -854, -415, -839, 13,
+    -1001, -271, -1026, -309,
+    -798, -478, -832, -488,
+    -943, 168, -1112, -387,
+    -1185, -101, -1183, -40,
+    -941, -316, -1030, -770,
+    -1044, -625, -1081, -538,
+    -1224, -299, -1312, -436,
+    -1197, -663, -1167, -161,
+    -1216, -690, -1237, -831,
+    -1432, -720, -1403, -493,
+    -898, -740, -922, -801,
+    -1102, -402, -1579, -964,
+    -1061, -638, -1269, -1438,
+    -1499, -934, -1502, -895,
+    -1598, -564, -1723, -717,
+    -606, -597, -1166, -1085,
+    -1369, -468, -1946, -1493,
+    -1838, -953, -1932, -931,
+    -1499, -188, -1635, -421,
+    -1457, -338, -1448, -22,
+    -1942, -422, -2006, -249,
+    -496, -114, -1910, -755,
+    -1289, 174, -1451, -109,
+    -482, -257, -1221, -508,
+    -1617, 151, -1694, 208,
+    -654, 107, -1651, 29,
+    -1141, 279, -1215, 306,
+    -1228, -506, -730, -175,
+    -1236, -101, -969, 551,
+    -870, 278, -823, 315,
+    -563, 376, -1051, 228,
+    -507, 280, -599, 281,
+    -758, 253, -305, 379,
+    -755, -134, -611, 660,
+    -824, 536, -817, 646,
+    -413, 49, -341, 177,
+    -453, 526, -482, 589,
+    -71, 339, -657, 264,
+    -244, 295, -237, 315,
+    -387, 569, -506, -9,
+    -377, 14, -160, 661,
+    -216, 40, -308, -46,
+    95, 214, -242, 167,
+    -86, 192, -56, 27,
+    -76, 31, 36, 309,
+    -106, -182, -113, 74,
+    -441, -22, 23, 139,
+    81, -11, 44, 15,
+    -87, -137, -118, -207,
+    -158, -58, 272, -92,
+    -156, -441, 8, -136,
+    128, -221, 101, -218,
+    40, -197, -76, -456,
+    9, -445, 33, -423,
+    226, 60, 73, -222,
+    156, -399, 280, -318,
+    245, -341, 166, -499,
+    339, -190, 327, -219,
+    325, -137, -89, -596,
+    100, -627, 144, -677,
+    487, 28, 252, -391,
+    214, -41, 282, -28,
+    99, -286, 331, 49,
+    459, -388, 565, -369,
+    436, 28, 336, -9,
+    397, -167, 618, 34,
+    596, -17, 561, -140,
+    299, 79, 522, 125,
+    203, 2, 244, 288,
+    255, 211, 175, 82,
+    596, 187, 517, 108,
+    381, 255, 365, 297,
+    497, 352, 327, -82,
+    25, 210, 371, 245,
+    261, 3, 545, 449,
+    140, 294, 44, 295,
+    212, 347, 244, 494,
+    331, 528, 201, 307,
+    349, 411, 613, 284,
+    614, 413, 464, 322,
+    624, 397, 97, 200,
+    -160, 384, 149, 362,
+    495, 525, 269, 585,
+    33, 491, -121, 433,
+    427, 611, 498, 516,
+    171, 443, 497, 666,
+    440, 275, 566, 575,
+    146, 639, 155, 670,
+    -33, 173, 212, 696,
+    -166, 601, -191, 695,
+    -489, 503, 175, 742,
+    214, 476, 372, 1083,
+    578, 530, 586, 777,
+    425, 874, 315, 841,
+    374, 848, -165, 565,
+    35, 991, -39, 1062,
+    329, 712, 786, 840,
+    645, 795, 661, 676,
+    571, 918, 632, 1079,
+    673, 817, 318, 388,
+    874, 1012, 564, 848,
+    880, 620, 557, 479,
+    671, 453, 692, 468,
+    840, 642, 844, 645,
+    506, 428, 897, 567,
+    837, 387, 962, 499,
+    691, 561, 939, 926,
+    783, 296, 790, 268,
+    1028, 530, 874, 329,
+    548, 143, 675, 291,
+    503, 66, 1041, 359,
+    786, 97, 805, 33,
+    837, 470, 511, 49,
+    1092, 327, 1174, 323,
+    3, 242, 872, 474,
+    689, 429, 1329, 678,
+    1042, 620, 1109, 664,
+    321, 193, 889, 950,
+    1153, 874, 893, 635,
+    877, 862, 948, 913,
+    1293, 665, 1320, 639,
+    997, 793, 1402, 1030,
+    1176, 1012, 1110, 959,
+    1410, 925, 1403, 915,
+    543, 862, 1116, 1222,
+    835, 1190, 835, 1190,
+    959, 1148, 1147, 1376,
+    1300, 1193, 1415, 1231,
+    1335, 1341, 746, 1092,
+    1711, 1283, 1389, 1073,
+    1334, 1566, 1153, 1475,
+    1645, 1137, 1825, 1220,
+    1056, 1382, 1521, 1730,
+    1632, 1545, 1620, 1542,
+    855, 1596, 865, 1667,
+    693, 885, 1716, 1519,
+    1167, 1296, 2209, 1760,
+    1952, 1493, 2020, 1482,
+    1534, 1866, 1694, 2008,
+    1566, 748, 1761, 825,
+    294, 1392, 1084, 2058,
+    621, 1315, 365, 1287,
+    198, 1028, 488, 1408,
+    249, 403, 1014, 1561,
+    324, 363, 1645, 1044,
+    193, 367, 2034, 1859,
+    -251, 579, 750, 994,
+    -243, 30, 1325, 879,
+    -28, -169, 624, 917,
+    -453, 159, 186, 1370,
+    -614, 6, 537, 392,
+    -94, -291, 781, 229,
+    -128, -298, 245, 491,
+    -701, -648, 972, 789,
+    -501, -640, 178, 255,
+    -365, -390, -255, 317,
+    -958, -294, -191, 228,
+    -775, -447, 157, -237,
+    -657, -720, -407, 92,
+    -117, -611, 334, -230,
+    -679, -1084, -144, -317,
+    -901, -861, -738, -360,
+    -85, -727, -90, -787,
+    100, -22, -391, -263,
+    -56, -73, -337, -754,
+    5, -189, -706, -624,
+    89, -344, -135, -1113,
+    -353, -237, -684, -1135,
+    -275, -1102, -269, -1203,
+    152, 145, -722, -1232,
+    49, 80, -1248, -776,
+    -248, 391, -732, -547,
+    469, 218, -255, -864,
+    69, 366, -166, -485,
+    -688, 191, -1212, -1196,
+    -170, -169, -1308, -1631,
+    321, 470, -1419, -1243,
+    -64, 272, -1361, -248,
+    492, 565, -721, -609,
+    195, 485, -573, -133,
+    427, 202, -171, -118,
+    199, 575, 2, -31,
+    694, 755, -1366, -39,
+    552, 557, -489, 271,
+    680, 537, 13, -453,
+    855, 954, -133, -52,
+    -81, 738, -1169, 637,
+    1055, 1059, -95, 676,
+    1259, 1081, 489, 305,
+    -449, 954, -534, 996,
+    -969, 866, -1058, 1059,
+    -1294, 618, -1416, 617,
+    -458, 1366, -159, 1821,
+    -774, -528, -14, 1110,
+    -1202, -901, -772, 433,
+    -1256, -1255, -1011, -302,
+    -602, -585, -759, -1618,
+    -760, -1549, -840, -1921,
+    -816, -539, -1769, -2235,
+    -227, -36, -2034, -1831,
+    -2107, -1126, -2471, -1816,
+    -1470, 252, -2701, -415,
+    -571, -467, 1509, 1554,
+    2180, 1975, 2326, 2020
+};
+
+static const Word16 dico4_lsf[DICO4_SIZE * 4] =
+{
+    -1857, -1681, -1857, -1755,
+    -2056, -1150, -2134, -1654,
+    -1619, -1099, -1704, -1131,
+    -1345, -1608, -1359, -1638,
+    -1338, -1293, -1325, -1265,
+    -1664, -1649, -1487, -851,
+    -1346, -1832, -1413, -2188,
+    -1282, -681, -1785, -1649,
+    -966, -1082, -1183, -1676,
+    -1054, -1073, -1142, -1158,
+    -1207, -744, -1274, -997,
+    -934, -1383, -927, -1416,
+    -1010, -1305, -783, -955,
+    -1049, -900, -993, -817,
+    -737, -823, -972, -1189,
+    -738, -1094, -738, -1154,
+    -784, -801, -810, -786,
+    -892, -520, -1000, -818,
+    -644, -965, -577, -882,
+    -541, -694, -671, -917,
+    -595, -642, -646, -615,
+    -956, -621, -925, -515,
+    -727, -483, -815, -485,
+    -840, -578, -440, -713,
+    -578, -325, -657, -670,
+    -386, -570, -441, -666,
+    -514, -787, -392, -529,
+    -522, -453, -487, -423,
+    -616, -585, -617, -157,
+    -662, -268, -680, -348,
+    -322, -323, -632, -444,
+    -304, -430, -332, -458,
+    -277, -468, -659, -793,
+    -319, -636, -227, -554,
+    -373, -347, -334, -210,
+    -456, -192, -530, -242,
+    -216, -198, -366, -370,
+    -338, -161, -409, -748,
+    -107, -380, -294, -643,
+    -223, -665, -234, -741,
+    -141, -496, -130, -510,
+    -139, -327, -172, -305,
+    -306, -580, -164, -263,
+    -262, -172, -67, -402,
+    31, -366, -10, -436,
+    -86, -527, 71, -377,
+    -22, -609, -12, -678,
+    -67, -319, 63, -191,
+    35, -181, -39, -242,
+    126, -167, -140, -544,
+    155, -297, 174, -297,
+    38, -8, 117, -380,
+    197, -452, 240, -522,
+    223, -103, 110, -187,
+    87, -155, 169, -47,
+    157, 26, -83, -100,
+    128, 80, 209, -62,
+    6, 7, 22, 5,
+    318, -20, 248, -45,
+    -200, -63, 156, -69,
+    250, -183, 369, -126,
+    -113, -76, -142, -122,
+    -64, -254, -31, 35,
+    -177, -71, -7, 171,
+    93, 27, 108, 212,
+    -330, -209, -123, -70,
+    -279, 95, -96, 20,
+    -188, -61, -314, 87,
+    -300, -78, -354, -134,
+    11, 122, -140, 122,
+    -275, 152, -293, 140,
+    -82, 138, -321, -111,
+    -480, -156, -359, 76,
+    -254, -40, -635, -96,
+    -522, 79, -507, 8,
+    -268, 303, -539, 68,
+    -446, 61, -522, 306,
+    111, 189, -435, 122,
+    -379, 166, -571, -398,
+    -632, -74, -747, -95,
+    -455, 194, -952, 83,
+    -798, 192, -755, 192,
+    -781, -162, -619, 234,
+    -663, -297, -488, -109,
+    -964, -132, -838, -68,
+    -843, 58, -1112, -86,
+    -805, -299, -944, -253,
+    -778, -50, -965, -549,
+    -352, -98, -992, -343,
+    -1117, -315, -1117, -307,
+    -1155, -374, -637, -230,
+    -1166, -43, -1299, -100,
+    -925, -393, -1274, -600,
+    -689, -130, -1479, -312,
+    -1321, -254, -1464, -442,
+    -1292, -613, -1261, -503,
+    -1501, -368, -1322, 26,
+    -1432, -66, -1743, -161,
+    -1644, -467, -1760, -548,
+    -1393, -568, -1556, -871,
+    -1495, -1034, -1387, -571,
+    -1917, -528, -1783, -123,
+    -1897, -231, -2054, -323,
+    -2052, -906, -1976, -567,
+    -1917, -620, -2047, -989,
+    -1077, -370, -2031, -704,
+    -2355, -749, -2740, -1089,
+    -1909, 159, -2012, 248,
+    -626, -123, -2339, -962,
+    -669, -408, -1379, -1174,
+    -452, -364, -1044, -735,
+    -132, 183, -1620, -752,
+    -547, -307, -777, -1261,
+    -98, 41, -880, -1091,
+    -257, 97, -1602, -1833,
+    31, -26, -644, -561,
+    -180, -546, -385, -1095,
+    -410, -802, -414, -827,
+    -457, -970, -490, -1109,
+    -215, -916, -144, -937,
+    -493, -1269, -517, -1507,
+    181, 101, -332, -889,
+    -836, -937, -559, -429,
+    -629, -547, -183, -337,
+    -545, -82, -250, -286,
+    5, -132, -348, -252,
+    -293, -472, -158, 100,
+    -29, 197, -236, -424,
+    -861, -213, -140, -7,
+    -427, -443, 187, -97,
+    -684, -736, -293, 258,
+    -368, -152, -150, 392,
+    -609, 175, -142, 299,
+    -138, 152, -119, 329,
+    -486, -52, 293, 198,
+    -183, 117, 175, 331,
+    -58, -274, 231, 300,
+    -288, 330, -305, 372,
+    -111, 409, -9, 423,
+    83, 256, 67, 367,
+    -19, 248, 91, 113,
+    -35, 406, -191, 154,
+    238, 296, 5, 197,
+    141, 221, 313, 198,
+    211, 421, 244, 334,
+    88, 426, -243, 454,
+    202, 552, -5, 403,
+    291, 185, 219, 301,
+    251, 138, 128, 69,
+    197, 288, -140, -61,
+    188, 361, 197, 598,
+    442, 273, 290, 143,
+    472, 482, 157, 370,
+    415, 321, 372, 385,
+    402, 552, 155, 24,
+    550, 263, -11, 21,
+    360, 227, 147, -254,
+    424, 97, 366, -13,
+    375, 141, 449, 232,
+    396, 507, 474, 272,
+    701, 324, 362, -47,
+    587, 148, 543, 69,
+    400, -51, 561, 59,
+    220, -10, 352, 147,
+    206, 211, 653, 185,
+    563, 297, 565, 284,
+    594, 121, 766, 192,
+    398, 118, 642, 434,
+    233, 264, 481, 467,
+    129, -165, 699, 239,
+    90, 26, 342, 474,
+    -55, 27, 388, 94,
+    -172, 0, 725, 379,
+    -60, 337, 370, 465,
+    95, 319, 806, 595,
+    78, 260, 497, 851,
+    210, 560, 458, 574,
+    -464, 202, 497, 625,
+    -202, 152, 48, 712,
+    -20, 566, 100, 715,
+    455, 468, 411, 605,
+    319, 646, 195, 615,
+    401, 538, 680, 739,
+    201, 667, 434, 954,
+    454, 425, 646, 491,
+    606, 681, 416, 508,
+    497, 822, 426, 815,
+    660, 647, 628, 716,
+    697, 466, 618, 457,
+    685, 460, 365, 309,
+    721, 567, 836, 601,
+    609, 300, 825, 459,
+    943, 687, 681, 533,
+    915, 598, 591, 243,
+    876, 451, 874, 420,
+    786, 317, 732, 220,
+    922, 317, 1108, 367,
+    531, 466, 1028, 649,
+    1053, 615, 1034, 553,
+    829, 602, 1021, 799,
+    927, 803, 878, 763,
+    799, 496, 1373, 773,
+    585, 770, 803, 930,
+    1099, 793, 1222, 862,
+    1209, 895, 1025, 727,
+    772, 845, 1172, 1115,
+    867, 1021, 830, 1013,
+    841, 910, 506, 703,
+    1239, 1077, 620, 819,
+    1196, 1083, 1155, 1081,
+    1142, 907, 1547, 1121,
+    1309, 648, 1343, 612,
+    1484, 988, 1479, 937,
+    985, 1328, 955, 1341,
+    429, 910, 841, 1338,
+    564, 1179, 412, 1156,
+    1427, 1320, 1434, 1330,
+    640, 760, 1726, 1410,
+    190, 555, 1073, 1005,
+    426, 257, 839, 980,
+    235, 231, 1520, 1167,
+    109, 293, 1014, 1569,
+    305, 142, 1148, 539,
+    -291, -108, 1213, 972,
+    22, -216, 667, 828,
+    -482, 438, 453, 1431,
+    -581, -422, 789, 387,
+    -358, -454, 174, 780,
+    -36, -372, 390, -134,
+    -629, 160, -306, 751,
+    -1258, -331, 177, 522,
+    -248, 574, -251, 639,
+    -531, 407, -596, 394,
+    -419, 789, -617, 801,
+    -986, 399, -857, 727,
+    -7, 518, -703, 310,
+    -1143, -24, -1002, 287,
+    -960, 363, -1299, 312,
+    -1534, 245, -1557, 305,
+    28, 153, -859, -175,
+    -33, 332, -1398, -154,
+    212, 410, -593, -197,
+    -1092, -704, -904, -65,
+    282, 367, -918, -686,
+    345, 93, -258, -357,
+    696, 644, -693, -28,
+    448, 493, -273, 193,
+    527, 546, -243, -513,
+    384, -136, 273, -353,
+    512, -142, 537, -198,
+    941, 750, 83, 248,
+    578, 861, -56, 592,
+    842, 44, 892, 24,
+    33, 890, -16, 982,
+    831, 1398, 1535, 1898,
+    1716, 1376, 1948, 1465
+};
+
+static const Word16 dico5_lsf[DICO5_SIZE * 4] =
+{
+    -1002, -929, -1096, -1203,
+    -641, -931, -604, -961,
+    -779, -673, -835, -788,
+    -416, -664, -458, -766,
+    -652, -521, -662, -495,
+    -1023, -509, -1023, -428,
+    -444, -552, -368, -449,
+    -479, -211, -1054, -903,
+    -316, -249, -569, -591,
+    -569, -275, -541, -191,
+    -716, -188, -842, -264,
+    -333, -248, -318, -228,
+    -275, 1, -567, -228,
+    -115, -221, -238, -374,
+    -197, -507, -222, -579,
+    -258, -432, -61, -244,
+    -345, 2, -338, 39,
+    -215, -169, -58, 0,
+    -56, -6, -203, -131,
+    1, -186, -5, -211,
+    6, -380, 11, -418,
+    -116, 131, -134, 113,
+    89, -4, 71, -2,
+    -19, -192, 262, 24,
+    189, 151, -133, -109,
+    186, -153, 166, -219,
+    37, 139, 193, 171,
+    337, 124, 158, -61,
+    141, 226, -13, 190,
+    231, 34, 354, 109,
+    316, 201, 244, 164,
+    330, -85, 390, -84,
+    254, 327, 257, 335,
+    491, 147, 476, 105,
+    54, 77, 437, 370,
+    421, 314, 449, 342,
+    329, 126, 673, 292,
+    571, 388, 243, 193,
+    653, 320, 621, 280,
+    194, 380, 517, 581,
+    45, 323, 111, 422,
+    489, 395, 734, 534,
+    622, 546, 486, 502,
+    318, 572, 189, 550,
+    385, 422, -157, 153,
+    -125, 382, -197, 386,
+    -263, 334, 228, 697,
+    -188, 1, 51, 297,
+    -507, 213, -376, 397,
+    -24, 255, -547, 89,
+    -502, -94, 387, 179,
+    -620, 68, -684, 112,
+    -642, -350, -260, 172,
+    -438, -324, 264, 648,
+    -964, -4, -1121, 7,
+    -134, 134, -1133, -306,
+    143, 96, -420, -497,
+    -1221, -350, -1527, -685,
+    -161, 72, 873, 691,
+    732, 283, 921, 353,
+    334, 475, 1095, 821,
+    864, 524, 843, 497,
+    714, 711, 788, 750,
+    1076, 714, 1204, 753
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/reorder.c	Wed Apr 03 05:31:37 2024 +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/src/residu.c	Wed Apr 03 05:31:37 2024 +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/src/set_zero.c	Wed Apr 03 05:31:37 2024 +0000
@@ -0,0 +1,26 @@
+/*************************************************************************
+ *
+ *  FUNCTION:   Set zero()
+ *
+ *  PURPOSE:  Set vector x[] to zero
+ *
+ *************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "count.h"
+
+void Set_zero (
+    Word16 x[],         /* (o)    : vector to clear     */
+    Word16 L            /* (i)    : length of vector    */
+)
+{
+    Word16 i;
+
+    for (i = 0; i < L; i++)
+    {
+        x[i] = 0;               move16 (); 
+    }
+
+    return;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/sig_proc.h	Wed Apr 03 05:31:37 2024 +0000
@@ -0,0 +1,126 @@
+/*--------------------------------------------------------------*
+* Function prototypes for general SIGnal PROCessing functions. *
+*--------------------------------------------------------------*/
+
+/* Mathematic functions  */
+
+Word32 Inv_sqrt (      /* (o) : output value   (range: 0<=val<1)            */
+    Word32 L_x         /* (i) : input value    (range: 0<=val<=7fffffff)    */
+);
+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)*/
+);
+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)     */
+);
+
+/* General signal processing */
+
+void Init_Pre_Process (void);
+void Pre_Process (
+    Word16 signal[],   /* Input/output signal                               */
+    Word16 lg          /* Lenght of signal                                  */
+);
+
+Word16 Autocorr (
+    Word16 x[],        /* (i)    : Input signal                             */
+    Word16 m,          /* (i)    : LPC order                                */
+    Word16 r_h[],      /* (o)    : Autocorrelations  (msb)                  */
+    Word16 r_l[],      /* (o)    : Autocorrelations  (lsb)                  */
+    const Word16 wind[]/* (i)    : window for LPC analysis.                 */
+);
+void Lag_window (
+    Word16 m,          /* (i)    : LPC order                                */
+    Word16 r_h[],      /* (i/o)  : Autocorrelations  (msb)                  */
+    Word16 r_l[]       /* (i/o)  : Autocorrelations  (lsb)                  */
+);
+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  */
+);
+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)   */
+);
+void Lsp_Az (
+    Word16 lsp[],      /* (i)    : line spectral frequencies                */
+    Word16 a[]         /* (o)    : predictor coefficients (order = 10)      */
+);
+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                                */
+);
+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                                */
+);
+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                                */
+);
+void Weight_Fac (
+    Word16 gamma,      /* (i)    : Spectral expansion.                      */
+    Word16 fac[]       /* (i/o)  : Computed factors.                        */
+);
+void Weight_Ai (
+    Word16 a[],        /* (i)  : a[m+1]  LPC coefficients   (m=10)          */
+    const Word16 fac[],/* (i)  : Spectral expansion factors.                */
+    Word16 a_exp[]     /* (o)  : Spectral expanded LPC coefficients         */
+);
+void Residu (
+    Word16 a[],        /* (i)  : prediction coefficients                    */
+    Word16 x[],        /* (i)  : speech signal                              */
+    Word16 y[],        /* (o)  : residual signal                            */
+    Word16 lg          /* (i)  : size of filtering                          */
+);
+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.           */
+);
+void Convolve (
+    Word16 x[],        /* (i)  : input vector                               */
+    Word16 h[],        /* (i)  : impulse response                           */
+    Word16 y[],        /* (o)  : output vector                              */
+    Word16 L           /* (i)  : vector size                                */
+);
+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                              */
+);
+void agc2 (
+    Word16 *sig_in,    /* (i)  : postfilter input signal                    */
+    Word16 *sig_out,   /* (i/o): postfilter output signal                   */
+    Word16 l_trm       /* (i)  : subframe size                              */
+);
+void preemphasis (
+    Word16 *signal,    /* (i/o): input signal overwritten by the output     */
+    Word16 g,          /* (i)  : preemphasis coefficient                    */
+    Word16 L           /* (i)  : size of filtering                          */
+);
+
+/* General */
+
+void Copy (
+    Word16 x[],        /* (i)  : input vector                               */
+    Word16 y[],        /* (o)  : output vector                              */
+    Word16 L           /* (i)  : vector length                              */
+);
+void Set_zero (
+    Word16 x[],        /* (o)  : vector to clear                            */
+    Word16 L           /* (i)  : length of vector                           */
+);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/syn_filt.c	Wed Apr 03 05:31:37 2024 +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/src/typedef.h	Wed Apr 03 05:31:37 2024 +0000
@@ -0,0 +1,22 @@
+/*_____________________
+ |                     |
+ | Basic types.        |
+ |_____________________|
+*/
+
+#if defined(__BORLANDC__) || defined(__WATCOMC__) || defined(_MSC_VER) || defined(__ZTC__)
+typedef short Word16;
+typedef long Word32;
+typedef int Flag;
+
+#elif defined(__sun)
+typedef short Word16;
+typedef long Word32;
+typedef int Flag;
+
+#elif defined(__unix__) || defined(__unix)
+typedef short Word16;
+typedef int Word32;
+typedef int Flag;
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/vad.c	Wed Apr 03 05:31:37 2024 +0000
@@ -0,0 +1,1223 @@
+/***************************************************************************
+ *
+ *   File Name: vad.c
+ *
+ *   Purpose:   Contains all functions for voice activity detection, as
+ *              described in the high level specification of VAD.
+ *
+ *     Below is a listing of all the functions appearing in the file.
+ *     The functions are arranged according to their purpose.  Under
+ *     each heading, the ordering is hierarchical.
+ *
+ *     Resetting of static variables of VAD:
+ *       reset_vad()
+ *
+ *     Main routine of VAD (called by the speech encoder):
+ *       vad_computation()
+ *       Adaptive filtering and energy computation:
+ *         energy_computation()
+ *       Averaging of autocorrelation function values:
+ *         acf_averaging()
+ *       Computation of predictor values:
+ *         predictor_values()
+ *           schur_recursion()
+ *           step_up()
+ *           compute_rav1()
+ *       Spectral comparison:
+ *         spectral_comparison()
+ *       Information tone detection:
+ *         tone_detection()
+ *           step_up()
+ *       Threshold adaptation:
+ *         threshold_adaptation()
+ *       VAD decision:
+ *         vad_decision()
+ *       VAD hangover addition:
+ *         vad_hangover()
+ *
+ *     Periodicity detection routine (called by the speech encoder):
+ *       periodicity_detection()
+ *
+ **************************************************************************/
+
+#include "typedef.h"
+#include "cnst.h"
+#include "basic_op.h"
+#include "oper_32b.h"
+#include "count.h"
+#include "vad.h"
+
+/* Constants of VAD hangover addition */
+
+#define HANGCONST 10
+#define BURSTCONST 3
+
+/* Constant of spectral comparison */
+
+#define STAT_THRESH 3670L       /* 0.056 */
+
+/* Constants of periodicity detection */
+
+#define LTHRESH 2
+#define NTHRESH 4
+
+/* Pseudo floating point representations of constants
+   for threshold adaptation */
+
+#define M_PTH    32500          /*** 130000.0 ***/
+#define E_PTH    17
+#define M_PLEV   21667          /*** 346666.7 ***/
+#define E_PLEV   19
+#define M_MARGIN 16927          /*** 69333340 ***/
+#define E_MARGIN 27
+
+#define FAC 17203               /* 2.1 */
+
+/* Constants of tone detection */
+
+#define FREQTH 3189
+#define PREDTH 1464
+
+/* Static variables of VAD */
+
+static Word16 rvad[9], scal_rvad;
+static Pfloat thvad;
+static Word32 L_sacf[27];
+static Word32 L_sav0[36];
+static Word16 pt_sacf, pt_sav0;
+static Word32 L_lastdm;
+static Word16 adaptcount;
+static Word16 burstcount, hangcount;
+static Word16 oldlagcount, veryoldlagcount, oldlag;
+
+Word16 ptch;
+
+/*************************************************************************
+ *
+ *   FUNCTION NAME: vad_reset
+ *
+ *   PURPOSE:  Resets the static variables of the VAD to their
+ *             initial values
+ *
+ *************************************************************************/
+
+void vad_reset ()
+{
+    Word16 i;
+
+    /* Initialize rvad variables */
+    rvad[0] = 0x6000;
+    for (i = 1; i < 9; i++)
+    {
+        rvad[i] = 0;
+    }
+    scal_rvad = 7;
+
+    /* Initialize threshold level */
+    thvad.e = 20;               /*** exponent ***/
+    thvad.m = 27083;            /*** mantissa ***/
+
+    /* Initialize ACF averaging variables */
+    for (i = 0; i < 27; i++)
+    {
+        L_sacf[i] = 0L;
+    }
+    for (i = 0; i < 36; i++)
+    {
+        L_sav0[i] = 0L;
+    }
+    pt_sacf = 0;
+    pt_sav0 = 0;
+
+    /* Initialize spectral comparison variable */
+    L_lastdm = 0L;
+
+    /* Initialize threshold adaptation variable */
+    adaptcount = 0;
+
+    /* Initialize VAD hangover addition variables */
+    burstcount = 0;
+    hangcount = -1;
+
+    /* Initialize periodicity detection variables */
+    oldlagcount = 0;
+    veryoldlagcount = 0;
+    oldlag = 18;
+
+    ptch = 1;
+
+    return;
+}
+
+/****************************************************************************
+ *
+ *     FUNCTION:  vad_computation
+ *
+ *     PURPOSE:   Returns a decision as to whether the current frame being
+ *                processed by the speech encoder contains speech or not.
+ *
+ *     INPUTS:    r_h[0..8]     autocorrelation of input signal frame (msb)
+ *                r_l[0..8]     autocorrelation of input signal frame (lsb)
+ *                scal_acf      scaling factor for the autocorrelations
+ *                rc[0..3]      speech encoder reflection coefficients
+ *                ptch          flag to indicate a periodic signal component
+ *
+ *     OUTPUTS:   none
+ *
+ *     RETURN VALUE: vad decision
+ *
+ ***************************************************************************/
+
+Word16 vad_computation (
+    Word16 r_h[],
+    Word16 r_l[],
+    Word16 scal_acf,
+    Word16 rc[],
+    Word16 ptch
+)
+{
+    Word32 L_av0[9], L_av1[9];
+    Word16 vad, vvad, rav1[9], scal_rav1, stat, tone;
+    Pfloat acf0, pvad;
+
+    energy_computation (r_h, scal_acf, rvad, scal_rvad, &acf0, &pvad);
+    acf_averaging (r_h, r_l, scal_acf, L_av0, L_av1);
+    predictor_values (L_av1, rav1, &scal_rav1);
+    stat = spectral_comparison (rav1, scal_rav1, L_av0);        move16 (); 
+    tone_detection (rc, &tone);
+    threshold_adaptation (stat, ptch, tone, rav1, scal_rav1, pvad, acf0,
+                          rvad, &scal_rvad, &thvad);
+    vvad = vad_decision (pvad, thvad);                          move16 (); 
+    vad = vad_hangover (vvad);                                  move16 (); 
+
+    return vad;
+}
+
+/****************************************************************************
+ *
+ *     FUNCTION:  energy_computation
+ *
+ *     PURPOSE:   Computes the input and residual energies of the adaptive
+ *                filter in a floating point representation.
+ *
+ *     INPUTS:    r_h[0..8]      autocorrelation of input signal frame (msb)
+ *                scal_acf       scaling factor for the autocorrelations
+ *                rvad[0..8]     autocorrelated adaptive filter coefficients
+ *                scal_rvad      scaling factor for rvad[]
+ *
+ *     OUTPUTS:   *acf0          signal frame energy (mantissa+exponent)
+ *                *pvad          filtered signal energy (mantissa+exponent)
+ *
+ *     RETURN VALUE: none
+ *
+ ***************************************************************************/
+
+void energy_computation (
+    Word16 r_h[],
+    Word16 scal_acf,
+    Word16 rvad[],
+    Word16 scal_rvad,
+    Pfloat * acf0,
+    Pfloat * pvad
+)
+{
+    Word16 i, temp, norm_prod;
+    Word32 L_temp;
+
+    /* r[0] is always greater than zero (no need to test for r[0] == 0) */
+
+    /* Computation of acf0 (exponent and mantissa) */
+
+    acf0->e = sub (32, scal_acf);       move16 (); 
+    acf0->m = r_h[0] & 0x7ff8;          move16 (); logic16 (); 
+
+    /* Computation of pvad (exponent and mantissa) */
+
+    pvad->e = add (acf0->e, 14);        move16 (); 
+    pvad->e = sub (pvad->e, scal_rvad); move16 (); 
+
+    L_temp = 0L;                        move32 (); 
+
+    for (i = 1; i <= 8; i++)
+    {
+        temp = shr (r_h[i], 3);
+        L_temp = L_mac (L_temp, temp, rvad[i]);
+    }
+
+    temp = shr (r_h[0], 3);
+    L_temp = L_add (L_temp, L_shr (L_mult (temp, rvad[0]), 1));
+
+    test (); 
+    if (L_temp <= 0L)
+    {
+        L_temp = 1L;                    move32 (); 
+    }
+    norm_prod = norm_l (L_temp);
+    pvad->e = sub (pvad->e, norm_prod); move16 (); 
+    pvad->m = extract_h (L_shl (L_temp, norm_prod));
+                                        move16 (); 
+
+    return;
+}
+
+/****************************************************************************
+ *
+ *     FUNCTION:  acf_averaging
+ *
+ *     PURPOSE:   Computes the arrays L_av0[0..8] and L_av1[0..8].
+ *
+ *     INPUTS:    r_h[0..8]     autocorrelation of input signal frame (msb)
+ *                r_l[0..8]     autocorrelation of input signal frame (lsb)
+ *                scal_acf      scaling factor for the autocorrelations
+ *
+ *     OUTPUTS:   L_av0[0..8]   ACF averaged over last four frames
+ *                L_av1[0..8]   ACF averaged over previous four frames
+ *
+ *     RETURN VALUE: none
+ *
+ ***************************************************************************/
+
+void acf_averaging (
+    Word16 r_h[],
+    Word16 r_l[],
+    Word16 scal_acf,
+    Word32 L_av0[],
+    Word32 L_av1[]
+)
+{
+    Word32 L_temp;
+    Word16 scale;
+    Word16 i;
+
+    scale = add (9, scal_acf);
+
+    for (i = 0; i <= 8; i++)
+    {
+        L_temp = L_shr (L_Comp (r_h[i], r_l[i]), scale);
+        L_av0[i] = L_add (L_sacf[i], L_temp);           move32 (); 
+        L_av0[i] = L_add (L_sacf[i + 9], L_av0[i]);     move32 (); 
+        L_av0[i] = L_add (L_sacf[i + 18], L_av0[i]);    move32 (); 
+        L_sacf[pt_sacf + i] = L_temp;                   move32 (); 
+        L_av1[i] = L_sav0[pt_sav0 + i];                 move32 (); 
+        L_sav0[pt_sav0 + i] = L_av0[i];                 move32 (); 
+    }
+
+    /* Update the array pointers */
+
+    test (); 
+    if (sub (pt_sacf, 18) == 0)
+    {
+        pt_sacf = 0;                                    move16 (); 
+    }
+    else
+    {
+        pt_sacf = add (pt_sacf, 9);
+    }
+
+    test (); 
+    if (sub (pt_sav0, 27) == 0)
+    {
+        pt_sav0 = 0;                                    move16 (); 
+    }
+    else
+    {
+        pt_sav0 = add (pt_sav0, 9);
+    }
+
+    return;
+}
+
+/****************************************************************************
+ *
+ *     FUNCTION:  predictor_values
+ *
+ *     PURPOSE:   Computes the array rav[0..8] needed for the spectral
+ *                comparison and the threshold adaptation.
+ *
+ *     INPUTS:    L_av1[0..8]   ACF averaged over previous four frames
+ *
+ *     OUTPUTS:   rav1[0..8]    ACF obtained from L_av1
+ *                *scal_rav1    rav1[] scaling factor
+ *
+ *     RETURN VALUE: none
+ *
+ ***************************************************************************/
+
+void predictor_values (
+    Word32 L_av1[],
+    Word16 rav1[],
+    Word16 *scal_rav1
+)
+{
+    Word16 vpar[8], aav1[9];
+
+    schur_recursion (L_av1, vpar);
+    step_up (8, vpar, aav1);
+    compute_rav1 (aav1, rav1, scal_rav1);
+
+    return;
+}
+
+/****************************************************************************
+ *
+ *     FUNCTION:  schur_recursion
+ *
+ *     PURPOSE:   Uses the Schur recursion to compute adaptive filter
+ *                reflection coefficients from an autorrelation function.
+ *
+ *     INPUTS:    L_av1[0..8]    autocorrelation function
+ *
+ *     OUTPUTS:   vpar[0..7]     reflection coefficients
+ *
+ *     RETURN VALUE: none
+ *
+ ***************************************************************************/
+
+void schur_recursion (
+    Word32 L_av1[],
+    Word16 vpar[]
+)
+{
+    Word16 acf[9], pp[9], kk[9], temp;
+    Word16 i, k, m, n;
+
+    /*** Schur recursion with 16-bit arithmetic ***/
+
+    test (); move32 (); 
+    if (L_av1[0] == 0)
+    {
+        for (i = 0; i < 8; i++)
+        {
+            vpar[i] = 0;                                move16 (); 
+        }
+        return;
+    }
+    temp = norm_l (L_av1[0]);
+
+    for (k = 0; k <= 8; k++)
+    {
+        acf[k] = extract_h (L_shl (L_av1[k], temp));    move16 (); 
+    }
+
+    /*** Initialize arrays pp[..] and kk[..] for the recursion: ***/
+
+    for (i = 1; i <= 7; i++)
+    {
+        kk[9 - i] = acf[i];                             move16 (); 
+    }
+
+    for (i = 0; i <= 8; i++)
+    {
+        pp[i] = acf[i];                                 move16 (); 
+    }
+
+    /*** Compute Parcor coefficients: ***/
+
+    for (n = 0; n < 8; n++)
+    {
+        test (); 
+        if ((pp[0] == 0) ||
+            (sub (pp[0], abs_s (pp[1])) < 0))
+        {
+            for (i = n; i < 8; i++)
+            {
+                vpar[i] = 0;                            move16 (); 
+            }
+            return;
+        }
+        vpar[n] = div_s (abs_s (pp[1]), pp[0]);         move16 (); 
+
+        test ();                                        move16 (); 
+        if (pp[1] > 0)
+        {
+            vpar[n] = negate (vpar[n]);                 move16 (); 
+        }
+        test (); 
+        if (sub (n, 7) == 0)
+        {
+            return;
+        }
+        /*** Schur recursion: ***/
+
+        pp[0] = add (pp[0], mult_r (pp[1], vpar[n]));   move16 (); 
+
+        for (m = 1; m <= 7 - n; m++)
+        {
+            pp[m] = add (pp[1 + m], mult_r (kk[9 - m], vpar[n]));
+                                                        move16 (); 
+            kk[9 - m] = add (kk[9 - m], mult_r (pp[1 + m], vpar[n]));
+                                                        move16 (); 
+        }
+    }
+
+    return;
+}
+
+/****************************************************************************
+ *
+ *     FUNCTION:  step_up
+ *
+ *     PURPOSE:   Computes the transversal filter coefficients from the
+ *                reflection coefficients.
+ *
+ *     INPUTS:    np               filter order (2..8)
+ *                vpar[0..np-1]    reflection coefficients
+ *
+ *     OUTPUTS:   aav1[0..np]      transversal filter coefficients
+ *
+ *     RETURN VALUE: none
+ *
+ ***************************************************************************/
+
+void step_up (
+    Word16 np,
+    Word16 vpar[],
+    Word16 aav1[]
+)
+{
+    Word32 L_coef[9], L_work[9];
+    Word16 temp;
+    Word16 i, m;
+
+    /*** Initialization of the step-up recursion ***/
+
+    L_coef[0] = 0x20000000L;    move32 (); 
+    L_coef[1] = L_shl (L_deposit_l (vpar[0]), 14);              move32 (); 
+
+    /*** Loop on the LPC analysis order: ***/
+
+    for (m = 2; m <= np; m++)
+    {
+        for (i = 1; i < m; i++)
+        {
+            temp = extract_h (L_coef[m - i]);
+            L_work[i] = L_mac (L_coef[i], vpar[m - 1], temp);   move32 (); 
+        }
+
+        for (i = 1; i < m; i++)
+        {
+            L_coef[i] = L_work[i];                              move32 (); 
+        }
+
+        L_coef[m] = L_shl (L_deposit_l (vpar[m - 1]), 14);      move32 (); 
+    }
+
+    /*** Keep the aav1[0..np] in 15 bits ***/
+
+    for (i = 0; i <= np; i++)
+    {
+        aav1[i] = extract_h (L_shr (L_coef[i], 3));             move32 (); 
+    }
+
+    return;
+}
+
+/****************************************************************************
+ *
+ *     FUNCTION:  compute_rav1
+ *
+ *     PURPOSE:   Computes the autocorrelation function of the adaptive
+ *                filter coefficients.
+ *
+ *     INPUTS:    aav1[0..8]     adaptive filter coefficients
+ *
+ *     OUTPUTS:   rav1[0..8]     ACF of aav1
+ *                *scal_rav1     rav1[] scaling factor
+ *
+ *     RETURN VALUE: none
+ *
+ ***************************************************************************/
+
+void compute_rav1 (
+    Word16 aav1[],
+    Word16 rav1[],
+    Word16 *scal_rav1
+)
+{
+    Word32 L_work[9];
+    Word16 i, k;
+
+    /*** Computation of the rav1[0..8] ***/
+
+    for (i = 0; i <= 8; i++)
+    {
+        L_work[i] = 0L;                                           move32 (); 
+
+        for (k = 0; k <= 8 - i; k++)
+        {
+            L_work[i] = L_mac (L_work[i], aav1[k], aav1[k + i]);  move32 (); 
+        }
+    }
+
+    test (); move32 (); 
+    if (L_work[0] == 0L)
+    {
+        *scal_rav1 = 0;                                           move16 (); 
+    }
+    else
+    {
+        *scal_rav1 = norm_l (L_work[0]);
+    }
+
+    for (i = 0; i <= 8; i++)
+    {
+        rav1[i] = extract_h (L_shl (L_work[i], *scal_rav1));      move16 (); 
+    }
+
+    return;
+}
+
+/****************************************************************************
+ *
+ *     FUNCTION:  spectral_comparison
+ *
+ *     PURPOSE:   Computes the stat flag needed for the threshold
+ *                adaptation decision.
+ *
+ *     INPUTS:    rav1[0..8]      ACF obtained from L_av1
+ *                *scal_rav1      rav1[] scaling factor
+ *                L_av0[0..8]     ACF averaged over last four frames
+ *
+ *     OUTPUTS:   none
+ *
+ *     RETURN VALUE: flag to indicate spectral stationarity
+ *
+ ***************************************************************************/
+
+Word16 spectral_comparison (
+    Word16 rav1[],
+    Word16 scal_rav1,
+    Word32 L_av0[]
+)
+{
+    Word32 L_dm, L_sump, L_temp;
+    Word16 stat, sav0[9], shift, divshift, temp;
+    Word16 i;
+
+    /*** Re-normalize L_av0[0..8] ***/
+
+    test (); move32 (); 
+    if (L_av0[0] == 0L)
+    {
+        for (i = 0; i <= 8; i++)
+        {
+            sav0[i] = 0x0fff;   /* 4095 */                      move16 (); 
+        }
+    }
+    else
+    {
+        shift = sub (norm_l (L_av0[0]), 3);
+        for (i = 0; i <= 8; i++)
+        {
+            sav0[i] = extract_h (L_shl (L_av0[i], shift));      move16 (); 
+        }
+    }
+
+    /*** Compute partial sum of dm ***/
+
+    L_sump = 0L;                                                move32 (); 
+    for (i = 1; i <= 8; i++)
+    {
+        L_sump = L_mac (L_sump, rav1[i], sav0[i]);
+    }
+
+    /*** Compute the division of the partial sum by sav0[0] ***/
+
+    test (); 
+    if (L_sump < 0L)
+    {
+        L_temp = L_negate (L_sump);
+    }
+    else
+    {
+        L_temp = L_sump;                                        move32 (); 
+    }
+
+    test (); 
+    if (L_temp == 0L)
+    {
+        L_dm = 0L;                                              move32 (); 
+        shift = 0;                                              move16 (); 
+    }
+    else
+    {
+        sav0[0] = shl (sav0[0], 3);                             move16 (); 
+        shift = norm_l (L_temp);
+        temp = extract_h (L_shl (L_temp, shift));
+
+        test (); 
+        if (sub (sav0[0], temp) >= 0)
+        {
+            divshift = 0;                                       move16 (); 
+            temp = div_s (temp, sav0[0]);
+        }
+        else
+        {
+            divshift = 1;                                       move16 (); 
+            temp = sub (temp, sav0[0]);
+            temp = div_s (temp, sav0[0]);
+        }
+
+        test (); 
+        if (sub (divshift, 1) == 0)
+        {
+            L_dm = 0x8000L;                                     move32 (); 
+        }
+        else
+        {
+            L_dm = 0L;                                          move32 (); 
+        }
+
+        L_dm = L_shl (L_add (L_dm, L_deposit_l (temp)), 1);
+
+        test (); 
+        if (L_sump < 0L)
+        {
+            L_dm = L_negate (L_dm);
+        }
+    }
+
+    /*** Re-normalization and final computation of L_dm ***/
+
+    L_dm = L_shl (L_dm, 14);
+    L_dm = L_shr (L_dm, shift);
+    L_dm = L_add (L_dm, L_shl (L_deposit_l (rav1[0]), 11));
+    L_dm = L_shr (L_dm, scal_rav1);
+
+    /*** Compute the difference and save L_dm ***/
+
+    L_temp = L_sub (L_dm, L_lastdm);
+    L_lastdm = L_dm;                                            move32 (); 
+
+    test (); 
+    if (L_temp < 0L)
+    {
+        L_temp = L_negate (L_temp);
+    }
+    /*** Evaluation of the stat flag ***/
+
+    L_temp = L_sub (L_temp, STAT_THRESH);
+
+    test (); 
+    if (L_temp < 0L)
+    {
+        stat = 1;                                               move16 (); 
+    }
+    else
+    {
+        stat = 0;                                               move16 (); 
+    }
+
+    return stat;
+}
+
+/****************************************************************************
+ *
+ *     FUNCTION:  threshold_adaptation
+ *
+ *     PURPOSE:   Evaluates the secondary VAD decision.  If speech is not
+ *                present then the noise model rvad and adaptive threshold
+ *                thvad are updated.
+ *
+ *     INPUTS:    stat          flag to indicate spectral stationarity
+ *                ptch          flag to indicate a periodic signal component
+ *                tone          flag to indicate a tone signal component
+ *                rav1[0..8]    ACF obtained from L_av1
+ *                scal_rav1     rav1[] scaling factor
+ *                pvad          filtered signal energy (mantissa+exponent)
+ *                acf0          signal frame energy (mantissa+exponent)
+ *
+ *     OUTPUTS:   rvad[0..8]    autocorrelated adaptive filter coefficients
+ *                *scal_rvad    rvad[] scaling factor
+ *                *thvad        decision threshold (mantissa+exponent)
+ *
+ *     RETURN VALUE: none
+ *
+ ***************************************************************************/
+
+void threshold_adaptation (
+    Word16 stat,
+    Word16 ptch,
+    Word16 tone,
+    Word16 rav1[],
+    Word16 scal_rav1,
+    Pfloat pvad,
+    Pfloat acf0,
+    Word16 rvad[],
+    Word16 *scal_rvad,
+    Pfloat * thvad
+)
+{
+    Word16 comp, comp2;
+    Word32 L_temp;
+    Word16 temp;
+    Pfloat p_temp;
+    Word16 i;
+
+    comp = 0;                                           move16 (); 
+
+    /*** Test if acf0 < pth; if yes set thvad to plev ***/
+
+    test (); 
+    if (sub (acf0.e, E_PTH) < 0)
+    {
+        comp = 1;                                       move16 (); 
+    }
+    test (); test (); 
+    if ((sub (acf0.e, E_PTH) == 0) && (sub (acf0.m, M_PTH) < 0))
+    {
+        comp = 1;                                       move16 (); 
+    }
+    test (); 
+    if (sub (comp, 1) == 0)
+    {
+        thvad->e = E_PLEV;                              move16 (); 
+        thvad->m = M_PLEV;                              move16 (); 
+
+        return;
+    }
+    /*** Test if an adaption is required ***/
+
+    test (); 
+    if (sub (ptch, 1) == 0)
+    {
+        comp = 1;                                       move16 (); 
+    }
+    test (); 
+    if (stat == 0)
+    {
+        comp = 1;                                       move16 (); 
+    }
+    test (); 
+    if (sub (tone, 1) == 0)
+    {
+        comp = 1;                                       move16 (); 
+    }
+    test (); 
+    if (sub (comp, 1) == 0)
+    {
+        adaptcount = 0;                                 move16 (); 
+        return;
+    }
+    /*** Increment adaptcount ***/
+
+    adaptcount = add (adaptcount, 1);
+    test (); 
+    if (sub (adaptcount, 8) <= 0)
+    {
+        return;
+    }
+    /*** computation of thvad-(thvad/dec) ***/
+
+    thvad->m = sub (thvad->m, shr (thvad->m, 5));       move16 (); 
+
+    test (); 
+    if (sub (thvad->m, 0x4000) < 0)
+    {
+        thvad->m = shl (thvad->m, 1);                   move16 (); 
+        thvad->e = sub (thvad->e, 1);                   move16 (); 
+    }
+    /*** computation of pvad*fac ***/
+
+    L_temp = L_mult (pvad.m, FAC);
+    L_temp = L_shr (L_temp, 15);
+    p_temp.e = add (pvad.e, 1);                         move16 (); 
+
+    test (); 
+    if (L_temp > 0x7fffL)
+    {
+        L_temp = L_shr (L_temp, 1);
+        p_temp.e = add (p_temp.e, 1);                   move16 (); 
+    }
+    p_temp.m = extract_l (L_temp);                      move16 (); 
+
+    /*** test if thvad < pvad*fac ***/
+
+    test (); 
+    if (sub (thvad->e, p_temp.e) < 0)
+    {
+        comp = 1;                                       move16 (); 
+    }
+    test (); test (); 
+    if ((sub (thvad->e, p_temp.e) == 0) &&
+        (sub (thvad->m, p_temp.m) < 0))
+    {
+        comp = 1;                                       move16 (); 
+    }
+    /*** compute minimum(thvad+(thvad/inc), pvad*fac) when comp = 1 ***/
+
+    test (); 
+    if (sub (comp, 1) == 0)
+    {
+        /*** compute thvad + (thvad/inc) ***/
+
+        L_temp = L_add (L_deposit_l (thvad->m),
+                        L_deposit_l (shr (thvad->m, 4)));
+
+        test (); 
+        if (L_sub (L_temp, 0x7fffL) > 0)
+        {
+            thvad->m = extract_l (L_shr (L_temp, 1));   move16 (); 
+            thvad->e = add (thvad->e, 1);               move16 (); 
+        }
+        else
+        {
+            thvad->m = extract_l (L_temp);              move16 (); 
+        }
+
+        comp2 = 0;                                      move16 (); 
+
+        test (); 
+        if (sub (p_temp.e, thvad->e) < 0)
+        {
+            comp2 = 1;                                  move16 (); 
+        }
+        test (); test (); 
+        if ((sub (p_temp.e, thvad->e) == 0) &&
+            (sub (p_temp.m, thvad->m) < 0))
+        {
+            comp2 = 1;                                  move16 (); 
+        }
+        test (); 
+        if (sub (comp2, 1) == 0)
+        {
+            thvad->e = p_temp.e;move16 (); 
+            thvad->m = p_temp.m;move16 (); 
+        }
+    }
+    /*** compute pvad + margin ***/
+
+    test (); 
+    if (sub (pvad.e, E_MARGIN) == 0)
+    {
+        L_temp = L_add (L_deposit_l (pvad.m), L_deposit_l (M_MARGIN));
+        p_temp.m = extract_l (L_shr (L_temp, 1));       move16 (); 
+        p_temp.e = add (pvad.e, 1);     move16 (); 
+    }
+    else
+    {
+        test (); 
+        if (sub (pvad.e, E_MARGIN) > 0)
+        {
+            temp = sub (pvad.e, E_MARGIN);
+            temp = shr (M_MARGIN, temp);
+            L_temp = L_add (L_deposit_l (pvad.m), L_deposit_l (temp));
+
+            test (); 
+            if (L_sub (L_temp, 0x7fffL) > 0)
+            {
+                p_temp.e = add (pvad.e, 1);             move16 (); 
+                p_temp.m = extract_l (L_shr (L_temp, 1));
+                                                        move16 (); 
+            }
+            else
+            {
+                p_temp.e = pvad.e;                      move16 (); 
+                p_temp.m = extract_l (L_temp);          move16 (); 
+            }
+        }
+        else
+        {
+            temp = sub (E_MARGIN, pvad.e);
+            temp = shr (pvad.m, temp);
+            L_temp = L_add (L_deposit_l (M_MARGIN), L_deposit_l (temp));
+
+            test (); 
+            if (L_sub (L_temp, 0x7fffL) > 0)
+            {
+                p_temp.e = add (E_MARGIN, 1);           move16 (); 
+                p_temp.m = extract_l (L_shr (L_temp, 1));
+                                                        move16 (); 
+            }
+            else
+            {
+                p_temp.e = E_MARGIN;                    move16 (); 
+                p_temp.m = extract_l (L_temp);          move16 (); 
+            }
+        }
+    }
+
+    /*** Test if thvad > pvad + margin ***/
+
+    comp = 0;                                           move16 (); 
+
+    test (); 
+    if (sub (thvad->e, p_temp.e) > 0)
+    {
+        comp = 1;                                       move16 (); 
+    }
+    test (); test (); 
+    if ((sub (thvad->e, p_temp.e) == 0) &&
+        (sub (thvad->m, p_temp.m) > 0))
+    {
+        comp = 1;                                       move16 (); 
+    }
+    test (); 
+    if (sub (comp, 1) == 0)
+    {
+        thvad->e = p_temp.e;                            move16 (); 
+        thvad->m = p_temp.m;                            move16 (); 
+    }
+    /*** Normalise and retain rvad[0..8] in memory ***/
+
+    *scal_rvad = scal_rav1;                             move16 (); 
+
+    for (i = 0; i <= 8; i++)
+    {
+        rvad[i] = rav1[i];                              move16 (); 
+    }
+
+    /*** Set adaptcount to adp + 1 ***/
+
+    adaptcount = 9;                                     move16 (); 
+
+    return;
+}
+
+/****************************************************************************
+ *
+ *     FUNCTION:  tone_detection
+ *
+ *     PURPOSE:   Computes the tone flag needed for the threshold
+ *                adaptation decision.
+ *
+ *     INPUTS:    rc[0..3]    reflection coefficients calculated in the
+ *                            speech encoder short term predictor
+ *
+ *     OUTPUTS:   *tone       flag to indicate a periodic signal component
+ *
+ *     RETURN VALUE: none
+ *
+ ***************************************************************************/
+
+void tone_detection (
+    Word16 rc[],
+    Word16 *tone
+)
+{
+    Word32 L_num, L_den, L_temp;
+    Word16 temp, prederr, a[3];
+    Word16 i;
+
+    *tone = 0;                  move16 (); 
+
+    /*** Calculate filter coefficients ***/
+
+    step_up (2, rc, a);
+
+    /*** Calculate ( a[1] * a[1] ) ***/
+
+    temp = shl (a[1], 3);
+    L_den = L_mult (temp, temp);
+
+    /*** Calculate ( 4*a[2] - a[1]*a[1] ) ***/
+
+    L_temp = L_shl (L_deposit_h (a[2]), 3);
+    L_num = L_sub (L_temp, L_den);
+
+    /*** Check if pole frequency is less than 385 Hz ***/
+
+    test (); 
+    if (L_num <= 0)
+    {
+        return;
+    }
+    test (); move16 (); 
+    if (a[1] < 0)
+    {
+        temp = extract_h (L_den);
+        L_den = L_mult (temp, FREQTH);
+
+        L_temp = L_sub (L_num, L_den);
+
+        test (); 
+        if (L_temp < 0)
+        {
+            return;
+        }
+    }
+    /*** Calculate normalised prediction error ***/
+
+    prederr = 0x7fff;           move16 (); 
+
+    for (i = 0; i < 4; i++)
+    {
+        temp = mult (rc[i], rc[i]);
+        temp = sub (0x7fff, temp);
+        prederr = mult (prederr, temp);
+    }
+
+    /*** Test if prediction error is smaller than threshold ***/
+
+    temp = sub (prederr, PREDTH);
+
+    test (); 
+    if (temp < 0)
+    {
+        *tone = 1;              move16 (); 
+    }
+    return;
+}
+
+/****************************************************************************
+ *
+ *     FUNCTION:  vad_decision
+ *
+ *     PURPOSE:   Computes the VAD decision based on the comparison of the
+ *                floating point representations of pvad and thvad.
+ *
+ *     INPUTS:    pvad          filtered signal energy (mantissa+exponent)
+ *                thvad         decision threshold (mantissa+exponent)
+ *
+ *     OUTPUTS:   none
+ *
+ *     RETURN VALUE: vad decision before hangover is added
+ *
+ ***************************************************************************/
+
+Word16 vad_decision (
+    Pfloat pvad,
+    Pfloat thvad
+)
+{
+    Word16 vvad;
+
+    test (); test (); test (); 
+    if (sub (pvad.e, thvad.e) > 0)
+    {
+        vvad = 1;               move16 (); 
+    }
+    else if ((sub (pvad.e, thvad.e) == 0) &&
+               (sub (pvad.m, thvad.m) > 0))
+    {
+        vvad = 1;               move16 (); 
+    }
+    else
+    {
+        vvad = 0;               move16 (); 
+    }
+
+    return vvad;
+}
+
+/****************************************************************************
+ *
+ *     FUNCTION:  vad_hangover
+ *
+ *     PURPOSE:   Computes the final VAD decision for the current frame
+ *                being processed.
+ *
+ *     INPUTS:    vvad           vad decision before hangover is added
+ *
+ *     OUTPUTS:   none
+ *
+ *     RETURN VALUE: vad decision after hangover is added
+ *
+ ***************************************************************************/
+
+Word16 vad_hangover (
+    Word16 vvad
+)
+{
+    test (); 
+    if (sub (vvad, 1) == 0)
+    {
+        burstcount = add (burstcount, 1);
+    }
+    else
+    {
+        burstcount = 0;         move16 (); 
+    }
+
+    test (); 
+    if (sub (burstcount, BURSTCONST) >= 0)
+    {
+        hangcount = HANGCONST;  move16 (); 
+        burstcount = BURSTCONST;move16 (); 
+    }
+    test (); 
+    if (hangcount >= 0)
+    {
+        hangcount = sub (hangcount, 1);
+        return 1;               /* vad = 1 */
+    }
+    return vvad;                /* vad = vvad */
+}
+
+/****************************************************************************
+ *
+ *     FUNCTION:  periodicity_update
+ *
+ *     PURPOSE:   Computes the ptch flag needed for the threshold
+ *                adaptation decision for the next frame.
+ *
+ *     INPUTS:    lags[0..1]       speech encoder long term predictor lags
+ *
+ *     OUTPUTS:   *ptch            Boolean voiced / unvoiced decision
+ *
+ *     RETURN VALUE: none
+ *
+ ***************************************************************************/
+
+void periodicity_update (
+    Word16 lags[],
+    Word16 *ptch
+)
+{
+    Word16 minlag, maxlag, lagcount, temp;
+    Word16 i;
+
+    /*** Run loop for the two halves in the frame ***/
+
+    lagcount = 0;               move16 (); 
+
+    for (i = 0; i <= 1; i++)
+    {
+        /*** Search the maximum and minimum of consecutive lags ***/
+
+        test (); 
+        if (sub (oldlag, lags[i]) > 0)
+        {
+            minlag = lags[i];   move16 (); 
+            maxlag = oldlag;    move16 (); 
+        }
+        else
+        {
+            minlag = oldlag;    move16 (); 
+            maxlag = lags[i];   move16 (); 
+        }
+
+        temp = sub (maxlag, minlag);
+
+        test (); 
+        if (sub (temp, LTHRESH) < 0)
+        {
+            lagcount = add (lagcount, 1);
+        }
+        /*** Save the current LTP lag ***/
+
+        oldlag = lags[i];       move16 (); 
+    }
+
+    /*** Update the veryoldlagcount and oldlagcount ***/
+
+    veryoldlagcount = oldlagcount;
+                                move16 (); 
+    oldlagcount = lagcount;     move16 (); 
+
+    /*** Make ptch decision ready for next frame ***/
+
+    temp = add (oldlagcount, veryoldlagcount);
+
+    test (); 
+    if (sub (temp, NTHRESH) >= 0)
+    {
+        *ptch = 1;              move16 (); 
+    }
+    else
+    {
+        *ptch = 0;              move16 (); 
+    }
+
+    return;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/vad.h	Wed Apr 03 05:31:37 2024 +0000
@@ -0,0 +1,106 @@
+/***************************************************************************
+ *
+ *   File Name: vad.h
+ *
+ *   Purpose:   Contains the prototypes for all functions of voice activity
+ *              detection. Also contains the type definition for the pseudo
+ *              floating point data type.
+ *
+ **************************************************************************/
+
+/* Struct for storing pseudo floating point exponent and mantissa */
+struct _fp
+{
+    Word16 e;          /* exponent */
+    Word16 m;          /* mantissa */
+};
+
+typedef struct _fp Pfloat;
+
+void vad_reset (void);
+
+Word16 vad_computation (
+    Word16 r_h[],
+    Word16 r_l[],
+    Word16 scal_acf,
+    Word16 rc[],
+    Word16 ptch
+);
+
+void energy_computation (
+    Word16 r_h[],
+    Word16 scal_acf,
+    Word16 rvad[],
+    Word16 scal_rvad,
+    Pfloat * acf0,
+    Pfloat * pvad
+);
+
+void acf_averaging (
+    Word16 r_h[],
+    Word16 r_l[],
+    Word16 scal_acf,
+    Word32 L_av0[],
+    Word32 L_av1[]
+);
+
+void predictor_values (
+    Word32 L_av1[],
+    Word16 rav1[],
+    Word16 *scal_rav1
+);
+
+void schur_recursion (
+    Word32 L_av1[],
+    Word16 vpar[]
+);
+
+void step_up (
+    Word16 np,
+    Word16 vpar[],
+    Word16 aav1[]
+);
+
+void compute_rav1 (
+    Word16 aav1[],
+    Word16 rav1[],
+    Word16 *scal_rav1
+);
+
+Word16 spectral_comparison (
+    Word16 rav1[],
+    Word16 scal_rav1,
+    Word32 L_av0[]
+);
+
+void threshold_adaptation (
+    Word16 stat,
+    Word16 ptch,
+    Word16 tone,
+    Word16 rav1[],
+    Word16 scal_rav1,
+    Pfloat pvad,
+    Pfloat acf0,
+    Word16 rvad[],
+    Word16 *scal_rvad,
+    Pfloat * thvad
+);
+
+void tone_detection (
+    Word16 rc[],
+    Word16 *tone
+);
+
+Word16 vad_decision (
+    Pfloat pvad,
+    Pfloat thvad
+);
+
+Word16 vad_hangover (
+    Word16 vvad
+);
+
+void periodicity_update (
+    Word16 lags[],
+    Word16 *ptch
+);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/weight_a.c	Wed Apr 03 05:31:37 2024 +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;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/window2.tab	Wed Apr 03 05:31:37 2024 +0000
@@ -0,0 +1,59 @@
+/* Hamming_cos window for LPC analysis.           */
+
+static const Word16 window_232_8[L_WINDOW] =
+{
+    2621, 2623, 2627, 2634, 2644, 2656, 2671, 2689, 2710, 2734,
+    2760, 2789, 2821, 2855, 2893, 2933, 2975, 3021, 3069, 3120,
+    3173, 3229, 3288, 3350, 3414, 3481, 3550, 3622, 3697, 3774,
+    3853, 3936, 4021, 4108, 4198, 4290, 4385, 4482, 4582, 4684,
+    4788, 4895, 5004, 5116, 5230, 5346, 5464, 5585, 5708, 5833,
+    5960, 6090, 6221, 6355, 6491, 6629, 6769, 6910, 7054, 7200,
+    7348, 7498, 7649, 7803, 7958, 8115, 8274, 8434, 8597, 8761,
+    8926, 9093, 9262, 9432, 9604, 9778, 9952, 10129, 10306, 10485,
+    10665, 10847, 11030, 11214, 11399, 11586, 11773, 11962, 12152, 12342,
+    12534, 12727, 12920, 13115, 13310, 13506, 13703, 13901, 14099, 14298,
+    14497, 14698, 14898, 15100, 15301, 15504, 15706, 15909, 16112, 16316,
+    16520, 16724, 16928, 17132, 17337, 17541, 17746, 17950, 18155, 18359,
+    18564, 18768, 18972, 19175, 19379, 19582, 19785, 19987, 20189, 20390,
+    20591, 20792, 20992, 21191, 21390, 21588, 21785, 21981, 22177, 22372,
+    22566, 22759, 22951, 23143, 23333, 23522, 23710, 23897, 24083, 24268,
+    24451, 24633, 24814, 24994, 25172, 25349, 25525, 25699, 25871, 26042,
+    26212, 26380, 26546, 26711, 26874, 27035, 27195, 27353, 27509, 27664,
+    27816, 27967, 28115, 28262, 28407, 28550, 28691, 28830, 28967, 29102,
+    29234, 29365, 29493, 29619, 29743, 29865, 29985, 30102, 30217, 30330,
+    30440, 30548, 30654, 30757, 30858, 30956, 31052, 31146, 31237, 31326,
+    31412, 31495, 31576, 31655, 31730, 31804, 31874, 31942, 32008, 32071,
+    32131, 32188, 32243, 32295, 32345, 32392, 32436, 32477, 32516, 32552,
+    32585, 32615, 32643, 32668, 32690, 32709, 32726, 32740, 32751, 32759,
+    32765, 32767, 32767, 32097, 30112, 26895, 22576, 17333, 11380, 4962
+};
+
+/* Hamming-cosine window for LPC analysis.           */
+
+static const Word16 window_160_80[L_WINDOW] =
+{
+    2621, 2624, 2633, 2648, 2668, 2695, 2727, 2765, 2809, 2859,
+    2915, 2976, 3043, 3116, 3194, 3279, 3368, 3464, 3565, 3671,
+    3783, 3900, 4023, 4151, 4285, 4423, 4567, 4716, 4870, 5029,
+    5193, 5362, 5535, 5714, 5897, 6084, 6277, 6473, 6674, 6880,
+    7089, 7303, 7521, 7742, 7968, 8197, 8430, 8667, 8907, 9151,
+    9398, 9648, 9902, 10158, 10417, 10680, 10945, 11212, 11482, 11755,
+    12030, 12307, 12586, 12867, 13150, 13435, 13722, 14010, 14299, 14590,
+    14882, 15175, 15469, 15764, 16060, 16356, 16653, 16950, 17248, 17546,
+    17844, 18141, 18439, 18736, 19033, 19330, 19625, 19920, 20214, 20507,
+    20799, 21090, 21380, 21668, 21954, 22239, 22522, 22803, 23083, 23360,
+    23635, 23907, 24177, 24445, 24710, 24972, 25231, 25488, 25741, 25991,
+    26238, 26482, 26722, 26959, 27192, 27422, 27647, 27869, 28087, 28300,
+    28510, 28715, 28916, 29113, 29305, 29493, 29676, 29854, 30028, 30197,
+    30361, 30519, 30673, 30822, 30966, 31105, 31238, 31366, 31489, 31606,
+    31718, 31825, 31926, 32021, 32111, 32195, 32273, 32346, 32413, 32475,
+    32530, 32580, 32624, 32662, 32695, 32721, 32742, 32756, 32765, 32767,
+    32767, 32756, 32720, 32661, 32578, 32471, 32341, 32188, 32012, 31813,
+    31592, 31349, 31084, 30798, 30492, 30165, 29818, 29453, 29068, 28666,
+    28247, 27810, 27358, 26891, 26408, 25913, 25404, 24883, 24350, 23807,
+    23255, 22693, 22124, 21548, 20965, 20378, 19786, 19191, 18593, 17994,
+    17395, 16796, 16199, 15604, 15012, 14424, 13842, 13265, 12696, 12135,
+    11582, 11039, 10507, 9986, 9477, 8981, 8499, 8031, 7579, 7143,
+    6723, 6321, 5937, 5571, 5225, 4898, 4591, 4305, 4041, 3798,
+    3577, 3378, 3202, 3048, 2918, 2812, 2729, 2669, 2633, 2621
+};