/**********************************************************************
MPEG-4 Audio VM
Bit stream module



This software module was originally developed by

Bodo Teichmann (FhG)

and edited by

Bernhard Grill (University of Erlangen)
Takashi koike (Sony Corporation)

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) 1997.

*/

#include <memory.h>
#include <math.h>
#include <string.h>
#include "dec.h"
#include "bitstream.h"
#include "common.h"
/* ---  AAC --- */
#include "aac.h"
#include "util.h"
#include "scal_dec.h"
#include "tns.h"
#include "plotmtv.h"

/* ***************************************************************************/
/* scalable decoding : bitstream has 3 subframes (called granules) per frame */

static void vcopy( double src[], double dest[], int inc_src, int inc_dest, int vlen )
{
  int i;

  for( i=0; i<vlen-1; i++ ) {
    *dest = *src;
    dest += inc_dest;
    src  += inc_src;
  }
  if (vlen) /* just for bounds-checkers sake */
    *dest = *src;

}

static void vmult( double src1[], double src2[], double dest[], 
            int inc_src1, int inc_src2, int inc_dest, int vlen )
{
  int i;

  for( i=0; i<vlen-1; i++ ) {
    *dest = *src1 * *src2;
    dest += inc_dest;
    src1 += inc_src1;
    src2 += inc_src2;
  }
  if (i<vlen)
    *dest = *src1 * *src2;

}


static void vadd( double src1[], double src2[], double dest[], 
            int inc_src1, int inc_src2, int inc_dest, int vlen )
{
  int i;

  for( i=0; i<vlen; i++ ) {
    *dest = *src1 + *src2;
    dest += inc_dest;
    src1 += inc_src1;
    src2 += inc_src2;
  }
}
static void vsub( double src1[], double src2[], double dest[], 
            int inc_src1, int inc_src2, int inc_dest, int vlen )
{
  int i;

  for( i=0; i<vlen; i++ ) {
    *dest = *src1 - *src2;
    dest += inc_dest;
    src1 += inc_src1;
    src2 += inc_src2;
  }
}

/* get_tns_vm does exactly the same as get_tns in huffdec2.c. Just the
   VM bitstream handling functions replace the AAC-type functions */

void doInverseMsMatrix(
  Info       *p_sb_info,
  double *p_l_spec,
  double *p_r_spec,
  int msMask[8][60]
  )
{
  int sb, win;
  int sfbw;
  double  tmp_buffer[1024];
  for( win=0; win<p_sb_info->nsbk; win++ ) {
    int sboffs   = win*p_sb_info->bins_per_sbk[win];
    int maskoffs = win*p_sb_info->sfb_per_sbk[win];

    for( sb=0; sb<p_sb_info->sfb_per_sbk[win]; sb++ ) {
      if (p_sb_info->islong==0){
        sfbw = p_sb_info->sfb_width_short[sb];
      }else {
        if (sb==0)
          sfbw = p_sb_info->bk_sfb_top[sb];
        else 
          sfbw = p_sb_info->bk_sfb_top[sb]-p_sb_info->bk_sfb_top[sb-1];        
      }

      if( msMask[win][sb] != 0  ) {
        vadd( &p_l_spec[sboffs], &p_r_spec[sboffs], &tmp_buffer[sboffs],        1, 1, 1, sfbw );  /* -> L */
        vsub( &p_l_spec[sboffs], &p_r_spec[sboffs], &p_r_spec[sboffs], 1, 1, 1, sfbw );  /* -> R */
        vcopy(&tmp_buffer[sboffs], &p_l_spec[sboffs], 1, 1, sfbw );
      }

      sboffs += sfbw;
    }
  }

}
void  multCoreSpecMsFac(
  Info       *p_sb_info,
  int msMask[8][60],
  double *core_spec,
  double *out_spec
  )
{
  int sb, win;
  int sfbw;
  double ms_fac=2;
  for( win=0; win<p_sb_info->nsbk; win++ ) {
    int sboffs   = win*p_sb_info->bins_per_sbk[win];
    int maskoffs = win*p_sb_info->sfb_per_sbk[win];

    for( sb=0; sb<p_sb_info->sfb_per_sbk[win]; sb++ ) {
      if (p_sb_info->islong==0){
        sfbw = p_sb_info->sfb_width_short[sb];
      }else {
        if (sb==0)
          sfbw = p_sb_info->bk_sfb_top[sb];
        else 
          sfbw = p_sb_info->bk_sfb_top[sb]-p_sb_info->bk_sfb_top[sb-1];        
      }
      if( msMask[win][sb] == 0  ) {
        vmult( &core_spec[sboffs], &ms_fac,&out_spec[sboffs] ,1, 0, 1, sfbw );  /* if no ms core = core * fac */
      }else{
        vcopy( &core_spec[sboffs],&out_spec[sboffs] ,1, 1, sfbw );  /* if ms core = core */
      }
      sboffs += sfbw;
    }
  }

}
int get_tns_vm( BsBitStream *fixed_stream, Info *info, TNS_frame_info *tns_frame_info,int* decoded_bits )
{
  int                       f, t, top, res, res2, compress;
  int                       short_flag, s;
  short                     *sp, tmp, s_mask, n_mask;
  TNSfilt                   *tns_filt;
  TNSinfo                   *tns_info;
  static short              sgn_mask[] = { 
    0x2, 0x4, 0x8     };
  static short              neg_mask[] = { 
   (short) 0xfffc, (short)0xfff8, (short)0xfff0     };
  unsigned long ultmp, numBits;

  short_flag = (!info->islong);
  tns_frame_info->n_subblocks = info->nsbk;

  for (s=0; s<tns_frame_info->n_subblocks; s++) {
    tns_info = &tns_frame_info->info[s];
    numBits = (short_flag ? 1 : 2);
    BsGetBit( fixed_stream, &ultmp,numBits   );
    *decoded_bits += numBits; 
    if (!(tns_info->n_filt = ultmp) )
      continue;	    
    BsGetBit( fixed_stream, &ultmp, 1 );
    *decoded_bits += 1; 
    tns_info -> coef_res = res = ultmp + 3;
    top = info->sfb_per_sbk[s];
    tns_filt = &tns_info->filt[ 0 ];
    for (f=tns_info->n_filt; f>0; f--)  {
      tns_filt->stop_band = top;
      numBits = ( short_flag ? 4 : 6);
      BsGetBit( fixed_stream, &ultmp,numBits );
      *decoded_bits += numBits; 
      top = tns_filt->start_band = top - ultmp;

      numBits = ( short_flag ? 3 : 5);
      BsGetBit( fixed_stream, &ultmp, numBits );
      *decoded_bits += numBits; 

      tns_filt->order = ultmp;

      if (tns_filt->order)  {
        BsGetBit( fixed_stream, &ultmp, 1 );
        *decoded_bits += 1; 

        tns_filt->direction = ultmp;
        BsGetBit( fixed_stream, &ultmp, 1 );
        *decoded_bits += 1; 

        compress = ultmp;

        res2 = res - compress;
        s_mask = sgn_mask[ res2 - 2 ];
        n_mask = neg_mask[ res2 - 2 ];

        sp = tns_filt -> coef;
        for (t=tns_filt->order; t>0; t--)  {
          BsGetBit( fixed_stream, &ultmp, res2 );
          *decoded_bits += res2; 
          tmp = ultmp;
          *sp++ = (tmp & s_mask) ? (tmp | n_mask) : tmp;
        }
      }
      tns_filt++;
    }
  }   /* subblock loop */
  return 1;
}

static BsBitBuffer *dynBitBuf;
static int         gran;
static BsBitStream *dyn_stream_read;
int testDebug=0;
static int core_init = 1;

void aacScaleableDecodeInit( void )
{
 
  dynBitBuf  = BsAllocBuffer( 16000 );     /* just some large number. For AAC: required ca. 6000 */

  gran = 0;

  dyn_stream_read = BsOpenBufferRead( dynBitBuf );
}

  
void FSSwitch(
  double  p_core[],
  double  p_rest[], 
  double  p_out[], 
  int          *diff_control, 
  Info         *p_sbinfo,
  int           numDiffBands,
  int        shortDiffWidth,
  int           is_decoder
)
{
  int sbk, diffBand,x;
  int dc_decoded[8][128];
  short diffBandWidth[200];
  double doubleZero=0.0;
  int numDiffBandsPerSbk;
  int g;

  if (p_sbinfo->islong){
    numDiffBandsPerSbk=numDiffBands;
    diffBandWidth[0]= p_sbinfo->bk_sfb_top[0];  
    for (x=1;x< p_sbinfo->sfb_per_bk;x++){
      if  (p_sbinfo->bk_sfb_top[x]==0)
        CommonExit(-1,"\ninternal FSS error");
      diffBandWidth[x]= p_sbinfo->bk_sfb_top[x] - p_sbinfo->bk_sfb_top[x-1];
    }
  } else {
    numDiffBandsPerSbk=1;
    diffBandWidth[0]= shortDiffWidth;
  }

  g=0;
  for( sbk=0; sbk<p_sbinfo->nsbk; sbk++ ) {
    for( diffBand=0; diffBand<numDiffBandsPerSbk; diffBand++ ) {
      dc_decoded[sbk][diffBand] = diff_control[g];
      g++;
    }
  }

  for( sbk=0; sbk<p_sbinfo->nsbk; sbk++ ) {
    int offset = sbk*p_sbinfo->bins_per_sbk[sbk];
    int sum    = 0;
    for( diffBand=0; diffBand<numDiffBandsPerSbk; diffBand++ ) {
      if( dc_decoded[sbk][diffBand] == 0 ) {
        if( is_decoder ) {
          vadd ( &p_core[offset], &p_rest[offset], &p_out[offset], 1, 1, 1, diffBandWidth[diffBand] ); 
        }
      } else {
        vcopy( &p_rest[offset], &p_out[offset], 1, 1, diffBandWidth[diffBand] ); 
        if( !is_decoder ) {
          vcopy( &doubleZero , &p_core[offset], 0, 1, diffBandWidth[diffBand] ); 
        }
      }
      offset += diffBandWidth[diffBand];
      sum    += diffBandWidth[diffBand];
    }
    vcopy( &p_rest[offset], &p_out[offset], 1, 1, p_sbinfo->bins_per_sbk[sbk]-sum ); 
    vcopy( &doubleZero ,   &p_core[offset], 0, 1, p_sbinfo->bins_per_sbk[sbk]-sum ); 
  }
}

void FSSwitchSt(
  double  p_core[],/* bands of this spec is mult by 2 if ms is off */ 
  double  p_rest[], 
  double  p_out[], 
  int          *diff_control, 
  Info         *p_sbinfo,
  int           numDiffBands,
  int        shortDiffWidth,
  int         msMask[8][60],
  int         channel
)
{
  int sbk, diffBand,sfb;
  int dc_decoded[8][128];
  short sfbWidth[200];
  double doubleZero=0.0;
  int numDiffBandsPerSbk;
  int g;


  sfbWidth[0]= p_sbinfo->sbk_sfb_top[0][0];  
  for (sfb=1;sfb< p_sbinfo->sfb_per_sbk[0];sfb++){
    if  (p_sbinfo->sbk_sfb_top[0][sfb]==0)
      CommonExit(-1,"\ninternal FSS error");
    sfbWidth[sfb]= p_sbinfo->sbk_sfb_top[0][sfb] - p_sbinfo->sbk_sfb_top[0][sfb-1];
  }
  
  if (p_sbinfo->islong){
  } else {
  }

  g=0;
  for( sbk=0; sbk<p_sbinfo->nsbk; sbk++ ) {
    for( sfb=0; sfb<p_sbinfo->sfb_per_sbk[0]; sfb++ ) {
      dc_decoded[sbk][sfb] = diff_control[g];
      if (p_sbinfo->islong!=0){      
        g++; 
      }      
    }
    g++;       
  }

  for( sbk=0; sbk<p_sbinfo->nsbk; sbk++ ) {
    int offset = sbk*p_sbinfo->bins_per_sbk[sbk];
    int sum    = 0;  
    
    for( sfb=0; sfb<p_sbinfo->sfb_per_bk; sfb++  ) {
      /* build combined L/R spectrum */
      if( (msMask[sbk][sfb] == 0 ) ) {
        if(  dc_decoded[sbk][sfb] == 0 ) {
          vadd ( &p_core[offset], &p_rest[offset], &p_out[offset], 1, 1, 1, sfbWidth[sfb] ); 
        } else {
          vcopy( &p_rest[offset], &p_out[offset], 1, 1, sfbWidth[sfb] ); 
        }
      }
      /* build combined M spectrum */
      if( msMask[sbk][sfb] != 0 ) {
        if( channel == 0 ) {
          vadd ( &p_core[offset], &p_rest[offset], &p_out[offset], 1, 1, 1, sfbWidth[sfb] ); 
        } else {
          vcopy( &p_rest[offset], &p_out[offset], 1, 1, sfbWidth[sfb] ); 
        }
      }
      offset += sfbWidth[sfb];
      sum    += sfbWidth[sfb];
    }
    vcopy( &p_rest[offset], &p_out[offset], 1, 1, p_sbinfo->bins_per_sbk[sbk]-sum ); 
    vcopy( &doubleZero ,   &p_core[offset], 0, 1, p_sbinfo->bins_per_sbk[sbk]-sum ); 
  }
}


void  decodeDiffCtrl(
                     BsBitStream * fixed_stream, 
                     int diffControl[ ],
                     int *decodedBits, 
                     int fssGroups)
{
  unsigned long int   ultmp, fssIdx, diffControlTmp;
  int fssG,sfb;
  for (sfb=0;sfb<60;sfb++){
    diffControl[sfb]=0;
  }
  sfb=0;
  for (fssG=0;fssG<fssGroups;fssG++){
    diffControlTmp=0;
    BsGetBit( fixed_stream, &ultmp, 2 );
    *decodedBits += 2;
    fssIdx=ultmp;
    switch (ultmp){
    case 0 : diffControlTmp |=0;
      break;
    case 1 : diffControlTmp |=15;
      break;
    default :
      BsGetBit( fixed_stream, &ultmp, 2 );
      *decodedBits += 2;
      fssIdx= (fssIdx<<2)| ultmp;
      switch (fssIdx){
      case  8:  diffControlTmp |=7;
        break;
      case  9:  diffControlTmp |=8;
        break;
      default:
        BsGetBit( fixed_stream, &ultmp, 1 );
        *decodedBits += 1;
        fssIdx= (fssIdx<<1)| ultmp;
        switch (fssIdx) {
        case 20:
        case 21:
        case 22:
        case 23:
        case 24:
        case 25:
          diffControlTmp |= (fssIdx-19);
          break;
        case 26:
        case 27:
        case 28:
        case 29:
        case 30:
        case 31:
          diffControlTmp |= (fssIdx-17);
          break;
        default:
          CommonExit(-1,"\nfssdecode error");
        }
        break;
      }
    }
    diffControl[sfb+3]= ((diffControlTmp & 0x1)!=0);
    diffControl[sfb+2]= ((diffControlTmp & 0x2)!=0);
    diffControl[sfb+1]= ((diffControlTmp & 0x4)!=0);
    diffControl[sfb+0]= ((diffControlTmp & 0x8)!=0);
    sfb +=4;      
  }
}
static int diffContrBits; /* should be an array of sampling rates */

static int decode_grouping( int grouping, short region_len[] )
{
  int i, rlen, mask;

  int no_short_reg = 0;

  mask = 1 << ( 8-2 );
  rlen = 1;  /* min. length of first group is '1' */
  for( i = 1; i<8; i++ ) {
    if( (grouping & mask) == 0) {
      *region_len++ = rlen;
      no_short_reg++;
      rlen = 0;
    }
    rlen++;
    mask >>= 1;
  }
  *region_len = rlen;
  no_short_reg++;

  return( no_short_reg );
}

void aacScaleableDecode( 
  BsBitStream *fixed_stream,
  BsBitStream *gc_WRstream[],
  WINDOW_TYPE block_type[MAX_TIME_CHANNELS],
  int    *decodedBits,
  double *spectral_line_vector[MAX_TF_LAYER][MAX_TIME_CHANNELS],
  int    block_size_samples,
  int output_select,
  Info ** sfbInfo,
  int numChannels,
  long int samplRateFw
)
{
  static int opMode;
  static int lowRateChannelPresent;
  static enum CORE_CODEC  coreCodecIdx;
  static int bitrateIndex,mainSamplingFreqIdx,paddingBit,protectionBit,mainDataBegin;
  static Window_shape windowShape =  WS_FHG;
  static int coreNumBit = 160;
  static long gran_bits;
  static int samplRate;
  static int bitRate;
  static int nrGranules = 3;
  static int lastAacLay = 0;  
  static int firstAacLay = 1;  
  static int decoded_fixed_frame_bits;
  static int layNumChan[MAX_TF_LAYER];
  static int firstStLay;
  static int lastMonoLay;
  static int firstMonoLay;
  unsigned long ultmp,codedBlockType;
  int diffControl[MAX_TF_LAYER][MAX_TIME_CHANNELS][ 60 ]={{{0x0}}};
  float low_sr_time_buffer[MAX_TIME_CHANNELS][960]; 
  int aacLayer;
  int ch,commonWindow,calcMonoLay;
  int fssGroups;
  int maxSfbMed;
  double core_spectrum[MAX_TIME_CHANNELS][2048];
  double *low_spec;
  int diffControlBands[MAX_TF_LAYER];
  int i,tmp, rest_gran,dyn_bits,fill_bits;
  int msMask[8][60]={{0x0}};
  int msMaskPres;
  int shortFssWidth;
  TNS_frame_info tns_info[MAX_TIME_CHANNELS];
  byte max_sfb[Winds];

  *decodedBits = 0;


  /*********************/
  /* decode frame header */
  if( gran == 0 ) {
    decoded_fixed_frame_bits = 0;

    BsGetBit( fixed_stream, &ultmp, 7 );     
    *decodedBits += 7;
    if  ( ultmp != 0x37 ) {
      CommonExit(-1,"\n no sync found");
    }

   BsGetBit( fixed_stream, &ultmp, 4 );      
    opMode = (int)ultmp;
      
    *decodedBits += 4;
    for (aacLayer=0;aacLayer<MAX_TF_LAYER;aacLayer++){
      layNumChan[aacLayer]=0;
    }
    
    firstStLay=-1;
    lastAacLay=0;
    
    switch (opMode) {   
     case 2:
       lowRateChannelPresent=0;
       layNumChan[1]=1;
       lastAacLay=1;            
       commonWindow=0; 
       break;
     case 3:
       lowRateChannelPresent=0;
       layNumChan[1]=2;
       lastAacLay=1;
       commonWindow=1; 
       firstStLay=1;
       break;
     case 4: 
       lowRateChannelPresent=1;
       lastAacLay=1;
       commonWindow=0; 
       layNumChan[1]=1;
       break;
    case 5: 
      lowRateChannelPresent=1;
      lastAacLay=1;
      commonWindow=1; 
      layNumChan[1]=2;
      firstStLay=1;
      break;
    case 6: 
      lowRateChannelPresent=2;
      lastAacLay=1;
      commonWindow=1; 
      layNumChan[1]=2;
      firstStLay=1;
      break;
    case 7: 
      lowRateChannelPresent=1;
      lastAacLay=2;
      layNumChan[1]=1;
      layNumChan[2]=1;
      commonWindow=0; 
      break;
    case 8: 
      lowRateChannelPresent=1;
      lastAacLay=2;
      layNumChan[1]=1;
      layNumChan[2]=2;
      commonWindow=1; 
      firstStLay=2;
      break;
    case 11: 
      lowRateChannelPresent=0;
      lastAacLay=2;
      layNumChan[1]=1;
      layNumChan[2]=1;
      commonWindow=0; 
      break;
    case 12: 
      lowRateChannelPresent=0;
      lastAacLay=2;
      layNumChan[1]=1;
      layNumChan[2]=2;
      commonWindow=1;
      firstStLay=2;
      break;
    case 14: 
      lowRateChannelPresent=1;
      lastAacLay=3;
      layNumChan[1]=1;
      layNumChan[2]=1;
      layNumChan[3]=1;
      commonWindow=0; 
      break;
    default:
      CommonExit(-1,"this scaleable mode is not yet supported %d",opMode); 
    }

      
    if (lowRateChannelPresent){
      BsGetBit( fixed_stream, &ultmp, 4 );      
      coreCodecIdx=(enum CORE_CODEC) ultmp;
      *decodedBits += 4;
    
    }else {
      coreCodecIdx = NO_CORE;
    }
    if( (opMode>=7) && (opMode<=13) ){
      BsGetBit(fixed_stream, &ultmp,2);
      lastAacLay=(int)ultmp+2;
      *decodedBits += 2;      
    }
    
    if (layNumChan[lastAacLay] > numChannels)
      CommonExit(-1," \nwrong num of channels given by cmdline ");

    if (firstStLay!=-1){
      lastMonoLay=firstStLay-1;
      if (lastMonoLay==0){
        lastMonoLay=-1;
      }
    }else {
      lastMonoLay=lastAacLay;
    }
    if (lastMonoLay>0){
      firstMonoLay=1;
    }else {
      firstMonoLay=-1;
    }


    BsGetBit( fixed_stream, &ultmp,4);
    mainSamplingFreqIdx = (int)ultmp;
    *decodedBits += 4;
    
    BsGetBit( fixed_stream, &ultmp,4  );      
    bitrateIndex = (int)ultmp;
    *decodedBits += 4;
 
    BsGetBit( fixed_stream, &ultmp,1  );      
    paddingBit=(int)ultmp;
    *decodedBits += 1;
    
    BsGetBit( fixed_stream, &ultmp,1  );      
    protectionBit=(int)ultmp;
    *decodedBits += 1;
    
    BsGetBit( fixed_stream, &ultmp,10);
    mainDataBegin=(int)ultmp;
    *decodedBits += 10;
    bitRate=getBitRate(bitrateIndex);
    samplRate=getSamplRate(mainSamplingFreqIdx);
    if (samplRateFw!=samplRate){
      CommonExit(-1,"\nset sample rate in commandline to: : \"-s %d\" ",samplRate);
    }

    gran_bits = bitRate * block_size_samples /samplRate;
  } 
  /* gran == 0 : end frame header*/
  /*****************************/
  /* decode core bitstream*/
  if (lowRateChannelPresent){
    
    if( core_init ) {
      for (ch=0;ch<lowRateChannelPresent;ch++){
        CoreDecoderInit( samplRate, coreCodecIdx, nrGranules, ch, output_select );
      }
      core_init = 0;
    }
    for (ch=0;ch<lowRateChannelPresent;ch++){
      tmp = CoreDecoder( fixed_stream, low_sr_time_buffer[ch], 960, 0, ch, gran ); 
      *decodedBits += tmp;
    }
  }
  
  /************************/
  /* decode scaleable  header */
  {
    if  (!protectionBit) {
      BsGetBit( fixed_stream, &ultmp,16);
      *decodedBits += 16;  
    } 
    /* ics_info()*/
    BsGetBit( fixed_stream, &ultmp,1);/* reserved bit */
    *decodedBits += 1;

    BsGetBit( fixed_stream, &ultmp,2); /* window_sequence */
    codedBlockType = (int)ultmp;
    *decodedBits += 2;
    switch (   codedBlockType )
      {
      case 0: 
	block_type[MONO_CHAN] =  ONLY_LONG_WINDOW;
	break;
      case 1: 
	block_type[MONO_CHAN] =  LONG_SHORT_WINDOW;
	break;
      case 2: 
	block_type[MONO_CHAN] =  ONLY_SHORT_WINDOW;
	break;
      case 3: 
	block_type[MONO_CHAN] =  SHORT_LONG_WINDOW;
	break;
      default: 
	CommonExit(-1,"wrong blocktype %d",   codedBlockType);
      }

    BsGetBit( fixed_stream, &ultmp,1);
    windowShape = (Window_shape)ultmp; /* window shape */
    *decodedBits += 1;

    if (block_type[MONO_CHAN]== ONLY_SHORT_WINDOW ){
      BsGetBit( fixed_stream, &ultmp,4);        /* max_sfb */
      *decodedBits += 4;
      max_sfb[firstAacLay]=ultmp;
      BsGetBit( fixed_stream, &ultmp,7);        /* scale_factor_grouping */
      *decodedBits += 7;
       sfbInfo[block_type[MONO_CHAN]]->num_groups = decode_grouping( ultmp, sfbInfo[block_type[MONO_CHAN]]->group_len );
    }else {
      BsGetBit( fixed_stream, &ultmp,6);          /* max_sfb */
      *decodedBits += 6;
      max_sfb[firstAacLay]=ultmp;
      BsGetBit( fixed_stream, &ultmp,1);         /* prediction */
      *decodedBits += 1;
      if (ultmp!=0){
        CommonExit(-1,"\n prediction currently not supproted in scaleable mode");
      }
    }
    /* end of ics_info()*/

    /* rest fo aac_scaleable_header */

    /* [predictor data should be parsed here] */

    if( layNumChan[firstAacLay]==2 ){
      int g,sfb,win;
      int gwin;
      BsGetBit( fixed_stream, &ultmp,2);     /* ms_mask_present ? */
      *decodedBits += 2;
      msMaskPres = ultmp;
      if (msMaskPres==1){          
        win=0;
        for (g=0;g<sfbInfo[block_type[MONO_CHAN]]->num_groups;g++){
          for (sfb=0;sfb<max_sfb[firstAacLay];sfb++){
            BsGetBit( fixed_stream, &ultmp,1);    /* ms_mask */
            *decodedBits += 1;
            msMask[win][sfb]=ultmp;
          }
          for (gwin=1;gwin<sfbInfo[block_type[MONO_CHAN]]-> group_len[g];gwin++){
            for (sfb=0;sfb<max_sfb[firstAacLay];sfb++){                
              msMask[win+gwin][sfb]=msMask[win][sfb];/* apply same ms mask to all subwindows of same group */
            }
          }
          win += (gwin -1);
        }          
      }else if (msMaskPres==2){
        win=0;
        for (g=0;g<sfbInfo[block_type[MONO_CHAN]]->num_groups;g++){
          for (gwin=0;gwin<sfbInfo[block_type[MONO_CHAN]]-> group_len[g];gwin++){
            for (sfb=0;sfb<max_sfb[firstAacLay];sfb++){
              msMask[win][sfb]=1;
            }
            win++;
          }
        }
      }  
    }    
  }
  diffControlBands[firstAacLay] =0;
  for (ch=0;ch<layNumChan[lastAacLay];ch++){
    BsGetBit( fixed_stream, &ultmp,1);           /* tns */
    *decodedBits += 1;
    if( ultmp ) {
      get_tns_vm( fixed_stream, sfbInfo[block_type[MONO_CHAN]], &tns_info[ch] ,decodedBits);
    } else {
      clr_tns( sfbInfo[block_type[MONO_CHAN]], &tns_info[ch] );
    }
    BsGetBit( fixed_stream, &ultmp,1);           /* sony gain control not used */
    *decodedBits += 1;
    if (ultmp!=0){
      CommonExit(-1,"\n sony gaincontrol not supported for aac-scaleable");
    }
    
    if ( (coreCodecIdx!=NO_CORE) &&(ch<layNumChan[firstAacLay] ) ) {
      if (block_type[MONO_CHAN] ==  ONLY_SHORT_WINDOW){
        int g;
        for (g=0;g<8;g++){
          BsGetBit( fixed_stream,&ultmp, 1 );  /* short FSSwitch  1st aacLayer  */
          *decodedBits += 1;
          diffControl[firstAacLay][ch][g]= ultmp;
          if (ch==0){
            diffControlBands[firstAacLay] +=1;
          }
        }
      } else {
        decodeDiffCtrl(fixed_stream,diffControl[firstAacLay][ch],decodedBits,sfbInfo[block_type[MONO_CHAN]]->longFssGroups);/*  FSSwitch 1st aacLayer */
        if (ch==0){
          diffControlBands[firstAacLay] +=sfbInfo[block_type[MONO_CHAN]]->longFssGroups*4;
        }
      }
    }
  }     
  
    /* start of aac_scaleable_extension_stream */
    
    for ( aacLayer=firstAacLay+1;aacLayer<=lastAacLay;aacLayer++){
      if (block_type[MONO_CHAN]== ONLY_SHORT_WINDOW){
        BsGetBit( fixed_stream, &ultmp,4);          /* max_sfb_med */
        *decodedBits += 4;
        max_sfb[aacLayer]=ultmp;
      } else {
        BsGetBit( fixed_stream, &ultmp,6);          /*  max_sfb_med */
        *decodedBits += 6;
        max_sfb[aacLayer]=ultmp;
      }
      /* rest of predictor data should be parsed here */
      
      if(commonWindow){  /* rest of ms mask which was not transmitted in previous layer */
        int g,sfb,win,gwin;
        int startSfb;
        if ( layNumChan[aacLayer-1] != layNumChan[aacLayer] ){
          BsGetBit( fixed_stream, &ultmp,2);     /* ms_mask_present ? */
          *decodedBits += 2;
          msMaskPres = ultmp;          
        }
        if (msMaskPres==1){
          win=0;
          for (g=0;g<sfbInfo[block_type[MONO_CHAN]]->num_groups;g++){
            if (layNumChan[aacLayer-1]!=layNumChan[aacLayer]){
              startSfb=0;
            } else {
              startSfb=max_sfb[aacLayer-1];
            }
            for (sfb=startSfb;sfb<max_sfb[aacLayer];sfb++){
              BsGetBit( fixed_stream, &ultmp,1);    /* ms_mask */
              *decodedBits += 1;
              msMask[win][sfb]=ultmp;
            }
            for (gwin=1;gwin<sfbInfo[block_type[MONO_CHAN]]-> group_len[g];gwin++){
              for (sfb=startSfb;sfb<max_sfb[aacLayer];sfb++){                
                msMask[win+gwin][sfb]=msMask[win][sfb];/* apply same ms mask to all subwindows of same group */
              }
            }
            win += (gwin -1);
          }          
        }else if (msMaskPres==2){
          win=0;
          for (g=0;g<sfbInfo[block_type[MONO_CHAN]]->num_groups;g++){
            if (layNumChan[aacLayer-1]!=layNumChan[aacLayer]){
              startSfb=0;
            } else {
              startSfb=max_sfb[aacLayer-1];
            }
            for (g=0;g<sfbInfo[block_type[MONO_CHAN]]->num_groups;g++){
              for (gwin=0;gwin<sfbInfo[block_type[MONO_CHAN]]-> group_len[g];gwin++){
                for (sfb=startSfb;sfb<max_sfb[aacLayer];sfb++){
                  msMask[win][sfb]=1;
                }
                win++;
              }
            }
          }  
        }
      }
      diffControlBands[aacLayer] =0;       /* rest of FSSwitch for the second channel which was not transmitted in previous layer */
      if ( (coreCodecIdx!=NO_CORE) ) {
        int sfb,g;
        if ( layNumChan[aacLayer-1] != layNumChan[aacLayer] ){
          for (ch=0;ch<layNumChan[aacLayer];ch++){
            if (block_type[MONO_CHAN] ==  ONLY_SHORT_WINDOW){
              diffControlBands[aacLayer] = 8;
              for (g=0;g<8;g++){
                BsGetBit( fixed_stream,&ultmp, 1 );  /* short FSS */
                *decodedBits += 1;
                diffControl[aacLayer][ch][g]= ultmp;                
              }
            } else {
              diffControlBands[aacLayer] = max_sfb[aacLayer-1];
              for (sfb=0;sfb< max_sfb[aacLayer-1];sfb++){
                if (msMask[0][sfb]==0) {
                  BsGetBit( fixed_stream,&ultmp, 1 );  /* short FSS */
                  *decodedBits += 1;
                  diffControl[aacLayer][ch][sfb]= ultmp;
                } else {
                  diffControl[aacLayer][ch][sfb]= 0;/* allways on if ms on  channel */
                }
              }
              /*               decodeDiffCtrl(fixed_stream,diffControl[aacLayer][ch],decodedBits,sfbInfo[block_type[MONO_CHAN]]->longFssGroups);   long FSS*/ 
            }
          }        
        }
      }
    }
  
    /**********************************************************************************/
    /* get real dynpart start in dynpart bitstream buffer by subtracting the back ptr */
    /**********************************************************************************/
    if (gran==0){
      if(  (mainDataBegin << 3) == (dynBitBuf->numBit-dyn_stream_read->currentBit) ) {
        /* ok, exact */
      } else if ( (mainDataBegin << 3) < (dynBitBuf->numBit-dyn_stream_read->currentBit)  ) {
        /* incorrect decoding in the last frame */
        dyn_stream_read->currentBit +=  (dynBitBuf->numBit-dyn_stream_read->currentBit)  - (mainDataBegin << 3); 
      } else {
        CommonExit(-1,"\nsync error");
      }
    }
    /* up-sampling of core coder:
       we need the block type, therefore we can only do it after the granule header */
    for (ch=0;ch<lowRateChannelPresent;ch++){
      mdct_core( (block_type[MONO_CHAN]), windowShape, low_sr_time_buffer[ch]+gran*((960*8000)/samplRate), 
                 core_spectrum[ch],
                 0, samplRate, block_size_samples );
    }


  /* decode byte allign bits, if it is the last granule */
    decoded_fixed_frame_bits += *decodedBits;
    if( gran == (nrGranules-1) ) {
      
      tmp = 8 - decoded_fixed_frame_bits%8;
      tmp = (tmp == 8) ? 0 : tmp;
      
      BsGetBit( fixed_stream, &ultmp, tmp );
      *decodedBits += tmp;
      decoded_fixed_frame_bits += tmp;
    }
    
    /* copy the rest of the granule to the dynamic part buffer */
    rest_gran = gran_bits - *decodedBits;
    
    if( gran == 0 ) {
      dyn_bits  = dynBitBuf->numBit - dyn_stream_read->currentBit;
      fill_bits = dyn_bits - (mainDataBegin << 3);
      
      if( fill_bits < 0 ) {
        CommonExit(-11,"MainDataBegin miss-match");
      } else {
        while( fill_bits > 16 ) {
          BsGetBit( dyn_stream_read, &ultmp, 16 );
          fill_bits -= 16;
        }
        BsGetBit( dyn_stream_read, &ultmp, fill_bits );
      }
    }
    
    if( BsGetBufferAppend( fixed_stream, dynBitBuf, 1, rest_gran ) )
      CommonExit(-1,"\n Decode dyn bitstream : error get buffer" ) ;
    *decodedBits +=rest_gran;
    if ( *decodedBits != gran_bits){ 
      CommonExit(-1,"\n Decode dyn bitstream bitcount error" ) ;
    }
    /* decode intermediate  and  high quality frame */
    /* decode intermediate layer */
    for (aacLayer= firstAacLay;  aacLayer <= lastAacLay ; aacLayer++) {
      tmp = aac_decode_frame( dyn_stream_read,
                              gc_WRstream,
                              spectral_line_vector[aacLayer], 
                              (int*)&(block_type[MONO_CHAN]), 
                              &windowShape,
                              SCALEABLE,&max_sfb[aacLayer],layNumChan[aacLayer],commonWindow,sfbInfo );                  
      /* remove all completely read bytes */
      tmp = dyn_stream_read->currentBit/8;
      for( i=0; i<(dynBitBuf->size>>3)-tmp; i++ ) {
        dynBitBuf->data[i] = dynBitBuf->data[i+tmp];
      }
      dyn_stream_read->currentBit -= tmp*8;
      dynBitBuf->numBit -= tmp*8;  
    }

    if ( lastAacLay < output_select ) {
      output_select = lastAacLay;
    }

    if (output_select > lastMonoLay ){
      calcMonoLay=lastMonoLay ;
    } else {
      calcMonoLay=output_select ;      
    }

    /* combine all mono layers */
    for (aacLayer=firstAacLay+1 ; aacLayer <= calcMonoLay ; aacLayer++) {
        vadd(   spectral_line_vector[firstAacLay][MONO_CHAN],spectral_line_vector[aacLayer][MONO_CHAN],spectral_line_vector[firstAacLay][MONO_CHAN],  
                1,1,1, sfbInfo[block_type[MONO_CHAN]]->bins_per_bk );
    }
    
    /* combine all stereo layers */
    
    if (firstStLay!=-1 ) {
      for (aacLayer=firstStLay+1 ; aacLayer <= output_select ; aacLayer++) {
        for (ch=0;ch<layNumChan[aacLayer];ch++){              
          vadd(   spectral_line_vector[firstStLay][ch],spectral_line_vector[aacLayer][ch],spectral_line_vector[firstStLay][ch],  
                  1,1,1, sfbInfo[block_type[MONO_CHAN]]->bins_per_bk );
        }
      }
    }
    /* fss for aac mono layer */
    low_spec=core_spectrum[0];
    if ( (output_select > 0) && (lastMonoLay>0) ){
      double tmp[1024];
      shortFssWidth = sfbInfo[block_type[MONO_CHAN]]->shortFssWidth;
      if (lowRateChannelPresent) {
        FSSwitch( low_spec, spectral_line_vector[firstAacLay][MONO_CHAN],
                  tmp,
                  diffControl[firstAacLay][MONO_CHAN], sfbInfo[block_type[MONO_CHAN]] ,diffControlBands[firstAacLay] , shortFssWidth,1 );    
        vcopy (  tmp, spectral_line_vector[firstAacLay][MONO_CHAN],1,1 ,sfbInfo[block_type[MONO_CHAN]]->bins_per_bk);
      }
      
      low_spec=spectral_line_vector[firstAacLay][MONO_CHAN];
    } 
    /* fss for aac stereo layer */
    if ( (output_select >= firstStLay ) && (firstStLay!=-1 ) && (layNumChan[firstAacLay]==1)){
      double tmp_spec[1024];
    /* inverse ms matrix */
    
      multCoreSpecMsFac(sfbInfo[block_type[MONO_CHAN]],msMask,low_spec,tmp_spec);
      if (layNumChan[firstAacLay]==2 ){
        shortFssWidth = sfbInfo[block_type[MONO_CHAN]]->shortFssWidth;
      }else{
        if  (max_sfb[aacLayer-1]!=0) {
          shortFssWidth = sfbInfo[block_type[MONO_CHAN]]->sbk_sfb_top[0][ max_sfb[firstStLay-1]-1] ; 
        } else {
          shortFssWidth=0;
        }
      }
      for (ch=0;ch<layNumChan[firstStLay];ch++){                    
        FSSwitchSt( tmp_spec, spectral_line_vector[firstStLay][ch],
                  spectral_line_vector[firstAacLay][ch],
                  diffControl[firstStLay][ch], sfbInfo[block_type[MONO_CHAN]] , diffControlBands[firstStLay],shortFssWidth,msMask,ch);    
      }
      doInverseMsMatrix( sfbInfo[block_type[MONO_CHAN]],spectral_line_vector[firstAacLay][0], spectral_line_vector[firstAacLay][1],  msMask );
    } else if ((output_select >= firstStLay ) && (firstStLay!=-1 )  ){
      double tmp_spec[1024];
      doInverseMsMatrix( sfbInfo[block_type[MONO_CHAN]],spectral_line_vector[firstStLay][0], spectral_line_vector[firstStLay][1],  msMask );
      if (lowRateChannelPresent){
        multCoreSpecMsFac(sfbInfo[block_type[MONO_CHAN]],msMask,low_spec,tmp_spec);
        for (ch=0;ch<layNumChan[firstStLay];ch++){                    
          FSSwitch( tmp_spec, spectral_line_vector[firstStLay][ch],
                    spectral_line_vector[firstAacLay][ch],
                    diffControl[firstStLay][ch], sfbInfo[block_type[MONO_CHAN]] ,diffControlBands[firstStLay] , sfbInfo[block_type[MONO_CHAN]]->shortFssWidth ,1 );    
        }
      }
    }

#if 0
#ifdef DEBUGPLOT 
    plotSend("c", "mdctCore",  MTV_DOUBLE_SQA,960, low_spec , NULL);

    plotSend("r", "mdctSpecR",  MTV_DOUBLE_SQA,960, spectral_line_vector[firstAacLay][0] , NULL);
    plotSend("l", "mdctSpecL" , MTV_DOUBLE_SQA,960, spectral_line_vector[firstAacLay][1] , NULL);
#endif    
#endif
    if (output_select==0) {
      double zero  = 0;
      int no_win   = (block_type[MONO_CHAN] == ONLY_SHORT_WINDOW) ? 8 : 1;
      int no_lines = 960/no_win;
      int limit    = 8000*no_lines/samplRate;
      if( samplRate%1000 ) limit = (44100/6)*no_lines/samplRate;
      limit--;

      for (ch=0;ch<layNumChan[lastAacLay];ch++){
        register int win;
        for( win=0; win<no_win; win++ ) {
          vcopy( &core_spectrum[0][win*no_lines], &spectral_line_vector[MONO_CHAN][ch][win*no_lines],          1, 1, limit );
          vcopy( &zero,                           &spectral_line_vector[MONO_CHAN][ch][win*no_lines+limit], 0, 1, no_lines-limit ); 
        }
      }
    } else {
      if (layNumChan[output_select]==2){
        for (ch=0;ch<layNumChan[lastAacLay];ch++){
          vcopy( spectral_line_vector[firstAacLay][ch] ,   spectral_line_vector[0][ch] , 1, 1,  sfbInfo[block_type[MONO_CHAN]]->bins_per_bk ); 
        }        
      } else {
        for (ch=0;ch<numChannels;ch++){
          vcopy( spectral_line_vector[firstAacLay][MONO_CHAN] ,   spectral_line_vector[0][ch] , 1, 1,  sfbInfo[block_type[MONO_CHAN]]->bins_per_bk ); 
        }        
      }
    }

  /* tns decoder */
    if ( output_select!=0 ){
    for (ch=0;ch<layNumChan[lastAacLay];ch++){      
      int k, j;
      Info *info = sfbInfo[block_type[MONO_CHAN]];
      
      for (i=j=0; i<tns_info[ch].n_subblocks; i++) {
        float tmp_spec[960];
        for( k=0; k<info->bins_per_sbk[i]; k++ ) {
          tmp_spec[k] = spectral_line_vector[0][ch][j+k];
        }
        tns_decode_subblock( tmp_spec,
                             max_sfb[0],   /* max_sfb[wn] Attention: wn and not ch !! */
                             info->sbk_sfb_top[i],
                             info->islong,
                             &(tns_info[ch].info[i]) );      
        
        for( k=0; k<info->bins_per_sbk[i]; k++ ) {
          spectral_line_vector[0][ch][j+k] = tmp_spec[k];
        }
        
        j += info->bins_per_sbk[i];
      }
    }
    }

  /* increment granule counter */
  gran += 1;
  if( gran == nrGranules ) {
    gran = 0;
  }
}



