/*
***********************************************************************
*
* Copyright (C) 1999 Ericsson Radio Systems AB
* 
* The Association of Radio Industries and Businesses (ARIB) has the
* licence to reproduce, distribute and publish the Bit Exact C Code
* programs in this CD-ROM together with the other parts of the RCR
* STD-27 (Personal Digital Cellular Telecommunication System)
* specification.
* 
* Ericsson has declared Option 1 (royalty-free licence) to ARIB for
* its Essential Industrial Property Rights related to the ACELP
* specification and the Bit Exact C Code programs. The royalty-free
* licence is limited to the development and manufacturing of
* products complying with the RCR STD-27H specification (or
* subsequent versions) for sale and use in Japan. Copying of the
* program(s) for any other purpose requires the prior written
* permission from Ericsson.
* 
* The user of the Bit Exact C Code hereby acknowledges the
* following:
* 
* 1.  Ericsson does not provide the user with any warranties,
*     whether express or implied, including but not limited to
*     warranties of merchantability and fitness for a particular
*     purpose relating to the Bit Exact C Code.
* 
* 2.  Ericsson shall have no responsibility whatsoever to indemnify
*     the user against actions or claims for infringement of any
*     intellectual property rights, e.g. patents, copyrights,
*     registered designs or any other rights, by reason of the
*     user's use of the Bit Exact C Code.
* 
***********************************************************************
*/

/*************************************************************************
 *
 *  FUNCTION:   D_plsf_3()
 *
 *  PURPOSE: Decodes the LSP parameters using the received quantization
 *           indices.1st order MA prediction and split by 3 matrix
 *           quantization (split-MQ)
 *
 *************************************************************************/

#include "typedef.h"
#include "basic_op.h"
#include "sig_proc.h"

#include "q_plsf_3.tab"    /* Codebooks of LSF prediction residual */

/* M  ->order of linear prediction filter                      */
/* LSF_GAP  -> Minimum distance between LSF after quantization */
/*             50 hz = 205                                     */
/* ALPHA    ->  0.9                                            */
/* ONE_ALPHA-> (1.0-ALPHA)                                     */

#define M         10
#define LSF_GAP   205
#define ALPHA     29491
#define ONE_ALPHA 3277

/* Past quantized prediction error */

static Word16 past_rq[M] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};

void D_plsf_3(
    Word16 * past_lsf_q, /* i/o: Past quantized LSF vector */
    Word16 * indice,  /* input : quantization indices of 3 submatrices */
    Word16 * lsp1_q,  /* output: quantized 1st LSP vector              */
    Word16 blsfi      /* input : bad lsf indicator (set to 1 if a bad  */
                      /*         frame is received                     */
)
{
    Word16 i, index;
    Word16 *p_dico, temp;
    Word16 lsf1_r[M];
    Word16 lsf1_q[M];

    if (blsfi != 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));
        }

        /* 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_rq[i], pred_fac[i]));

            past_rq[i] = sub(lsf1_q[i], temp);
        }
    } else {    /* if good LSFs received */

        /* decode prediction residuals from 3 received indices */

        index = *indice++;
        p_dico = &dico1_lsf[add(index, add(index, index))];
        lsf1_r[0] = *p_dico++;
        lsf1_r[1] = *p_dico++;
        lsf1_r[2] = *p_dico++;

        index = *indice++;
        p_dico = &dico2_lsf[add(index, add(index, index))];
        lsf1_r[3] = *p_dico++;
        lsf1_r[4] = *p_dico++;
        lsf1_r[5] = *p_dico++;

        index = *indice++;
        p_dico = &dico3_lsf[shl(index, 2)];
        lsf1_r[6] = *p_dico++;
        lsf1_r[7] = *p_dico++;
        lsf1_r[8] = *p_dico++;
        lsf1_r[9] = *p_dico++;

        /* Compute quantized LSFs and update the past quantized residual */
        for (i = 0; i < M; i++) {
           temp = add(mean_lsf[i], mult(past_rq[i], pred_fac[i]));
           lsf1_q[i] = add(lsf1_r[i], temp);
           past_rq[i] = lsf1_r[i];
        }
    }

    /* verification that LSFs has mimimum distance of LSF_GAP Hz */

    Reorder_lsf(lsf1_q, LSF_GAP, M);

    for (i = 0; i < M; i++) {
        past_lsf_q[i] = lsf1_q[i];
    }

    /*  convert LSFs to the cosine domain */

    Lsf_lsp(lsf1_q, lsp1_q, M);

    return;
}


