/*
 * SpanDSP - a series of DSP components for telephony
 *
 * lpc10_decode.c - LPC10 low bit rate speech codec.
 *
 * Written by Steve Underwood <steveu@coppice.org>
 *
 * Copyright (C) 2006 Steve Underwood
 *
 * All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 2.1,
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * This code is based on the U.S. Department of Defense reference
 * implementation of the LPC-10 2400 bps Voice Coder. They do not
 * exert copyright claims on their code, and it may be freely used.
 */

#if defined(HAVE_CONFIG_H)
#include "config.h"
#endif

#include <stdlib.h>
#include <stdio.h>
#include <inttypes.h>
#include <memory.h>
#if defined(HAVE_TGMATH_H)
#include <tgmath.h>
#endif
#if defined(HAVE_MATH_H)
#include <math.h>
#endif
#if defined(HAVE_STDBOOL_H)
#include <stdbool.h>
#else
#include "spandsp/stdbool.h"
#endif
#include "floating_fudge.h"

#include "spandsp/telephony.h"
#include "spandsp/alloc.h"
#include "spandsp/fast_convert.h"
#include "spandsp/lpc10.h"
#include "spandsp/private/lpc10.h"

#include "lpc10_encdecs.h"

#if !defined(min)
#define min(a,b) ((a) <= (b) ? (a) : (b))
#endif
#if !defined(max)
#define max(a,b) ((a) >= (b) ? (a) : (b))
#endif

/* Pseudo random number generator based on Knuth, Vol 2, p. 27. */
/* lpc10_random - int32_t variable, uniformly distributed over -32768 to 32767 */
static int32_t lpc10_random(lpc10_decode_state_t *s)
{
    int32_t ret_val;

    /* The following is a 16 bit 2's complement addition,
       with overflow checking disabled */
    s->y[s->k] += s->y[s->j];
    ret_val = s->y[s->k];
    if (--s->k < 0)
        s->k = 4;
    if (--s->j < 0)
        s->j = 4;
    return ret_val;
}
/*- End of function --------------------------------------------------------*/

/* Synthesize one pitch epoch */
static void bsynz(lpc10_decode_state_t *s,
                  float coef[],
                  int32_t ip,
                  int32_t *iv,
                  float sout[],
                  float rms,
                  float ratio,
                  float g2pass)
{
    static const int32_t kexc[25] =
    {
          8,  -16,   26, -48,  86, -162, 294, -502, 718, -728, 184,
        672, -610, -672, 184, 728,  718, 502,  294, 162,   86,  48,
         26,   16,    8
    };
    int32_t i;
    int32_t j;
    int32_t k;
    int32_t px;
    float noise[LPC10_MIN_PITCH];
    float pulse;
    float r1;
    float gain;
    float xssq;
    float sscale;
    float xy;
    float sum;
    float ssq;
    float lpi0;
    float hpi0;

    /* MAXPIT + MAXORD = 166 */
    /* Calculate history scale factor XY and scale filter state */
    /* Computing MIN */
    r1 = s->rmso_bsynz/(rms + 1.0e-6f);
    xy = min(r1, 8.0f);
    s->rmso_bsynz = rms;
    for (i = 0;  i < LPC10_ORDER;  i++)
        s->exc2[i] = s->exc2[s->ipo + i]*xy;
    s->ipo = ip;
    if (*iv == 0)
    {
        /* Generate white noise for unvoiced */
        for (i = 0;  i < ip;  i++)
            s->exc[LPC10_ORDER + i] = (float) (lpc10_random(s)/64);
        /* Impulse double excitation for plosives */
        px = (lpc10_random(s) + 32768)*(ip - 1)/65536 + LPC10_ORDER + 1;
        r1 = ratio/4.0f;
        pulse = r1*342;
        if (pulse > 2.0e3f)
            pulse = 2.0e3f;
        s->exc[px - 1] += pulse;
        s->exc[px] -= pulse;
    }
    else
    {
        sscale = sqrtf((float) ip)/6.928f;
        for (i = 0;  i < ip;  i++)
        {
            s->exc[LPC10_ORDER + i] = 0.0f;
            if (i < 25)
                s->exc[LPC10_ORDER + i] = sscale*kexc[i];
            lpi0 = s->exc[LPC10_ORDER + i];
            s->exc[LPC10_ORDER + i] = s->exc[LPC10_ORDER + i]*0.125f + s->lpi[0]*0.75f + s->lpi[1]*0.125f;
            s->lpi[1] = s->lpi[0];
            s->lpi[0] = lpi0;
        }
        for (i = 0;  i < ip;  i++)
        {
            hpi0 = lpc10_random(s)/64.0f;
            noise[i] = hpi0*-0.125f + s->hpi[0]*0.25f + s->hpi[1]*-0.125f;
            s->hpi[1] = s->hpi[0];
            s->hpi[0] = hpi0;
        }
        for (i = 0;  i < ip;  i++)
            s->exc[LPC10_ORDER + i] += noise[i];
    }
    /* Synthesis filters: */
    /* Modify the excitation with all-zero filter 1 + G*SUM */
    xssq = 0.0f;
    for (i = 0;  i < ip;  i++)
    {
        k = LPC10_ORDER + i;
        sum = 0.0f;
        for (j = 0;  j < LPC10_ORDER;  j++)
            sum += coef[j]*s->exc[k - j - 1];
        sum *= g2pass;
        s->exc2[k] = sum + s->exc[k];
    }
    /* Synthesize using the all pole filter 1/(1 - SUM) */
    for (i = 0;  i < ip;  i++)
    {
        k = LPC10_ORDER + i;
        sum = 0.0f;
        for (j = 0;  j < LPC10_ORDER;  j++)
            sum += coef[j]*s->exc2[k - j - 1];
        s->exc2[k] = sum + s->exc2[k];
        xssq += s->exc2[k]*s->exc2[k];
    }
    /* Save filter history for next epoch */
    for (i = 0;  i < LPC10_ORDER;  i++)
    {
        s->exc[i] = s->exc[ip + i];
        s->exc2[i] = s->exc2[ip + i];
    }
    /* Apply gain to match RMS */
    ssq = rms*rms*ip;
    gain = sqrtf(ssq/xssq);
    for (i = 0;  i < ip;  i++)
        sout[i] = gain*s->exc2[LPC10_ORDER + i];
}
/*- End of function --------------------------------------------------------*/

/* Synthesize a single pitch epoch */
static int pitsyn(lpc10_decode_state_t *s,
                  int voice[2],
                  int32_t *pitch,
                  float rms,
                  float rc[LPC10_ORDER],
                  int32_t ivuv[16],
                  int32_t ipiti[16],
                  float rmsi[16],
                  float rci[16*LPC10_ORDER],
                  int32_t *nout,
                  float *ratio)
{
    int32_t i;
    int32_t j;
    int32_t vflag;
    int32_t jused;
    int32_t lsamp;
    int32_t ip;
    int32_t nl;
    int32_t ivoice;
    int32_t istart;
    float r1;
    float alrn;
    float alro;
    float yarc[10];
    float prop;
    float slope;
    float uvpit;
    float xxy;
    float msix;

    if (rms < 1.0f)
        rms = 1.0f;
    if (s->rmso < 1.0f)
        s->rmso = 1.0f;
    uvpit = 0.0f;
    *ratio = rms/(s->rmso + 8.0f);
    if (s->first_pitsyn)
    {
        ivoice = voice[1];
        if (ivoice == 0)
            *pitch = LPC10_SAMPLES_PER_FRAME/4;
        *nout = LPC10_SAMPLES_PER_FRAME / *pitch;
        s->jsamp = LPC10_SAMPLES_PER_FRAME - *nout * *pitch;

        for (i = 0;  i < *nout;  i++)
        {
            for (j = 0;  j < LPC10_ORDER;  j++)
                rci[j + i*LPC10_ORDER] = rc[j];
            ivuv[i] = ivoice;
            ipiti[i] = *pitch;
            rmsi[i] = rms;
        }
        s->first_pitsyn = false;
    }
    else
    {
        vflag = 0;
        lsamp = LPC10_SAMPLES_PER_FRAME + s->jsamp;
        *nout = 0;
        jused = 0;
        istart = 1;
        if (voice[0] == s->ivoico  &&  voice[1] == voice[0])
        {
            if (voice[1] == 0)
            {
                /* SSUV - -   0  ,  0  ,  0 */
                *pitch = LPC10_SAMPLES_PER_FRAME/4;
                s->ipito = *pitch;
                if (*ratio > 8.0f)
                    s->rmso = rms;
            }
            /* SSVC - -   1  ,  1  ,  1 */
            slope = (*pitch - s->ipito)/(float) lsamp;
            ivoice = voice[1];
        }
        else
        {
            if (s->ivoico != 1)
            {
                if (s->ivoico == voice[0])
                {
                    /* UV2VC2 - -  0  ,  0  ,  1 */
                    nl = lsamp - LPC10_SAMPLES_PER_FRAME/4;
                }
                else
                {
                    /* UV2VC1 - -  0  ,  1  ,  1 */
                    nl = lsamp - LPC10_SAMPLES_PER_FRAME*3/4;
                }
                ipiti[0] = nl/2;
                ipiti[1] = nl - ipiti[0];
                ivuv[0] = 0;
                ivuv[1] = 0;
                rmsi[0] = s->rmso;
                rmsi[1] = s->rmso;
                for (i = 0;  i < LPC10_ORDER;  i++)
                {
                    rci[i] = s->rco[i];
                    rci[i + LPC10_ORDER] = s->rco[i];
                    s->rco[i] = rc[i];
                }
                *nout = 2;
                s->ipito = *pitch;
                jused = nl;
                istart = nl + 1;
                ivoice = 1;
            }
            else
            {
                if (s->ivoico != voice[0])
                {
                    /* VC2UV1 - -   1  ,  0  ,  0 */
                    lsamp = LPC10_SAMPLES_PER_FRAME/4 + s->jsamp;
                }
                else
                {
                    /* VC2UV2 - -   1  ,  1  ,  0 */
                    lsamp = LPC10_SAMPLES_PER_FRAME*3/4 + s->jsamp;
                }
                for (i = 0;  i < LPC10_ORDER;  i++)
                {
                    yarc[i] = rc[i];
                    rc[i] = s->rco[i];
                }
                ivoice = 1;
                vflag = 1;
            }
            slope = 0.0f;
        }
        /* Here is the value of most variables that are used below, depending on */
        /* the values of IVOICO, VOICE(1), and VOICE(2).  VOICE(1) and VOICE(2) */
        /* are input arguments, and IVOICO is the value of VOICE(2) on the */
        /* previous call (see notes for the IF (NOUT .NE. 0) statement near the */
        /* end).  Each of these three values is either 0 or 1.  These three */
        /* values below are given as 3-bit long strings, in the order IVOICO, */
        /* VOICE(1), and VOICE(2).  It appears that the code above assumes that */
        /* the bit sequences 010 and 101 never occur, but I wonder whether a */
        /* large enough number of bit errors in the channel could cause such a */
        /* thing to happen, and if so, could that cause NOUT to ever go over 11? */

        /* Note that all of the 180 values in the table are floatly LFRAME, but */
        /* 180 has fewer characters, and it makes the table a little more */
        /* concrete.  If LFRAME is ever changed, keep this in mind.  Similarly, */
        /* 135's are 3*LFRAME/4, and 45's are LFRAME/4.  If LFRAME is not a */
        /* multiple of 4, then the 135 for NL-JSAMP is actually LFRAME-LFRAME/4, */
        /* and the 45 for NL-JSAMP is actually LFRAME-3*LFRAME/4. */

        /* Note that LSAMP-JSAMP is given as the variable.  This was just for */
        /* brevity, to avoid adding "+JSAMP" to all of the column entries. */
        /* Similarly for NL-JSAMP. */

        /* Variable    | 000  001    011,010  111       110       100,101 */
        /* ------------+-------------------------------------------------- */
        /* ISTART      | 1    NL+1   NL+1     1         1         1 */
        /* LSAMP-JSAMP | 180  180    180      180       135       45 */
        /* IPITO       | 45   PITCH  PITCH    oldPITCH  oldPITCH  oldPITCH */
        /* SLOPE       | 0    0      0        seebelow  0         0 */
        /* JUSED       | 0    NL     NL       0         0         0 */
        /* PITCH       | 45   PITCH  PITCH    PITCH     PITCH     PITCH */
        /* NL-JSAMP    | --   135    45       --        --        -- */
        /* VFLAG       | 0    0      0        0         1         1 */
        /* NOUT        | 0    2      2        0         0         0 */
        /* IVOICE      | 0    1      1        1         1         1 */

        /* while_loop  | once once   once     once      twice     twice */

        /* ISTART      | --   --     --       --        JUSED+1   JUSED+1 */
        /* LSAMP-JSAMP | --   --     --       --        180       180 */
        /* IPITO       | --   --     --       --        oldPITCH  oldPITCH */
        /* SLOPE       | --   --     --       --        0         0 */
        /* JUSED       | --   --     --       --        ??        ?? */
        /* PITCH       | --   --     --       --        PITCH     PITCH */
        /* NL-JSAMP    | --   --     --       --        --        -- */
        /* VFLAG       | --   --     --       --        0         0 */
        /* NOUT        | --   --     --       --        ??        ?? */
        /* IVOICE      | --   --     --       --        0         0 */

        /* UVPIT is always 0.0 on the first pass through the DO WHILE (true)
           loop below. */

        /* The only possible non-0 value of SLOPE (in column 111) is
           (PITCH-IPITO)/FLOAT(LSAMP) */

        /* Column 101 is identical to 100.  Any good properties we can prove
           for 100 will also hold for 101.  Similarly for 010 and 011. */

        /* synths() calls this subroutine with PITCH restricted to the range 20 to
           156.  IPITO is similarly restricted to this range, after the first
           call.  IP below is also restricted to this range, given the
           definitions of IPITO, SLOPE, UVPIT, and that I is in the range ISTART
           to LSAMP. */

        for (;;)
        {
            for (i = istart;  i <= lsamp;  i++)
            {
                r1 = s->ipito + slope*i;
                ip = (int32_t) (r1 + 0.5f);
                if (uvpit != 0.0f)
                    ip = (int32_t) uvpit;
                if (ip <= i - jused)
                {
                    ipiti[*nout] = ip;
                    *pitch = ip;
                    ivuv[*nout] = ivoice;
                    jused += ip;
                    prop = (jused - ip/2)/(float) lsamp;
                    for (j = 0;  j < LPC10_ORDER;  j++)
                    {
                        alro = logf((s->rco[j] + 1)/(1 - s->rco[j]));
                        alrn = logf((rc[j] + 1)/(1 - rc[j]));
                        xxy = alro + prop*(alrn - alro);
                        xxy = expf(xxy);
                        rci[j + *nout*LPC10_ORDER] = (xxy - 1.0f)/(xxy + 1.0f);
                    }
                    msix = logf(rms) - logf(s->rmso);
                    msix = prop*msix;
                    msix = logf(s->rmso) + msix;
                    rmsi[*nout] = expf(msix);
                    (*nout)++;
                }
            }
            if (vflag != 1)
                break;

            vflag = 0;
            istart = jused + 1;
            lsamp = LPC10_SAMPLES_PER_FRAME + s->jsamp;
            slope = 0.0f;
            ivoice = 0;
            uvpit = (float) ((lsamp - istart)/2);
            if (uvpit > 90.0f)
                uvpit /= 2;
            s->rmso = rms;
            for (i = 0;  i < LPC10_ORDER;  i++)
            {
                rc[i] = yarc[i];
                s->rco[i] = yarc[i];
            }
        }
        s->jsamp = lsamp - jused;
    }
    if (*nout != 0)
    {
        s->ivoico = voice[1];
        s->ipito = *pitch;
        s->rmso = rms;
        for (i = 0;  i < LPC10_ORDER;  i++)
            s->rco[i] = rc[i];
    }
    return 0;
}
/*- End of function --------------------------------------------------------*/

static void deemp(lpc10_decode_state_t *s, float x[], int len)
{
    int i;
    float r1;
    float dei0;

    for (i = 0;  i < len;  i++)
    {
        dei0 = x[i];
        r1 = x[i] - s->dei[0]*1.9998f + s->dei[1];
        x[i] = r1 + s->deo[0]*2.5f - s->deo[1]*2.0925f + s->deo[2]*0.585f;
        s->dei[1] = s->dei[0];
        s->dei[0] = dei0;
        s->deo[2] = s->deo[1];
        s->deo[1] = s->deo[0];
        s->deo[0] = x[i];
    }
}
/*- End of function --------------------------------------------------------*/

/* Convert reflection coefficients to predictor coefficients */
static float reflection_coeffs_to_predictor_coeffs(float rc[], float pc[], float gprime)
{
    float temp[10];
    float g2pass;
    int i;
    int j;

    g2pass = 1.0f;
    for (i = 0;  i < LPC10_ORDER;  i++)
        g2pass *= 1.0f - rc[i]*rc[i];
    g2pass = gprime*sqrtf(g2pass);
    pc[0] = rc[0];
    for (i = 1;  i < LPC10_ORDER;  i++)
    {
        for (j = 0;  j < i;  j++)
            temp[j] = pc[j] - rc[i]*pc[i - j - 1];
        for (j = 0;  j < i;  j++)
            pc[j] = temp[j];
        pc[i] = rc[i];
    }
    return g2pass;
}
/*- End of function --------------------------------------------------------*/

static int synths(lpc10_decode_state_t *s,
                  int voice[2],
                  int32_t *pitch,
                  float rms,
                  float rc[LPC10_ORDER],
                  float speech[])
{
    int32_t ivuv[16];
    int32_t ipiti[16];
    int32_t nout;
    int32_t i;
    int32_t j;
    float rmsi[16];
    float ratio;
    float g2pass;
    float pc[LPC10_ORDER];
    float rci[16*LPC10_ORDER];

    *pitch = max(min(*pitch, LPC10_MIN_PITCH), LPC10_MAX_PITCH);
    for (i = 0;  i < LPC10_ORDER;  i++)
        rc[i] = max(min(rc[i], 0.99f), -0.99f);
    pitsyn(s, voice, pitch, rms, rc, ivuv, ipiti, rmsi, rci, &nout, &ratio);
    if (nout > 0)
    {
        for (j = 0;  j < nout;  j++)
        {
            /* Add synthesized speech for pitch period J to the end of s->buf. */
            g2pass = reflection_coeffs_to_predictor_coeffs(&rci[j*LPC10_ORDER], pc, 0.7f);
            bsynz(s, pc, ipiti[j], &ivuv[j], &s->buf[s->buflen], rmsi[j], ratio, g2pass);
            deemp(s, &s->buf[s->buflen], ipiti[j]);
            s->buflen += ipiti[j];
        }
        /* Copy first MAXFRM samples from BUF to output array speech (scaling them),
           and then remove them from the beginning of s->buf. */
        for (i = 0;  i < LPC10_SAMPLES_PER_FRAME;  i++)
            speech[i] = s->buf[i]/4096.0f;
        s->buflen -= LPC10_SAMPLES_PER_FRAME;
        for (i = 0;  i < s->buflen;  i++)
            s->buf[i] = s->buf[i + LPC10_SAMPLES_PER_FRAME];
    }
    return 0;
}
/*- End of function --------------------------------------------------------*/

static void lpc10_unpack(lpc10_frame_t *t, const uint8_t ibits[])
{
    static const int bit[10] =
    {
        2, 4, 8, 8, 8, 8, 16, 16, 16, 16
    };
    static const int iblist[53] =
    {
        13, 12, 11,  1,  2, 13, 12, 11,  1,  2,
        13, 10, 11,  2,  1, 10, 13, 12, 11, 10,
         2, 13, 12, 11, 10,  2,  1, 12,  7,  6,
         1, 10,  9,  8,  7,  4,  6,  9,  8,  7,
         5,  1,  9,  8,  4,  6,  1,  5,  9,  8,
         7,  5,  6
    };
    int32_t itab[13];
    int x;
    int i;

    /* ibits is 54 bits of LPC data ordered as follows: */
    /*     R1-0, R2-0, R3-0,  P-0,  A-0, */
    /*     R1-1, R2-1, R3-1,  P-1,  A-1, */
    /*     R1-2, R4-0, R3-2,  A-2,  P-2, R4-1, */
    /*     R1-3, R2-2, R3-3, R4-2,  A-3, */
    /*     R1-4, R2-3, R3-4, R4-3,  A-4, */
    /*      P-3, R2-4, R7-0, R8-0,  P-4, R4-4, */
    /*     R5-0, R6-0, R7-1,R10-0, R8-1, */
    /*     R5-1, R6-1, R7-2, R9-0,  P-5, */
    /*     R5-2, R6-2,R10-1, R8-2,  P-6, R9-1, */
    /*     R5-3, R6-3, R7-3, R9-2, R8-3, SYNC */

    /* Reconstruct ITAB */
    for (i = 0;  i < 13;  i++)
        itab[i] = 0;
    for (i = 0;  i < 53;  i++)
    {
        x = 52 - i;
        x = (ibits[x >> 3] >> (7 - (x & 7))) & 1;
        itab[iblist[52 - i] - 1] = (itab[iblist[52 - i] - 1] << 1) | x;
    }
    /* Sign extend the RC's */
    for (i = 0;  i < LPC10_ORDER;  i++)
    {
        if ((itab[i + 3] & bit[i]))
            itab[i + 3] -= (bit[i] << 1);
    }
    /* Restore variables */
    t->ipitch = itab[0];
    t->irms = itab[1];
    for (i = 0;  i < LPC10_ORDER;  i++)
        t->irc[i] = itab[LPC10_ORDER - 1 - i + 3];
}
/*- End of function --------------------------------------------------------*/

/* Hamming 8, 4 decoder - can correct 1 out of seven bits
   and can detect up to two errors. */

/* This subroutine is entered with an eight bit word in INPUT.  The 8th */
/* bit is parity and is stripped off.  The remaining 7 bits address the */
/* hamming 8, 4 table and the output OUTPUT from the table gives the 4 */
/* bits of corrected data.  If bit 4 is set,  no error was detected. */
/* ERRCNT is the number of errors counted. */

static int32_t hamming_84_decode(int32_t input, int *errcnt)
{
    static const uint8_t dactab[128] =
    {
        16,  0,  0,  3,  0,  5, 14,  7,  0,  9, 14, 11, 14, 13, 30, 14,
         0,  9,  2,  7,  4,  7,  7, 23,  9, 25, 10,  9, 12,  9, 14,  7,
         0,  5,  2, 11,  5, 21,  6,  5,  8, 11, 11, 27, 12,  5, 14, 11,
         2,  1, 18,  2, 12,  5,  2,  7, 12,  9,  2, 11, 28, 12, 12, 15,
         0,  3,  3, 19,  4, 13,  6,  3,  8, 13, 10,  3, 13, 29, 14, 13,
         4,  1, 10,  3, 20,  4,  4,  7, 10,  9, 26, 10,  4, 13, 10, 15,
         8,  1,  6,  3,  6,  5, 22,  6, 24,  8,  8, 11,  8, 13,  6, 15,
         1, 17 , 2,  1,  4,  1,  6, 15,  8,  1, 10, 15, 12, 15, 15, 31
    };
    int i;
    int parity;
    int32_t output;

    parity = input & 255;
    parity ^= parity >> 4;
    parity ^= parity >> 2;
    parity ^= parity >> 1;
    parity &= 1;
    i = dactab[input & 127];
    output = i & 15;
    if ((i & 16))
    {
        /* No errors detected in seven bits */
        if (parity)
            (*errcnt)++;
    }
    else
    {
        /* One or two errors detected */
        (*errcnt)++;
        if (parity == 0)
        {
            /* Two errors detected */
            (*errcnt)++;
            output = -1;
        }
    }
    return output;
}
/*- End of function --------------------------------------------------------*/

static int32_t median(int32_t d1, int32_t d2, int32_t d3)
{
    int32_t ret_val;

    ret_val = d2;
    if (d2 > d1  &&  d2 > d3)
    {
        ret_val = d1;
        if (d3 > d1)
            ret_val = d3;
    }
    else if (d2 < d1  &&  d2 < d3)
    {
        ret_val = d1;
        if (d3 < d1)
            ret_val = d3;
    }
    return ret_val;
}
/*- End of function --------------------------------------------------------*/

static void decode(lpc10_decode_state_t *s,
                   lpc10_frame_t *t,
                   int voice[2],
                   int32_t *pitch,
                   float *rms,
                   float rc[])
{
    static const int32_t ivtab[32] =
    {
        24960, 24960, 24960, 24960, 25480, 25480, 25483, 25480,
        16640,  1560,  1560,  1560, 16640,  1816,  1563,  1560,
        24960, 24960, 24859, 24856, 26001, 25881, 25915, 25913,
         1560,  1560,  7800,  3640,  1561,  1561,  3643,  3641
    };
    static const float corth[32] =
    {
        32767.0f, 10.0f, 5.0f, 0.0f, 32767.0f,  8.0f, 4.0f, 0.0f,
           32.0f,  6.4f, 3.2f, 0.0f,    32.0f,  6.4f, 3.2f, 0.0f,
           32.0f, 11.2f, 6.4f, 0.0f,    32.0f, 11.2f, 6.4f, 0.0f,
           16.0f,  5.6f, 3.2f, 0.0f,    16.0f,  5.6f, 3.2f, 0.0f
    };
    static const int32_t detau[128] =
    {
          0,   0,   0,   3,   0,   3,   3,  31,
          0,   3,   3,  21,   3,   3,  29,  30,
          0,   3,   3,  20,   3,  25,  27,  26,
          3,  23,  58,  22,   3,  24,  28,   3,
          0,   3,   3,   3,   3,  39,  33,  32,
          3,  37,  35,  36,   3,  38,  34,   3,
          3,  42,  46,  44,  50,  40,  48,   3,
         54,   3,  56,   3,  52,   3,   3,   1,
          0,   3,   3, 108,   3,  78, 100, 104,
          3,  84,  92,  88, 156,  80,  96,   3,
          3,  74,  70,  72,  66,  76,  68,   3,
         62,   3,  60,   3,  64,   3,   3,   1,
          3, 116, 132, 112, 148, 152,   3,   3,
        140,   3, 136,   3, 144,   3,   3,   1,
        124, 120, 128,   3,   3,   3,   3,   1,
          3,   3,   3,   1,   3,   1,   1,   1
    };
    static const int32_t rmst[64] =
    {
        1024,  936,  856,  784,  718,  656,  600,  550,
         502,  460,  420,  384,  352,  328,  294,  270,
         246,  226,  206,  188,  172,  158,  144,  132,
         120,  110,  102,   92,   84,   78,   70,   64,
          60,   54,   50,   46,   42,   38,   34,   32,
          30,   26,   24,   22,   20,   18,   17,   16,
          15,   14,   13,   12,   11,   10,    9,    8,
           7,    6,    5,    4,    3,    2,    1,    0
    };
    static const int32_t detab7[32] =
    {
          4,  11,  18,  25,  32,  39,  46,  53,
         60,  66,  72,  77,  82,  87,  92,  96,
        101, 104, 108, 111, 114, 115, 117, 119,
        121, 122, 123, 124, 125, 126, 127, 127
    };
    static const float descl[8] =
    {
        0.6953f, 0.625f, 0.5781f, 0.5469f, 0.5312f, 0.5391f, 0.4688f, 0.3828f
    };
    static const int32_t deadd[8] =
    {
        1152, -2816, -1536, -3584, -1280, -2432, 768, -1920
    };
    static const int32_t qb[8] =
    {
        511, 511, 1023, 1023, 1023, 1023, 2047, 4095
    };
    static const int32_t nbit[10] =
    {
        8, 8, 5, 5, 4, 4, 4, 4, 3, 2
    };
    static const int32_t zrc[10] =
    {
        0, 0, 0, 0, 0, 3, 0, 2, 0, 0
    };
    static const int32_t bit[5] =
    {
        2, 4, 8, 16, 32
    };
    int32_t ipit;
    int32_t iout;
    int32_t i;
    int32_t icorf;
    int32_t index;
    int32_t ivoic;
    int32_t ixcor;
    int32_t i1;
    int32_t i2;
    int32_t i4;
    int32_t ishift;
    int32_t lsb;
    int errcnt;

    /* If no error correction, do pitch and voicing then jump to decode */
    i4 = detau[t->ipitch];
    if (!s->error_correction)
    {
        voice[0] = 1;
        voice[1] = 1;
        if (t->ipitch <= 1)
            voice[0] = 0;
        if (t->ipitch == 0  ||  t->ipitch == 2)
            voice[1] = 0;
        if (i4 <= 4)
            i4 = s->iptold;
        *pitch = i4;
        if (voice[0] == 1  &&  voice[1] == 1)
            s->iptold = *pitch;
        if (voice[0] != voice[1])
            *pitch = s->iptold;
    }
    else
    {
        /* Do error correction pitch and voicing */
        if (i4 > 4)
        {
            s->dpit[0] = i4;
            ivoic = 2;
            s->iavgp = (s->iavgp*15 + i4 + 8)/16;
        }
        else
        {
            s->dpit[0] = s->iavgp;
            ivoic = i4;
        }
        s->drms[0] = t->irms;
        for (i = 0;  i < LPC10_ORDER;  i++)
            s->drc[i][0] = t->irc[i];
        /* Determine index to IVTAB from V/UV decision */
        /* If error rate is high then use alternate table */
        index = (s->ivp2h << 4) + (s->iovoic << 2) + ivoic + 1;
        i1 = ivtab[index - 1];
        ipit = i1 & 3;
        icorf = i1 >> 3;
        if (s->erate < 2048)
            icorf /= 64;
        /* Determine error rate:  4=high    1=low */
        ixcor = 4;
        if (s->erate < 2048)
            ixcor = 3;
        if (s->erate < 1024)
            ixcor = 2;
        if (s->erate < 128)
            ixcor = 1;
        /* Voice/unvoice decision determined from bits 0 and 1 of IVTAB */
        voice[0] = icorf/2 & 1;
        voice[1] = icorf & 1;
        /* Skip decoding on first frame because present data not yet available */
        if (s->first)
        {
            s->first = false;
            /* Assign PITCH a "default" value on the first call, since */
            /* otherwise it would be left uninitialized.  The two lines */
            /* below were copied from above, since it seemed like a */
            /* reasonable thing to do for the first call. */
            if (i4 <= 4)
                i4 = s->iptold;
            *pitch = i4;
        }
        else
        {
            /* If bit 4 of ICORF is set then correct RMS and RC(1) - RC(4). */
            /* Determine error rate and correct errors using a Hamming 8,4 code */
            /* during transition of unvoiced frames.  If IOUT is negative, */
            /* more than 1 error occurred, use previous frame's parameters. */
            if ((icorf & bit[3]) != 0)
            {
                errcnt = 0;
                lsb = s->drms[1] & 1;
                index = (s->drc[7][1] << 4) + s->drms[1]/2;
                iout = hamming_84_decode(index, &errcnt);
                s->drms[1] = s->drms[2];
                if (iout >= 0)
                    s->drms[1] = (iout << 1) + lsb;
                for (i = 1;  i <= 4;  i++)
                {
                    if (i == 1)
                        i1 = ((s->drc[8][1] & 7) << 1) + (s->drc[9][1] & 1);
                    else
                        i1 = s->drc[8 - i][1] & 15;
                    i2 = s->drc[4 - i][1] & 31;
                    lsb = i2 & 1;
                    index = (i1 << 4) + (i2 >> 1);
                    iout = hamming_84_decode(index, &errcnt);
                    if (iout >= 0)
                    {
                        iout = (iout << 1) + lsb;
                        if ((iout & 16) == 16)
                            iout -= 32;
                    }
                    else
                    {
                        iout = s->drc[4 - i][2];
                    }
                    s->drc[4 - i][1] = iout;
                }
                /* Determine error rate */
                s->erate = (int32_t) (s->erate*0.96875f + errcnt*102.0f);
            }
            /* Get unsmoothed RMS, RC's, and PITCH */
            t->irms = s->drms[1];
            for (i = 0;  i < LPC10_ORDER;  i++)
                t->irc[i] = s->drc[i][1];
            if (ipit == 1)
                s->dpit[1] = s->dpit[2];
            if (ipit == 3)
                s->dpit[1] = s->dpit[0];
            *pitch = s->dpit[1];
            /* If bit 2 of ICORF is set then smooth RMS and RC's, */
            if ((icorf & bit[1]) != 0)
            {
                if ((float) abs(s->drms[1] - s->drms[0]) >= corth[ixcor + 3]
                    &&
                    (float) abs(s->drms[1] - s->drms[2]) >= corth[ixcor + 3])
                {
                    t->irms = median(s->drms[2], s->drms[1], s->drms[0]);
                }
                for (i = 0;  i < 6;  i++)
                {
                    if ((float) abs(s->drc[i][1] - s->drc[i][0]) >= corth[ixcor + ((i + 3) << 2) - 5]
                        &&
                        (float) abs(s->drc[i][1] - s->drc[i][2]) >= corth[ixcor + ((i + 3) << 2) - 5])
                    {
                        t->irc[i] = median(s->drc[i][2], s->drc[i][1], s->drc[i][0]);
                    }
                }
            }
            /* If bit 3 of ICORF is set then smooth pitch */
            if ((icorf & bit[2]) != 0)
            {
                if ((float) abs(s->dpit[1] - s->dpit[0]) >= corth[ixcor - 1]
                    &&
                    (float) abs(s->dpit[1] - s->dpit[2]) >= corth[ixcor - 1])
                {
                    *pitch = median(s->dpit[2], s->dpit[1], s->dpit[0]);
                }
            }
            /* If bit 5 of ICORF is set then RC(5) - RC(10) are loaded with
               values so that after quantization bias is removed in decode
               the values will be zero. */
        }
        if ((icorf & bit[4]) != 0)
        {
            for (i = 4;  i < LPC10_ORDER;  i++)
                t->irc[i] = zrc[i];
        }
        /* Housekeeping  - one frame delay */
        s->iovoic = ivoic;
        s->ivp2h = voice[1];
        s->dpit[2] = s->dpit[1];
        s->dpit[1] = s->dpit[0];
        s->drms[2] = s->drms[1];
        s->drms[1] = s->drms[0];
        for (i = 0;  i < LPC10_ORDER;  i++)
        {
            s->drc[i][2] = s->drc[i][1];
            s->drc[i][1] = s->drc[i][0];
        }
    }
    /* Decode RMS */
    t->irms = rmst[(31 - t->irms)*2];
    /* Decode RC(1) and RC(2) from log-area-ratios */
    /* Protect from illegal coded value (-16) caused by bit errors */
    for (i = 0;  i < 2;  i++)
    {
        i2 = t->irc[i];
        i1 = 0;
        if (i2 < 0)
        {
            i1 = 1;
            i2 = -i2;
            if (i2 > 15)
                i2 = 0;
        }
        i2 = detab7[i2*2];
        if (i1 == 1)
            i2 = -i2;
        ishift = 15 - nbit[i];
        t->irc[i] = i2*pow_ii(2, ishift);
    }
    /* Decode RC(3)-RC(10) to sign plus 14 bits */
    for (i = 2;  i < LPC10_ORDER;  i++)
    {
        ishift = 15 - nbit[i];
        i2 = t->irc[i]*pow_ii(2, ishift) + qb[i - 2];
        t->irc[i] = (int32_t) (i2*descl[i - 2] + deadd[i - 2]);
    }
    /* Scale RMS and RC's to floats */
    *rms = (float) t->irms;
    for (i = 0;  i < LPC10_ORDER;  i++)
        rc[i] = t->irc[i]/16384.0f;
}
/*- End of function --------------------------------------------------------*/

SPAN_DECLARE(lpc10_decode_state_t *) lpc10_decode_init(lpc10_decode_state_t *s, int error_correction)
{
    static const int16_t rand_init[] =
    {
        -21161,
         -8478,
         30892,
        -10216,
         16950
    };
    int i;
    int j;

    if (s == NULL)
    {
        if ((s = (lpc10_decode_state_t *) span_alloc(sizeof(*s))) == NULL)
            return NULL;
    }

    s->error_correction = error_correction;

    /* State used by function decode */
    s->iptold = 60;
    s->first = true;
    s->ivp2h = 0;
    s->iovoic = 0;
    s->iavgp = 60;
    s->erate = 0;
    for (i = 0;  i < 3;  i++)
    {
        for (j = 0;  j < 10;  j++)
            s->drc[j][i] = 0;
        s->dpit[i] = 0;
        s->drms[i] = 0;
    }

    /* State used by function synths */
    for (i = 0;  i < 360;  i++)
        s->buf[i] = 0.0f;
    s->buflen = LPC10_SAMPLES_PER_FRAME;

    /* State used by function pitsyn */
    s->rmso = 1.0f;
    s->first_pitsyn = true;

    /* State used by function bsynz */
    s->ipo = 0;
    for (i = 0;  i < 166;  i++)
    {
        s->exc[i] = 0.0f;
        s->exc2[i] = 0.0f;
    }
    for (i = 0;  i < 3;  i++)
    {
        s->lpi[i] = 0.0f;
        s->hpi[i] = 0.0f;
    }
    s->rmso_bsynz = 0.0f;

    /* State used by function lpc10_random */
    s->j = 1;
    s->k = 4;
    for (i = 0;  i < 5;  i++)
        s->y[i] = rand_init[i];

    /* State used by function deemp */
    for (i = 0;  i < 2;  i++)
        s->dei[i] = 0.0f;
    for (i = 0;  i < 3;  i++)
        s->deo[i] = 0.0f;

    return s;
}
/*- End of function --------------------------------------------------------*/

SPAN_DECLARE(int) lpc10_decode_release(lpc10_decode_state_t *s)
{
    return 0;
}
/*- End of function --------------------------------------------------------*/

SPAN_DECLARE(int) lpc10_decode_free(lpc10_decode_state_t *s)
{
    span_free(s);
    return 0;
}
/*- End of function --------------------------------------------------------*/

SPAN_DECLARE(int) lpc10_decode(lpc10_decode_state_t *s, int16_t amp[], const uint8_t code[], int len)
{
    int voice[2];
    int32_t pitch;
    float speech[LPC10_SAMPLES_PER_FRAME];
    float rc[LPC10_ORDER];
    lpc10_frame_t frame;
    float rms;
    int i;
    int j;
    int base;

    /* Decode 54 bits in 7 bytes to LPC10_SAMPLES_PER_FRAME speech samples. */
    len /= 7;
    for (i = 0;  i < len;  i++)
    {
        lpc10_unpack(&frame, &code[i*7]);
        decode(s, &frame, voice, &pitch, &rms, rc);
        synths(s, voice, &pitch, rms, rc, speech);
        base = i*LPC10_SAMPLES_PER_FRAME;
        for (j = 0;  j < LPC10_SAMPLES_PER_FRAME;  j++)
            amp[base + j] = (int16_t) lfastrintf(32768.0f*speech[j]);
    }

    return len*LPC10_SAMPLES_PER_FRAME;
}
/*- End of function --------------------------------------------------------*/
/*- End of file ------------------------------------------------------------*/
