/*====================================================================*/
/*         MPEG-4 Audio (ISO/IEC 14496-3) Copyright Header            */
/*====================================================================*/
/*
This software module was originally developed by Rakesh Taori and Andy
Gerrits (Philips Research Laboratories, Eindhoven, The Netherlands) in
the course of development of the MPEG-4 Audio (ISO/IEC 14496-3). This
software module is an implementation of a part of one or more MPEG-4
Audio (ISO/IEC 14496-3) tools as specified by the MPEG-4 Audio
(ISO/IEC 14496-3). ISO/IEC gives users of the MPEG-4 Audio (ISO/IEC
14496-3) free license to this software module or modifications thereof
for use in hardware or software products claiming conformance to the
MPEG-4 Audio (ISO/IEC 14496-3). Those intending to use this software
module in hardware or software products are advised that its use may
infringe existing patents. The original developer of this software
module and his/her company, the subsequent editors and their
companies, and ISO/IEC have no liability for use of this software
module or modifications thereof in an implementation. Copyright is not
released for non MPEG-4 Audio (ISO/IEC 14496-3) conforming products.
CN1 retains full right to use the code for his/her own purpose, assign
or donate the code to a third party and to inhibit third parties from
using the code for non MPEG-4 Audio (ISO/IEC 14496-3) conforming
products.  This copyright notice must be included in all copies or
derivative works. Copyright 1996.
*/
/*====================================================================*/
/*====================================================================*/
/*                                                                    */
/*      SOURCE_FILE:    PHI_BS2P.C                                    */
/*      PACKAGE:        WDBxx                                         */
/*      COMPONENT:      Bitstream to Parameter converter              */
/*                                                                    */
/*====================================================================*/
    
/*====================================================================*/
/*      I N C L U D E S                                               */
/*====================================================================*/
#include <stdio.h>
#include <stdlib.h>
#include "phi_cons.h"      
#include "lpc_common.h"  /* Common LPC core Defined Constants           */
#include "phi_bs2p.h"    /* Parameter to bitstream conversion routines  */

/*======================================================================*/
/*      L O C A L  D A T A    D E C L A R A T I O N S                   */
/*======================================================================*/
static int  PHI_decoded_bits  = 0;

/*======================================================================*/
/*      L O C A L  F U N C T I O N  P R O T O T Y P E S                 */
/*======================================================================*/
/*======================================================================*/
/* Unpack Header                                                        */
/*======================================================================*/
static void PHI_unpack_header(
    BITSTREAM * const bs,       /* In: Bitstream Pointer                */ 
    long * const code,          /* Out: Interpolation Flag              */
    const long num_bits         /* In: Number of bits used for header   */
    );

/*======================================================================*/
/* Unpack lar codes                                                     */
/*======================================================================*/
static void PHI_unpack_LPC(
    BITSTREAM * const bs,       /* In: Bitstream Pointer                */
    const long num_lpc_indices, /* In: Number of packed LPC             */
    long lpc_codes[],           /* Out: Packed LPC Codes                */
    const long bit_allocation[] /* In: Number of bits for each LPC code */
    );

/*======================================================================*/
/* Unpack Excitation Paramaters                                         */
/*======================================================================*/
static void PHI_unpack_excitation(
    BITSTREAM * const bs,       /* In: Bitstream Pointer                */
    const long n_subframes,     /* In: Number of subframes              */
    const long num_shape_cbks,  /* In: Number of Shape Codebooks        */
    const long num_gain_cbks,   /* In: Number of Gain Codebooks         */
    long shape_indices[],       /* Out: Adaptive Cbk lag and Fcbk index */
    long gain_indices[],        /* Out: Adaptive and Fixed Codebook Gain*/
    const long bit_allocation[] /* In: Number of bits for excitation    */
    );
    
/*======================================================================*/
/* GetBit: To avoid lot of lines of code                                */
/*======================================================================*/
static void GetBit(
   BITSTREAM const * const bs,/* In:  Bitstream Pointer                 */
   long   * const c,         /* Out: Value read off the bitstream       */
   const  long num_bits      /* In:  #bits to be read                   */
   );
   
/*======================================================================*/
/* Function Definition: celp_bitstream_demux                            */
/*======================================================================*/
void 
    celp_bitstream_demux(             
    BITSTREAM  * const p_bitstream,  /* In:  Bitstream                  */
    long * const signal_mode,        /* Out: Signal mode (NOT USED)     */
    long frame_bit_allocation[],     /* In:  Bit Alloc.                 */ 
    long * const interpol,           /* Out: Interpolation flag         */
    const long num_lpc_indices,      /* In: Number of packed LPC        */
    long lpc_indices[],              /* Out: LP coefficients            */
    long * const rms_index,          /* Out: RMS index (NOT USED)       */
    long shape_indices[],            /* Out: Shape indices              */
    long gain_indices[],             /* Out: Gain indices               */
    const long num_shape_cbks,       /* In: Number of Shape Codebooks   */
    const long num_gain_cbks,        /* In: Number of Gain Codebooks    */
    const long n_sbfrms              /* In: Number of subframes         */
    )
{
    /* -----------------------------------------------------------------*/
    /* Unpack Header Info                                               */
    /* -----------------------------------------------------------------*/
    PHI_unpack_header(p_bitstream, interpol, frame_bit_allocation[0]);

    /* -----------------------------------------------------------------*/
    /* Unpack LPC parameters                                            */
    /* -----------------------------------------------------------------*/
    PHI_unpack_LPC(p_bitstream, num_lpc_indices, lpc_indices, 
         &(frame_bit_allocation[1]));
    

    /* -----------------------------------------------------------------*/
    /* Unpack Excitation parameters                                     */
    /* -----------------------------------------------------------------*/
    PHI_unpack_excitation(p_bitstream, n_sbfrms, num_shape_cbks, num_gain_cbks, shape_indices,
                   gain_indices, &(frame_bit_allocation[num_lpc_indices+1]));
     
    /* -----------------------------------------------------------------*/
    /*  Update the number of bits that were used for this frame         */
    /* -----------------------------------------------------------------*/
    p_bitstream->valid_bits = PHI_decoded_bits;
    PHI_decoded_bits = 0;
}
    
/*======================================================================*/
/* L O C A L     F U N C T I O N     D E F I N I T I O N S              */
/*======================================================================*/

/*======================================================================*/
/* Pack Header                                                          */
/*======================================================================*/
static void PHI_unpack_header(
    BITSTREAM * const bs,       /* In: Bitstream Pointer                */ 
    long * const code,          /* Out: Interpolation Flag              */
    const long num_bits         /* In: Number of bits used for header   */
    )
{
    GetBit(bs, code, num_bits);
}

/*======================================================================*/
/* Pack lar codes                                                       */
/*======================================================================*/
static void PHI_unpack_LPC(
    BITSTREAM * const bs,       /* In: Bitstream Pointer                */
    const long num_lpc_indices, /* In: Number of packed LPC             */
    long lpc_codes[],           /* Out: Packed LPC Codes                */
    const long bit_allocation[] /* In: Number of bits for each LPC code */
)
{
    long receive_lpc_flag;
    
    GetBit(bs, &(receive_lpc_flag), bit_allocation[0]);
    lpc_codes[0] = receive_lpc_flag;
    
    if (receive_lpc_flag)
    {
        long k;
        for (k = 1; k < num_lpc_indices; k++)
        {
            GetBit(bs, &(lpc_codes[k]),  bit_allocation[k]); 
        }
    }
}


/*======================================================================*/
/* Pack Excitation Paramaters                                           */
/*======================================================================*/
static void PHI_unpack_excitation(
    BITSTREAM * const bs,       /* In: Bitstream Pointer                */
    const long n_subframes,     /* In: Number of subframes              */
    const long num_shape_cbks,  /* In: Number of Shape Codebooks        */
    const long num_gain_cbks,   /* In: Number of Gain Codebooks         */
    long shape_indices[],       /* Out: Adaptive Cbk lag and Fcbk index */
    long gain_indices[],        /* Out: Adaptive and Fixed Codebook Gain*/
    const long bit_allocation[] /* In: Number of bits for excitation    */
    )
{
    long k;
 

    /*==================================================================*/
    /* Make sure the number of shape and gain codebooks is correct      */
    /*==================================================================*/
    if (num_shape_cbks != 2)
    { 
        fprintf(stderr, "Wrong number of shape codebooks in Block: wdb_bs2p\n");
        exit(1);
    }    
    if (num_gain_cbks != 2)
    { 
        fprintf(stderr, "Wrong number of gain codebooks in Block: wdb_bs2p\n");
        exit(1);
    }    
    
    for(k = 0; k < n_subframes; k++)
    {
        long shape_index = k * num_shape_cbks;
        long gain_index  = k * num_gain_cbks;
        long bit_index   = k * (num_gain_cbks + num_shape_cbks);

        GetBit(bs, &(shape_indices[shape_index]),     bit_allocation[bit_index + 0]);
        GetBit(bs, &(shape_indices[shape_index + 1]), bit_allocation[bit_index + 1]);
        GetBit(bs, &(gain_indices[gain_index]),       bit_allocation[bit_index + 2]);
        GetBit(bs, &(gain_indices[gain_index + 1]),   bit_allocation[bit_index + 3]);
    }
}

/*======================================================================*/
/* GetBit: To avoid lot of lines of code                                */
/*======================================================================*/
static void GetBit(
   BITSTREAM const * const bs,/* In:  Bitstream Pointer                 */
   long   * const c,         /* Out: Value read off the bitstream       */
   const  long num_bits      /* In:  #bits to be read                   */
   )
{
    int j;
    unsigned int temp = 0;
    
    if (bs != NULL)
    {
        for (j=(int)num_bits-1; j>=0; j -=1)
        {
            int index = PHI_decoded_bits/8;
            int bit = 7-(PHI_decoded_bits%8);
        
            if ((bs->p_bitstream_buffer_start[index] >> bit) & 1)
               temp |= (unsigned int)(1 << j);

            PHI_decoded_bits += 1;
            
            if (PHI_decoded_bits > bs->valid_bits)
            {
                fprintf(stderr,"More bits decoded than present\n");
                fprintf(stderr,"Exitting.....\n");
                exit(0);
            }
        }

        *c = (long)temp;
    }
    else
    {
        *c = 0;
    }

}

/*======================================================================*/
/*      H I S T O R Y                                                   */
/*======================================================================*/
/* 07-06-96  R. Taori & A.Gerrits    Initial Version                    */
/* 18-09-96  R. Taori & A.Gerrits    MPEG bitstream used                */
