/*
***********************************************************************
*
* 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:  Dec_gain()
 *
 *   PURPOSE: Decode the pitch and codebook gains
 *
 ************************************************************************/

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

#include "qua_gain.tab"

/* MA prediction coeffs */
static Word16 pred[4] = {5571, 4751, 2785, 1556};

void Dec_gain(
    Word16 index,       /* (i)  :index of quantization.       */
    Word16 code[],      /* (i)  :Innovative vector.           */
    Word16 L_subfr,     /* (i)  :Subframe lenght.             */
    Word16 *past_qua_en,  /* i/o : MA predictor state         */
    Word16 * gain_pit,  /* (o)  :Pitch gain.                  */
    Word16 * gain_cod   /* (o)  :Code gain.                   */
)
{
    Word16 i, *p;
    Word16 exp, frac, gcode0, exp_gcode0, qua_ener;
    Word16 g_code;
    Word32 L_tmp;

    static Word16 old_gain_pit = 0;
    static Word16 old_gain_code = 0;

  /*-------------------------------*
   * Energy coming from code       *
   *-------------------------------*/

    L_tmp = L_mac((Word32) 0, code[0], code[0]);
    for (i = 1; i < L_subfr; i++)
        L_tmp = L_mac(L_tmp, code[i], code[i]);


    Log2(L_tmp, &exp, &frac);
    L_tmp = Mpy_32_16(exp, frac, -24660);

    L_tmp = L_mac(L_tmp, 32268, 32);  /* 28.75dB */

  /*-----------------------------------------------------------------*
   * Compute gcode0.                                                 *
   *  = Sum(i=0,3) pred[i]*past_qua_en[i] - ener_code + mean_ener    *
   *-----------------------------------------------------------------*/

    L_tmp = L_shl(L_tmp, 10);
    for (i = 0; i < 4; i++)
        L_tmp = L_mac(L_tmp, pred[i], past_qua_en[i]);

    gcode0 = extract_h(L_tmp);

  /*-----------------------------------------------------------------*
   * gcode0 = pow(10.0, gcode0/20)                                   *
   *        = pow(2, 3.3219*gcode0/20)                               *
   *        = pow(2, 0.166*gcode0)                                   *
   *-----------------------------------------------------------------*/

    L_tmp = L_mult(gcode0, 5443);
    L_tmp = L_shr(L_tmp, 8);
    L_Extract(L_tmp, &exp_gcode0, &frac);

    gcode0 = extract_l(Pow2(14, frac));

    /* Read the quantized gains */

    p = &table_gain[add(index, add(index, index))];
    *gain_pit = *p++;
    g_code = *p++;
    qua_ener = *p;


    L_tmp = L_mult(g_code, gcode0);
    L_tmp = L_shr(L_tmp, sub(10, exp_gcode0));
    *gain_cod = extract_h(L_tmp);

    /* update table of past quantized energies */

    for (i = 3; i > 0; i--) {
        past_qua_en[i] = past_qua_en[i - 1];
    }
    past_qua_en[0] = qua_ener;

    old_gain_code = *gain_cod;
    old_gain_pit = *gain_pit;

    return;
}
