/*****************************************************************************/
/* This software module was originally developed by                          */
/*   Naoki Iwakami (NTT)                                                     */
/* and edited by                                                             */
/*   Naoki Iwakami and Satoshi Miki (NTT) on 1996-05-01,                     */
/*   Naoki Iwakami (NTT) on 1996-08-27,                                      */
/*   Heiko Purnhagen (Uni Hannover) on 1996-11-15,                           */
/*   Naoki Iwakami (NTT) on 1996-12-06,                                      */
/*   Naoki Iwakami (NTT) on 1997-04-18,                                      */
/*   Naoki Iwakami (NTT) on 1997-08-25,                                      */
/*   Naoki Iwakami (NTT) on 1997-10-26,                                      */
/* in the course of development of the                                       */
/* MPEG-2 NBC/MPEG-4 Audio standard ISO/IEC 13818-7, 14496-1,2 and 3.        */
/* This software module is an implementation of a part of one or more        */
/* MPEG-2 NBC/MPEG-4 Audio tools as specified by the MPEG-2 NBC/MPEG-4 Audio */
/* standard. ISO/IEC  gives users of the MPEG-2 NBC/MPEG-4 Audio standards   */
/* free license to this software module or modifications thereof for use in  */
/* hardware or software products claiming conformance to the MPEG-2 NBC/     */
/* MPEG-4 Audio  standards. Those intending to use this software module in   */
/* hardware or software products are advised that this 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-2 NBC/MPEG-4 Audio conforming products. The original developer       */
/* 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 party from using    */
/* the code for non MPEG-2 NBC/MPEG-4 Audio conforming products.             */
/* This copyright notice must be included in all copies or derivative works. */
/* Copyright (c)1996.                                                        */
/*****************************************************************************/

/* 15-nov-96   HP   adapted to new bitstream module */
/* 06-dec-96   NI   provided 6 kbit/s support */
/* 18-apr-97   NI   merged long, medium, & short sequences into one sequence */
/* 25-aug-97   NI   bugfixes */

#include "bitstream.h"
#include "ntt_conf.h"
#include "ntt_conf.h"
#include "all.h"
#include "aac.h"
#include "nok_lt_prediction.h"
#include "ntt_nok_pred.h"
#include "ntt_nok_lt_predict_dec.h"
#include "common.h"

int ntt_LTP_SW;
int nokia_LPTOOL_BITS;

int ntt_BitUnPack ( BsBitStream*  stream,
                    int           available_bits,
                    WINDOW_TYPE   block_type,
                    ntt_INDEX*    index,
                    HANDLE_RESILIENCE hResilience,
		    HANDLE_BUFFER hVm,
                    HANDLE_EP_INFO hEPInfo )
{
  /*--- Variables ---*/
  int		bitcount, itmp, isf, i_ch, idiv, iptop;
  /* frame */
  int nsf, n_ch;
  /* shape */
  int bits_side_info, vq_bits, ndiv, bits0, bits1, bits;
  /* Bark-scale envelope */
  int fw_n_bit, fw_ndiv;
  int flag_pitch, flag_post;
  
  int	bits1_p[ntt_N_DIV_P_MAX], length_p[ntt_N_DIV_P_MAX];
  int	bits0_p[ntt_N_DIV_P_MAX];

  bitcount = 0;
  
  /*--- Get window type ---*/
  if (block_type > 8) 
    block_type = ONLY_LONG_WINDOW;
  index->w_type = block_type;
  
  /*--- Set parameters ---*/
  n_ch = ntt_N_SUP;
  switch (index->w_type){
  case ONLY_LONG_WINDOW: case LONG_MEDIUM_WINDOW: case MEDIUM_LONG_WINDOW:
  case LONG_SHORT_WINDOW: case SHORT_LONG_WINDOW:
    /* frame */
    nsf = 1;
    /* available bits */
    bits_side_info = ntt_PF_SW_BIT + ntt_NMTOOL_BITS;
    vq_bits = available_bits - bits_side_info;
    ntt_VQTOOL_BITS = vq_bits;
    /* Bark-scale envelope */
    fw_n_bit = ntt_FW_N_BIT;
    fw_ndiv = ntt_FW_N_DIV;
    /* flags */
    flag_pitch = 1;
    flag_post = 1;
    break;
  case ONLY_MEDIUM_WINDOW: case MEDIUM_SHORT_WINDOW: case SHORT_MEDIUM_WINDOW:
    /* frame */
    nsf = ntt_N_MID;
    /* available bits */
    bits_side_info = ntt_PF_SW_BIT + ntt_NMTOOL_BITS_M;
    vq_bits = available_bits - bits_side_info;
    ntt_VQTOOL_BITS_M = vq_bits;
    /* Bark-scale envelope */
    fw_n_bit = ntt_FW_N_BIT_M;
    fw_ndiv = ntt_FW_N_DIV_M;
    /* flags */
    flag_pitch = 0;
    flag_post = 1;
    break;
  case ONLY_SHORT_WINDOW:
    /* frame */
    nsf = ntt_N_SHRT;
    /* shape */
    bits_side_info = ntt_NMTOOL_BITS_S;
    vq_bits = available_bits - bits_side_info;
    ntt_VQTOOL_BITS_S = vq_bits;
    /* Bark-scale envelope */
    fw_n_bit = ntt_FW_N_BIT_S;
    fw_ndiv = ntt_FW_N_DIV_S;
    /* flags */
    flag_pitch = 0;
    flag_post = 0;
    break;
  default:
    CommonExit ( 1, "window type not supported" );
  }

  /* set bits for pitch */
  if(ntt_TBIT_P > 0){
    ntt_vec_lenp( bits1_p, length_p );
    for ( idiv=0; idiv<ntt_N_DIV_P; idiv++ ){
      bits0_p[idiv] = (bits1_p[idiv]+1)/2;
      bits1_p[idiv] /= 2;
    }
  }
  
  /*--- long term predictor ---*/
  if (ntt_LTP_SW == 1){
  nokia_LPTOOL_BITS = 0;
  if (index->w_type == ONLY_LONG_WINDOW ||
      index->w_type == LONG_MEDIUM_WINDOW ||
      index->w_type == MEDIUM_LONG_WINDOW ||
      index->w_type == LONG_SHORT_WINDOW ||
      index->w_type == SHORT_LONG_WINDOW){
    nokia_LPTOOL_BITS += 1;
    setHuffdec2BitBuffer(stream);
    nok_lt_decode((WINDOW_TYPE)index->w_type,
                  ntt_N_CRB,
                  ntt_nok_lt_status[0]->sbk_prediction_used,
                  ntt_nok_lt_status[0]->sfb_prediction_used,
                  &ntt_nok_lt_status[0]->weight,
                  ntt_nok_lt_status[0]->delay,
                  hResilience,
		  hVm, hEPInfo );
    if (ntt_nok_lt_status[0]->sbk_prediction_used[0]){
      nokia_LPTOOL_BITS += 3 + 11 + 40;
    }
    vq_bits -= nokia_LPTOOL_BITS;
    ntt_VQTOOL_BITS = vq_bits;
    bitcount += nokia_LPTOOL_BITS;
  }
  }

  /*--- Postfilter ---*/
#if ntt_POSTFILT
  if (flag_post){
    BsGetBitInt(stream, (unsigned int *)&(index->pf), ntt_PF_SW_BIT);
    bitcount += ntt_PF_SW_BIT;
  }
#endif

  for (i_ch=0; i_ch<n_ch; i_ch++){
    if (ntt_BLIM_BITS_H > 0){
      BsGetBitInt(stream, (unsigned int *)&(index->blim_h[i_ch]),
		  ntt_BLIM_BITS_H);
      bitcount += ntt_BLIM_BITS_H;
    }
    if (ntt_BLIM_BITS_L > 0){
      BsGetBitInt(stream, (unsigned int *)&(index->blim_l[i_ch]),
		  ntt_BLIM_BITS_L);
      bitcount += ntt_BLIM_BITS_L;
    }
  }
  
  /*--- Shape vector code ---*/
  ndiv = (int)((vq_bits+ntt_MAXBIT*2-1)/(ntt_MAXBIT*2));
  for ( idiv=0; idiv<ndiv; idiv++ ){
    /* set bits */
    bits = (vq_bits+ndiv-1-idiv)/ndiv;
    bits0 = (bits+1)/2;
    bits1 = bits/2;
    /* read stream */
    BsGetBitInt(stream, (unsigned int *)&(index->wvq[idiv]), bits0);
    BsGetBitInt(stream, (unsigned int *)&(index->wvq[idiv+ndiv]), bits1);
    bitcount += bits0 + bits1;
  }
  
  /*--- Forward envelope code ---*/
  if (fw_n_bit > 0){
    for ( i_ch=0; i_ch<n_ch; i_ch++ ){
      for ( isf=0; isf<nsf; isf++ ){
	for ( idiv=0; idiv<fw_ndiv; idiv++ ){
	  itmp = idiv+(isf+i_ch*nsf)*fw_ndiv;
	  BsGetBitInt(stream, (unsigned int *)&(index->fw[itmp]), fw_n_bit);
	  bitcount += fw_n_bit;
	}
      }
    }
    for ( i_ch=0; i_ch<n_ch; i_ch++ ){
      for ( isf=0; isf<nsf; isf++ ){
	BsGetBitInt(stream, (unsigned int *)&(index->fw_alf[i_ch*nsf+isf]),
		    ntt_FW_ARQ_NBIT);
	bitcount += ntt_FW_ARQ_NBIT;
      }
    }
  }
  
  /*--- Gain ---*/
  if (nsf == 1){
    for (i_ch=0; i_ch<n_ch; i_ch++){
      BsGetBitInt(stream, (unsigned int *)&(index->pow[i_ch]), ntt_GAIN_BITS);
      bitcount += ntt_GAIN_BITS;
    }
  }
  else{
    for (i_ch=0; i_ch<n_ch; i_ch++){
      iptop = (nsf+1)*i_ch;
      BsGetBitInt(stream, (unsigned int *)&(index->pow[iptop]), ntt_GAIN_BITS);
      for ( isf=0; isf<nsf; isf++ ){
	BsGetBitInt(stream, (unsigned int *)&(index->pow[iptop+isf+1]),
		    ntt_SUB_GAIN_BITS);
      }
      bitcount += ntt_GAIN_BITS + ntt_SUB_GAIN_BITS * nsf;
    }
  }
  /*--- LSP ---*/
  for (i_ch=0; i_ch<n_ch; i_ch++){
    /* pred. switch */
    BsGetBitInt(stream, (unsigned int *)&(index->lsp[i_ch][0]), ntt_LSP_BIT0);
    /* first stage */
    BsGetBitInt(stream, (unsigned int *)&(index->lsp[i_ch][1]), ntt_LSP_BIT1);
    /* second stage */
    for (itmp=0; itmp<ntt_LSP_SPLIT; itmp++)
      BsGetBitInt(stream, (unsigned int *)&(index->lsp[i_ch][itmp+2]),
		  ntt_LSP_BIT2);
    bitcount += ntt_LSP_BIT0 + ntt_LSP_BIT1 + ntt_LSP_SPLIT * ntt_LSP_BIT2;
  }
  
  /*--- Pitch excitation ---*/
  if (flag_pitch){
    if (ntt_TBIT_P > 0 ){
      for ( idiv=0; idiv<ntt_N_DIV_P; idiv++ ){
	BsGetBitInt(stream, (unsigned int *)&(index->pls[idiv]),
		    bits0_p[idiv]);       /*CB0*/
	BsGetBitInt(stream, (unsigned int *)&(index->pls[idiv+ntt_N_DIV_P]),
		    bits1_p[idiv]);       /*CB1*/
	bitcount += bits0_p[idiv] + bits1_p[idiv];
      }
      for (i_ch=0; i_ch<n_ch; i_ch++){
	BsGetBitInt(stream, (unsigned int *)&(index->pit[i_ch]), ntt_BASF_BIT);
	BsGetBitInt(stream, (unsigned int *)&(index->pgain[i_ch]),
		    ntt_PGAIN_BIT);
	bitcount += ntt_BASF_BIT + ntt_PGAIN_BIT;
      }
    }
  }

  return(bitcount);
  
}
