/***************************************************************************
 *
 *  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 "sig_proc.h"
#include "codec.h"
#include "cnst.h"


/*---------------------------------------------------------------*
 *   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];


/***************************************************************************
 *
 *   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;
}

/***************************************************************************
 *
 *   FUNCTION:  Decoder_12k2
 *
 *   PURPOSE:   Speech decoder routine.
 *
 ***************************************************************************/

void Decoder_12k2 (
    Word16 parm[], /* input : vector of synthesis parameters    */
    Word16 synth[],/* output: synthesis speech                  */
    Word16 A_t[]   /* output: decoded LP filter in 4 subframes  */
)
{

    /* 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, pit_sharp;
    Word16 temp;
    Word32 L_temp;


    D_plsf_5 (parm, lsp_mid, lsp_new);

    /* Advance synthesis parameters pointer */
    parm += 5;

    /* Interpolation of LPC for the 4 subframes */

    Int_lpc (lsp_old, lsp_mid, lsp_new, A_t);

    /* update the LSPs for the next frame */
    for (i = 0; i < M; i++)
    {
        lsp_old[i] = lsp_new[i];
    }

    /*---------------------------------------------------------------------*
     *       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;

    for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)
    {

        index = *parm++; /* pitch index */

        T0 = Dec_lag6 (index, i_subfr, &T0_frac);

        /*-------------------------------------------------*
         * - Find the adaptive codebook vector.            *
         *-------------------------------------------------*/

        Pred_lt_6 (&exc[i_subfr], T0, T0_frac);

        /*-------------------------------------------------------*
         * - Decode pitch gain.                                  *
         *-------------------------------------------------------*/

        index = *parm++;

        gain_pit = d_gain_pitch (index);

        /*-------------------------------------------------------*
         * - Decode innovative codebook.                         *
         *-------------------------------------------------------*/

        dec_10i40_35bits (parm, code);

        parm += 10;

        /*-------------------------------------------------------*
         * - Add the pitch contribution to code[].               *
         *-------------------------------------------------------*/

        /* pit_sharp = gain_pit;                   */
        /* if (pit_sharp > 1.0) pit_sharp = 1.0;   */

				{
					Word32
						t;

					t = (Word32)gain_pit << 3;
					if (t > 0x7fff)
						t = 0x7fff;
					pit_sharp = (Word16)t;
				}

        /* This loop is not entered when SP_FLAG is 0 */
        for (i = T0; i < L_SUBFR; i++)
        {
#if 0
            temp = mult (code[i - T0], pit_sharp);
            code[i] = add (code[i], temp);
#else
            temp = (Word16)(((Word32)code[i - T0] * (Word32)pit_sharp) >> 15);
            code[i] += temp;
#endif
        }
        /* post processing of excitation elements */

        /* This test is not passed when SP_FLAG is 0 */
        if (pit_sharp > 16384)
        {
            for (i = 0; i < L_SUBFR; i++)
            {
#if 0
                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);
#else
                temp = (Word16)(((Word32)exc[i + i_subfr] * (Word32)pit_sharp) >> 15);
                L_temp = (Word32)temp * (Word32)gain_pit;
                excp[i] = (Word16)((L_temp + (1<<13)) >> 14);
#endif
            }
        }
        /*-------------------------------------------------*
         * - Decode codebook gain.                         *
         *-------------------------------------------------*/

        index = *parm++; /* index of energy VQ */

        d_gain_code (index, code, &gain_code, i_subfr);

        /*-------------------------------------------------------*
         * - Find the total excitation.                          *
         * - Find synthesis speech corresponding to exc[].       *
         *-------------------------------------------------------*/
        for (i = 0; i < L_SUBFR; i++)
        {
#if 0
            /* 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);
#else
            /* exc[i] = gain_pit*exc[i] + gain_code*code[i]; */

            L_temp = (Word32)exc[i + i_subfr] * (Word32)gain_pit;
            L_temp += (Word32)code[i] * (Word32)gain_code;

            exc[i + i_subfr] = (Word16)((L_temp + (1<<11)) >> 12);
#endif
        }

        if (pit_sharp > 16384)
        {
            for (i = 0; i < L_SUBFR; i++)
            {
                excp[i] += exc[i + i_subfr];
            }
            agc2 (&exc[i_subfr], excp);
            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);
        }

        /* interpolated LPC parameters for next subframe */
        Az += MP1;
    }

    /*--------------------------------------------------*
     * 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);
}
