/*************************************************************************
 *
 *  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 "sig_proc.h"

#include "q_plsf_5.tab"         /* Codebooks of LSF prediction residual */

#include "cnst.h"

/* LSF_GAP  -> Minimum distance between LSF after quantization */
/*             50 Hz = 205                                     */
/* PRED_FAC -> Prediction factor = 0.65                        */

#define LSF_GAP   205
#define PRED_FAC  21299

/* Past quantized prediction error */

Word16 past_r2_q[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 i;
    const Word16 *p_dico;
    Word16 temp, sign;
    Word16 lsf1_r[M], lsf2_r[M];
    Word16 lsf1_q[M], lsf2_q[M];

    /* decode prediction residuals from 5 received indices */

    p_dico = &dico1_lsf[indice[0] << 2];
    lsf1_r[0] = p_dico[0];
    lsf1_r[1] = p_dico[1];
    lsf2_r[0] = p_dico[2];
    lsf2_r[1] = p_dico[3];

    p_dico = &dico2_lsf[indice[1] << 2];
    lsf1_r[2] = p_dico[0];
    lsf1_r[3] = p_dico[1];
    lsf2_r[2] = p_dico[2];
    lsf2_r[3] = p_dico[3];

    sign = indice[2] & 1;
    i = indice[2] >> 1;
    p_dico = &dico3_lsf[i << 2];

    if (sign == 0)
    {
        lsf1_r[4] = p_dico[0];
        lsf1_r[5] = p_dico[1];
        lsf2_r[4] = p_dico[2];
        lsf2_r[5] = p_dico[3];
    }
    else
    {
        lsf1_r[4] = -p_dico[0];
        lsf1_r[5] = -p_dico[1];
        lsf2_r[4] = -p_dico[2];
        lsf2_r[5] = -p_dico[3];
    }

    p_dico = &dico4_lsf[indice[3] << 2];
    lsf1_r[6] = p_dico[0];
    lsf1_r[7] = p_dico[1];
    lsf2_r[6] = p_dico[2];
    lsf2_r[7] = p_dico[3];

    p_dico = &dico5_lsf[indice[4] << 2];
    lsf1_r[8] = p_dico[0];
    lsf1_r[9] = p_dico[1];
    lsf2_r[8] = p_dico[2];
    lsf2_r[9] = p_dico[3];

    /* Compute quantized LSFs and update the past quantized residual */

    for (i = 0; i < M; i++)
    {
#if 0
        temp = add (mean_lsf[i], mult (past_r2_q[i], PRED_FAC));
        lsf1_q[i] = add (lsf1_r[i], temp);
        lsf2_q[i] = add (lsf2_r[i], temp);
        past_r2_q[i] = lsf2_r[i];
#else
        temp = (Word16)(((Word32)past_r2_q[i] * (Word32)PRED_FAC) >> 15);
        temp += mean_lsf[i];
        lsf1_q[i] = lsf1_r[i] + temp;
        lsf2_q[i] = lsf2_r[i] + temp;
        past_r2_q[i] = lsf2_r[i];
#endif
    }

    /* verification that LSFs have minimum distance of LSF_GAP Hz */

    Reorder_lsf (lsf1_q, LSF_GAP, M);
    Reorder_lsf (lsf2_q, LSF_GAP, M);

    /*  convert LSFs to the cosine domain */

    Lsf_lsp (lsf1_q, lsp1_q, M);
    Lsf_lsp (lsf2_q, lsp2_q, M);
}
