/**********************************************************************
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 <assert.h>
#include "all.h"
#include "port.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"
#include "sam_dec.h"    /* HP 980211 */
#include "flex_mux.h"
#include "ntt_conf.h"
#include "plotmtv.h"
#include "interface.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;

}

/* compute scalar product of two vectors */
static double scalprod( double src1[], double src2[], 
                        int inc_src1, int inc_src2, int vlen)
{
  int i;
  double sum=0.0;

  for (i=0;i<vlen; i++) {
    sum += (*src1)*(*src2);
    src1 += inc_src1;
    src2 += inc_src2;
  }
  return (sum);
}

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;
  }
}

static void dec_lowpass(double spectrum[], int lopLong,
                        int lopShort, int maxLine, int iblen, 
                        int block_type, int nr_of_sbk)
{
  int bl, block_len, lop, i;
  float slope;
  double zero = 0.0;

  if (block_type != ONLY_SHORT_WINDOW) {
    lop = lopLong;
  }
  else {
    lop = lopShort;
  }
    
  block_len = iblen /nr_of_sbk;
  if (lop > maxLine) {
    lop = maxLine;
  }
  slope = (1.0F /(float)lop);
  for (bl=0;bl<nr_of_sbk;bl++){
    vcopy( &zero, &spectrum[bl*block_len+maxLine], 0, 1, block_len - maxLine);
    for (i=1; i<lop; i++) {
      spectrum[bl*block_len+maxLine-i] *= (i*slope);
    }
  }
}

/* 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];

    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];

    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, sfb;
  int dc_decoded[8][128];
  short sfbWidth[200];
  double doubleZero=0.0;
  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 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,
                          int               lopLong,
                          int               lopShort,
                          float             normBw,
                          Window_shape*     windowShape,
                          QC_MOD_SELECT     qc_select,
                          int               bsacDecBr,
                          HANDLE_RESILIENCE hResilience,
                          HANDLE_BUFFER     hVm,
                          HANDLE_BUFFER     hHcrSpecData,
                          HANDLE_HCR        hHcrInfo ,
                          FRAME_DATA* fd,
                          HANDLE_EP_INFO    hEPInfo )
{
  static int opMode;
  static unsigned int x;
  static int lowRateChannelPresent;
  static enum CORE_CODEC  coreCodecIdx;
  static int bitrateIndex,mainSamplingFreqIdx,protectionBit,mainDataBegin;
  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;
  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;
  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];
  static byte sfbCbMap[MAX_TF_LAYER][MAX_TIME_CHANNELS][MAXBANDS] = {{{0x0}}};
  int  core_used_bits;
  int  groupInfo;
  int  tns_data_present[2];
  int  gain_control_data_present[2];
  int   used_bits[4][2];
  unsigned long totalLength;

  *decodedBits = 0;
  core_used_bits = 0;

  /*********************/
  if (fd != NULL ) {
    for (x=0;x<fd->od->streamCount.value ;x++){
      unsigned int AUindex;/* AUindex = scaleable layer Number , since we have not stream map table*/
      getAccessUnit ( fixed_stream, fd->layer[x].bitBuf, &AUindex, &totalLength );
    }
  } else {
  /* 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;
    case 15:
      lowRateChannelPresent=0;
      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;
    }


    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  );      
    *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;
      core_used_bits += tmp;
    }
  }
  
  /************************/
  /* decode scaleable  header */
  {
    if (fd == NULL ) {
    if  (!protectionBit) {
      BsGetBit( fixed_stream, &ultmp,16);
      *decodedBits += 16;  
    } 
    }
    
    if (fd != NULL ) {
      fixed_stream= BsOpenBufferRead(fd->layer[0].bitBuf); 
      /* open the first aac layer to read, assume that no core layer is present */
    }
    /* 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 */
      groupInfo = ultmp;
      *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 */
    tns_data_present[ch] = ultmp;
    *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 */
    gain_control_data_present[ch] = ultmp;
    *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;
        }
      }
    }
  }     
  

  used_bits[firstAacLay][0] = *decodedBits;
  /* start of aac_scaleable_extension_stream */
    
  if(qc_select == AAC_SCALEABLE)
    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*/ 
            }
          }        
        }
      }
      used_bits[aacLayer][0] = *decodedBits;
    }
  
  /**********************************************************************************/
  /* 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 */
    mdct_core( (block_type[MONO_CHAN]), *windowShape, low_sr_time_buffer[ch]+gran*((960*8000)/samplRate), 
               core_spectrum[ch],
               0, samplRate, block_size_samples );
#if 1
    if (output_select != 0) {
      /* tns encoder */
      int k, j;
      Info *info =sfbInfo[block_type[MONO_CHAN]];
      info->islong = (block_type[MONO_CHAN] != ONLY_SHORT_WINDOW);
        
      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] = core_spectrum[ch][j+k];
        }
        tns_encode_subblock( tmp_spec,
                             max_sfb[1],   /* 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++ ) {
          core_spectrum[ch][j+k] = tmp_spec[k];
        }
          
        j += info->bins_per_sbk[i];
      }
    }
#endif

  }


  /* 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 */
  if(qc_select == AAC_SCALEABLE) {
    for (aacLayer= firstAacLay;  aacLayer <= lastAacLay ; aacLayer++) {
      tmp = aac_decode_frame( dyn_stream_read,
                              gc_WRstream,
                              spectral_line_vector[aacLayer], 
                              &(block_type[MONO_CHAN]), 
                              windowShape,
                              SCALEABLE,
                              &max_sfb[aacLayer],
                              layNumChan[aacLayer],
                              commonWindow,
                              sfbInfo, 
                              sfbCbMap[aacLayer],
                              hResilience,
                              hVm,
                              hHcrSpecData,
                              hHcrInfo,
                              hEPInfo );
      used_bits[aacLayer][1] = tmp;
      /* 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;  
    }

  } else {        /* qc_select == AAC_SCA_BSAC */

    tmp = sam_decode_core_bsac(dyn_stream_read,
                               bsacDecBr,
                               spectral_line_vector[firstAacLay], 
                               block_type[MONO_CHAN], 
                               *windowShape,
                               max_sfb[firstAacLay],
                               groupInfo,
                               core_used_bits,
                               layNumChan[lastAacLay]);

    /* 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 ;      
  }

  /* compute PNS and restore spectrum */
  {
    int sfb, maxSfb, lineIdx=0;
    int prevSfbCb,sfbCb, sfbWidth;
    double energy, zero = 0.0;
 
    if (sfbInfo[block_type[MONO_CHAN]]->islong) {
 
      for (aacLayer=firstAacLay+1; aacLayer <= calcMonoLay; aacLayer++) {       
        /* for the first layer do nothing */
        maxSfb = (max_sfb[aacLayer-1]<max_sfb[aacLayer])?max_sfb[aacLayer-1]:max_sfb[aacLayer];

        for (sfb=0; sfb<maxSfb; sfb++) {
          prevSfbCb = (int)sfbCbMap[aacLayer-1][MONO_CHAN][sfb];
          sfbCb     = (int)sfbCbMap[aacLayer][MONO_CHAN][sfb];
          if (sfb==0) {
            sfbWidth = sfbInfo[block_type[MONO_CHAN]]->bk_sfb_top[sfb];
          }
          else {
            sfbWidth = sfbInfo[block_type[MONO_CHAN]]->bk_sfb_top[sfb]-sfbInfo[block_type[MONO_CHAN]]->bk_sfb_top[sfb-1];
          }

          if (prevSfbCb == NOISE_HCB) {
            energy = scalprod(&spectral_line_vector[aacLayer][MONO_CHAN][lineIdx], &spectral_line_vector[aacLayer][MONO_CHAN][lineIdx], 1, 1, sfbWidth);
            /* if sfb of enhancement layer has MDCT lines, set sfb of previous layer to 0 */
            if (energy > 0) {
              vcopy(&zero, &spectral_line_vector[aacLayer-1][MONO_CHAN][lineIdx], 0 ,1 ,sfbWidth);
            }
            else {
              sfbCbMap[aacLayer][MONO_CHAN][sfb] = sfbCbMap[aacLayer-1][MONO_CHAN][sfb];
              vcopy(&spectral_line_vector[aacLayer-1][MONO_CHAN][lineIdx],&spectral_line_vector[aacLayer][MONO_CHAN][lineIdx], 1, 1, sfbWidth);
              vcopy(&zero,&spectral_line_vector[aacLayer-1][MONO_CHAN][lineIdx], 0, 1, sfbWidth);  
            }
            if (sfbCb == NOISE_HCB) {
              CommonWarning("Two consecutive layers have PNS in same SFB !");
            } 
          }
          lineIdx += sfbWidth; 
        }
      }    
    }
  }

  /* 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 ); 
      }        
    }
  }

  /* Bandwidth control */
  if ((lopLong != 0) && (max_sfb[lastAacLay] != 0)) {
    int maxline;
      
    if (normBw == 0.0F) {
      maxline = sfbInfo[block_type[MONO_CHAN]]->sbk_sfb_top[0][max_sfb[lastAacLay]-1];
    }
    else {
      maxline = (int)((float)(sfbInfo[block_type[MONO_CHAN]]->bins_per_bk /sfbInfo[block_type[MONO_CHAN]]->nsbk)*normBw + 0.5);
    } 
    for (ch=0; ch<layNumChan[lastAacLay]; ch++) {
      dec_lowpass(spectral_line_vector[0][ch], lopLong, lopShort, maxline,
                  sfbInfo[block_type[MONO_CHAN]]->bins_per_bk, block_type[MONO_CHAN],
                  sfbInfo[block_type[MONO_CHAN]]->nsbk);
    }
  }

  /* 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[output_select],  
                             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;
  }
}





void getModeFromOD(OBJECT_DESCRIPTOR *od,int *lowRateChannelPresent,int *layNumChan,int *lastAacLay,int *firstStLay, enum CORE_CODEC* coreCoderIndex)
{
  
  int nEsNumber, i, aac=0, nAacLay = 0;
  int nLowRateChan = 0;
  int audioDecType;
  int nFirstStereo = -1;
  int tfType;
  nEsNumber   = od->streamCount.value;
  *coreCoderIndex=NO_CORE;
  for (i= 0; i< nEsNumber; i++)
    {
    audioDecType = od->ESDescriptor[i]->DecConfigDescr.audioSpecificConfig.audioDecoderType.value;
    switch (audioDecType)
      {
      case 0:
        if (( layNumChan[i] = od->ESDescriptor[i]->DecConfigDescr.audioSpecificConfig.channelConfiguration.value) == 2 && (nFirstStereo < 0))
          nFirstStereo = i;
        tfType=od->ESDescriptor[i]->DecConfigDescr.audioSpecificConfig.specConf.TFSpecificConfig.TFCodingType.value;
        switch (tfType) {
        case 0 :
          nAacLay++;
          aac=1;
          break;
        case 1 :
          nAacLay++;
          aac=1;
          break;
        case 2 :
          nLowRateChan++;
          *coreCoderIndex=NTT_TVQ;          
          break;
        case 3 :
          CommonExit(-1,"tfDecoderType not implemented");
          break;
        default:
          CommonExit(-1,"tfDecoderType not implemented");
          break;
        }          
        break;
      default:
        CommonExit(-1,"audioDecoderType not implemented");
        break;
      }
    }
  *lastAacLay = nLowRateChan ? nAacLay : nAacLay-1;
  if (aac==0) *lastAacLay=-1;
  *lowRateChannelPresent = nLowRateChan;
  *firstStLay = nFirstStereo;

}

static int debugDiff=0;

void aacScaleableFlexMuxDecode ( BsBitStream*      fixed_stream,
                          BsBitStream*      gc_WRstream[],
                          WINDOW_TYPE       block_type[MAX_TIME_CHANNELS],
                          int*              flexMuxBits,
                          double*           spectral_line_vector[MAX_TF_LAYER][MAX_TIME_CHANNELS],
                          int               block_size_samples,
                          int               output_select,
                          Info**            sfbInfo,
                          int               numChannels,
                          long int          samplRateFw,
                          int               lopLong,
                          int               lopShort,
                          float             normBw,
                          Window_shape*     windowShape,
                          QC_MOD_SELECT     qc_select,
                          int               bsacDecBr,
                          HANDLE_RESILIENCE hResilience,
                          HANDLE_BUFFER     hVm,
                          HANDLE_BUFFER     hHcrSpecData,
                          HANDLE_HCR        hHcrInfo ,
                          FRAME_DATA* fd,
                          HANDLE_EP_INFO    hEPInfo )
{
  BsBitStream* layer_stream ;
  unsigned int x;
  static int lowRateChannelPresent;
  static enum CORE_CODEC  coreCodecIdx;
  static int nrGranules = 3;
  static int lastAacLay = 0;  
  static int firstAacLay = 0;  
  static int layNumChan[MAX_TF_LAYER];
  static int firstStLay;
  static int lastMonoLay;
  unsigned long ultmp,codedBlockType;
  int diffControl[MAX_TF_LAYER][MAX_TIME_CHANNELS][ 60 ]={{{0x0}}};
  int aacLayer,layer;
  int ch,commonWindow,calcMonoLay;
  double *low_spec;
  int diffControlBands[MAX_TF_LAYER];
  int i,tmp;
  int msMask[8][60]={{0x0}};
  int msMaskPres;
  int shortFssWidth;
  TNS_frame_info tns_info[MAX_TIME_CHANNELS];
  byte max_sfb[Winds];
  static byte sfbCbMap[MAX_TF_LAYER][MAX_TIME_CHANNELS][MAXBANDS] = {{{0x0}}};
  int  groupInfo;
  int  tns_data_present[2];
  int  gain_control_data_present[2];
  int   used_bits[4][2];
  int decodedBits,coreDecBits;
  ntt_INDEX           index;

  unsigned long totalLength;
  unsigned long AUlength[8];
  
  /* init */
  decodedBits = 0;

  /*********************/
  for ( x = 0; x < fd->od->streamCount.value; x++ ){
    unsigned int AUindex;/* AUindex = scaleable layer Number , since we have not stream map table*/
    totalLength = 0;
    getAccessUnit ( fixed_stream, fd->layer[x].bitBuf, &AUindex , &totalLength);
    if (x != AUindex) CommonExit(-1,"\nError in FlexMuxDecode");
    AUlength[x] = totalLength;
  }
  *flexMuxBits = BsCurrentBit(fixed_stream);
  layer=0;
#if 0 /* debug , should be read from frameData->od  */
  commonWindow=0; 
  firstAacLay=0;
  firstStLay=-1;
  lastAacLay=0;
  layNumChan[firstAacLay]  =1;
  layNumChan[lastAacLay] = 1;
  coreCodecIdx = NO_CORE;
#endif

  commonWindow=0; 
  getModeFromOD(fd->od,&lowRateChannelPresent ,layNumChan ,&lastAacLay ,&firstStLay,&coreCodecIdx);

  
  if (output_select>lastAacLay) output_select=lastAacLay;
  if (output_select<0) output_select=0; /* YB 980508 */
  lastMonoLay=lastAacLay;/* debug */
  if (output_select > lastMonoLay ){
    calcMonoLay=lastMonoLay ;
  } else {
    calcMonoLay=output_select ;      
  }

  /* YB 980504 */
  /* combine all AU data into one bitstream */
  if(qc_select == AAC_SCA_BSAC) {
	int lay=0;
	int base_layer = 0;
    if (lowRateChannelPresent) lay++;
	base_layer = lay++;
	for(; lay <= lastAacLay; lay++) {
      layer_stream= BsOpenBufferRead(fd->layer[lay].bitBuf);
	  BsGetBufferAppend(layer_stream, fd->layer[base_layer].bitBuf, 1,AUlength[lay]*8);
	  AUlength[base_layer] += AUlength[lay];
	  BsClose(layer_stream);
	}
	lastAacLay = base_layer;
  }

  /* open the first layer bitbuffer  to read :
     can  be a AAC or TwinVq bitbuffer as core */
  layer_stream= BsOpenBufferRead(fd->layer[layer].bitBuf);

  /* ics_info()*/
  BsGetBit( layer_stream, &ultmp,1); /* reserved bit */
  decodedBits += 1;
  
  BsGetBit( layer_stream, &ultmp,2); /* window_sequence */
  codedBlockType = (int)ultmp;
  decodedBits += 2;
  switch (   codedBlockType )
    {
    case 0: 
      block_type[MONO_CHAN] =  ONLY_LONG_WINDOW;
      *windowShape = WS_DOLBY;
      break;
    case 1: 
      block_type[MONO_CHAN] =  LONG_SHORT_WINDOW;
      *windowShape = WS_FHG;
      break;
    case 2: 
      block_type[MONO_CHAN] =  ONLY_SHORT_WINDOW;
      *windowShape = WS_FHG;
      break;
    case 3: 
      block_type[MONO_CHAN] =  SHORT_LONG_WINDOW;
      *windowShape = WS_DOLBY;
      break;
    default: 
      CommonExit(-1,"wrong blocktype %d",   codedBlockType);
    }
  
  BsGetBit( layer_stream, &ultmp,1);
  *windowShape = (Window_shape)ultmp; /* window shape */
  decodedBits += 1;
  

  /* decode core layer if present */
  if (lowRateChannelPresent)
    {
      coreDecBits = decodedBits;
      firstAacLay = 1; 

      switch (coreCodecIdx)
        {
        case NTT_TVQ:
          coreDecBits += ntt_BitUnPack ( layer_stream, 
                                         BsBufferNumBit(fd->layer[0].bitBuf)-4,
                                         block_type[MONO_CHAN], 
                                         &index, 
                                         hResilience,
                                         hVm,
                                         hEPInfo );
          ntt_vq_decoder(&index, spectral_line_vector[0]);
          totalLength =   BsBufferNumBit(fd->layer[0].bitBuf);
          BsGetSkip(layer_stream,(totalLength-coreDecBits ));
          BsClose ( layer_stream );
        
          layer++;
          layer_stream= BsOpenBufferRead(fd->layer[layer].bitBuf); 
          break;
      
        default:
          CommonExit(-1,"\n wrong core coder");
          break;
        }
    
      decodedBits = 0;
    }
  if (lastAacLay>=0){

    if (block_type[MONO_CHAN]== ONLY_SHORT_WINDOW ){
      BsGetBit( layer_stream, &ultmp,4);        /* max_sfb */
      decodedBits += 4;
      max_sfb[firstAacLay]=ultmp;
      BsGetBit( layer_stream, &ultmp,7);        /* scale_factor_grouping */
      groupInfo = ultmp;
      decodedBits += 7;
      sfbInfo[block_type[MONO_CHAN]]->num_groups = decode_grouping( ultmp, sfbInfo[block_type[MONO_CHAN]]->group_len );
    }else {
      BsGetBit( layer_stream, &ultmp,6);          /* max_sfb */
      decodedBits += 6;
      max_sfb[firstAacLay]=ultmp;
      BsGetBit( layer_stream, &ultmp,1);         /* prediction */
      decodedBits += 1;
      if (ultmp!=0){
        CommonExit(-1,"\n prediction currently not supproted in scaleable mode");
      }
    }
    /* end of ics_info()*/
  
    /* rest of aac_scaleable_header */
  
    /* [predictor data should be parsed here] */
  
    if( layNumChan[firstAacLay]==2 ){
      int g,sfb,win;
      int gwin;
      BsGetBit( layer_stream, &ultmp,2);     /* ms_mask_present ? */
      decodedBits += 2;
      msMaskPres = ultmp;
      if (msMaskPres==1&&qc_select != AAC_SCA_BSAC){          
        win=0;
        for (g=0;g<sfbInfo[block_type[MONO_CHAN]]->num_groups;g++){
          for (sfb=0;sfb<max_sfb[firstAacLay];sfb++){
            BsGetBit( layer_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( layer_stream, &ultmp,1);           /* tns */
      tns_data_present[ch] = ultmp;
      decodedBits += 1;
      if( ultmp ) {
        get_tns_vm( layer_stream, sfbInfo[block_type[MONO_CHAN]], &tns_info[ch] ,&decodedBits);
      } else {
        clr_tns( sfbInfo[block_type[MONO_CHAN]], &tns_info[ch] );
      }
      BsGetBit( layer_stream, &ultmp,1);           /* sony gain control not used */
      gain_control_data_present[ch] = ultmp;
      decodedBits += 1;
      if (ultmp!=0){
        CommonExit(-1,"\n sony gaincontrol not yet 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( layer_stream,&ultmp, 1 );  /* short FSSwitch  1st aacLayer  */
            decodedBits += 1;
            diffControl[firstAacLay][ch][g]= ultmp;
            if (ch==0){
              diffControlBands[firstAacLay] +=1;
            }
          }
        } else {
          decodeDiffCtrl(layer_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;
          }
        }
      }
    }     
  

    /* decode 1st AAC Layer */
    used_bits[firstAacLay][0] = decodedBits;
    aacLayer=firstAacLay;
    if(qc_select == AAC_SCALEABLE) {
      tmp = aac_decode_frame( layer_stream,
                              gc_WRstream,
                              spectral_line_vector[aacLayer], 
                              &(block_type[MONO_CHAN]), 
                              windowShape,
                              SCALEABLE,
                              &max_sfb[aacLayer],
                              layNumChan[aacLayer],
                              commonWindow,
                              sfbInfo, 
                              sfbCbMap[aacLayer],
                              hResilience,
                              hVm,
                              hHcrSpecData,
                              hHcrInfo,
                              hEPInfo );
    } else if(qc_select == AAC_SCA_BSAC) {
      if( layNumChan[firstAacLay]!=2 ) msMaskPres = 0;
      tmp = sam_decode_core_frame(layer_stream, bsacDecBr,
                               spectral_line_vector[aacLayer], 
                               block_type[MONO_CHAN], 
                               max_sfb[aacLayer],
                               groupInfo,
                               msMaskPres,
                               msMask,
                               decodedBits,
                               coreDecBits,
                               AUlength[layer],
                               layNumChan[aacLayer]);
    }
    used_bits[aacLayer][1] = tmp;
    decodedBits +=tmp;
    totalLength = BsBufferNumBit(fd->layer[aacLayer].bitBuf);
    if (  (totalLength-decodedBits) > 8){
      CommonWarning("%d bits more read than decoded",(totalLength-decodedBits));
    }
    BsGetSkip(layer_stream,(totalLength-decodedBits)); 
    BsClose ( layer_stream );
    /* end of 1st aac layer */
    layer++;
  }

  /* read and decode aac_scaleable_extension_stream(s) */
  if(qc_select != AAC_SCA_BSAC) {
  for ( aacLayer=firstAacLay+1;aacLayer<=lastAacLay;aacLayer++){
    layer_stream= BsOpenBufferRead(fd->layer[layer].bitBuf); 
    decodedBits =0;
    if (block_type[MONO_CHAN]== ONLY_SHORT_WINDOW){
      BsGetBit( layer_stream, &ultmp,4);          /* max_sfb_med */
      decodedBits += 4;
      max_sfb[aacLayer]=ultmp;
    } else {
        BsGetBit( layer_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( layer_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( layer_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( layer_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( layer_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(layer_stream,diffControl[aacLayer][ch],decodedBits,sfbInfo[block_type[MONO_CHAN]]->longFssGroups);   long FSS*/ 
            }
          }        
        }
      }
      used_bits[aacLayer][0] = decodedBits;
    
      ResetReadBitCnt ( hVm );  
      tmp = aac_decode_frame( layer_stream,
                              gc_WRstream,
                              spectral_line_vector[aacLayer], 
                              &(block_type[MONO_CHAN]), 
                              windowShape,
                              SCALEABLE,
                              &max_sfb[aacLayer],
                              layNumChan[aacLayer],
                              commonWindow,
                              sfbInfo, 
                              sfbCbMap[aacLayer],
                              hResilience,
                              hVm,
                              hHcrSpecData,
                              hHcrInfo,
                              hEPInfo );
      used_bits[aacLayer][1] = tmp;
      decodedBits +=tmp;
      totalLength =   BsBufferNumBit(fd->layer[aacLayer].bitBuf);
      if (  (totalLength-decodedBits) > 8){
        CommonWarning("%d bits more than decoded",(totalLength-decodedBits));
      }
      BsGetSkip(layer_stream,(totalLength-decodedBits));
      BsClose ( layer_stream );

  }
  }


  if ( (coreCodecIdx!=NO_CORE) && (output_select > 0) && (fd->tnsBevCore==0)  ) {
    /* tns encoder */
    int k, j;
    Info *info =sfbInfo[block_type[MONO_CHAN]];
    info->islong = (block_type[MONO_CHAN] != ONLY_SHORT_WINDOW);
    ch = 0;
    for (i=j=0; i<tns_info[ch].n_subblocks; i++) {
      float tmp_spec[1024];
      for( k=0; k < info->bins_per_sbk[i]; k++ ) {
        tmp_spec[k] = spectral_line_vector[0][ch][j+k];
      }
      tns_encode_subblock( tmp_spec,
                           max_sfb[1],   /* 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];
    }
  }
  
  /* compute PNS and restore spectrum */
  {
    int sfb, maxSfb, lineIdx=0;
    int prevSfbCb,sfbCb, sfbWidth;
    double energy, zero = 0.0;
 
    if (sfbInfo[block_type[MONO_CHAN]]->islong) {
 
      for (aacLayer=firstAacLay+1; aacLayer <= calcMonoLay; aacLayer++) {       
        /* for the first layer do nothing */
        maxSfb = (max_sfb[aacLayer-1]<max_sfb[aacLayer])?max_sfb[aacLayer-1]:max_sfb[aacLayer];

        for (sfb=0; sfb<maxSfb; sfb++) {
          prevSfbCb = (int)sfbCbMap[aacLayer-1][MONO_CHAN][sfb];
          sfbCb     = (int)sfbCbMap[aacLayer][MONO_CHAN][sfb];
          if (sfb==0) {
            sfbWidth = sfbInfo[block_type[MONO_CHAN]]->bk_sfb_top[sfb];
          }
          else {
            sfbWidth = sfbInfo[block_type[MONO_CHAN]]->bk_sfb_top[sfb]-sfbInfo[block_type[MONO_CHAN]]->bk_sfb_top[sfb-1];
          }

          if (prevSfbCb == NOISE_HCB) {
            energy = scalprod(&spectral_line_vector[aacLayer][MONO_CHAN][lineIdx], &spectral_line_vector[aacLayer][MONO_CHAN][lineIdx], 1, 1, sfbWidth);
            /* if sfb of enhancement layer has MDCT lines, set sfb of previous layer to 0 */
            if (energy > 0) {
              vcopy(&zero, &spectral_line_vector[aacLayer-1][MONO_CHAN][lineIdx], 0 ,1 ,sfbWidth);
            }
            else {
              sfbCbMap[aacLayer][MONO_CHAN][sfb] = sfbCbMap[aacLayer-1][MONO_CHAN][sfb];
              vcopy(&spectral_line_vector[aacLayer-1][MONO_CHAN][lineIdx],&spectral_line_vector[aacLayer][MONO_CHAN][lineIdx], 1, 1, sfbWidth);
              vcopy(&zero,&spectral_line_vector[aacLayer-1][MONO_CHAN][lineIdx], 0, 1, sfbWidth);  
            }
            if (sfbCb == NOISE_HCB) {
              CommonWarning("Two consecutive layers have PNS in same SFB !");
            } 
          }
          lineIdx += sfbWidth; 
        }
      }    
    }
  }

  /* combine all mono layers */
  for (aacLayer=firstAacLay+1 ; aacLayer <= calcMonoLay ; aacLayer++) {
    if (!debugDiff){
      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 );
    } else {
      vcopy (  spectral_line_vector[aacLayer][MONO_CHAN] , spectral_line_vector[firstAacLay][MONO_CHAN],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=spectral_line_vector[0][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 (output_select) {
    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 ); 
      }        
    }
  }

  /* Bandwidth control */
  if ((lopLong != 0) && (max_sfb[lastAacLay] != 0) && (output_select == 0)) {
    int maxline;
      
    if (normBw == 0.0F) {
      maxline = sfbInfo[block_type[MONO_CHAN]]->sbk_sfb_top[0][max_sfb[lastAacLay]-1];
    }
    else {
      maxline = (int)((float)(sfbInfo[block_type[MONO_CHAN]]->bins_per_bk /sfbInfo[block_type[MONO_CHAN]]->nsbk)*normBw + 0.5);
    } 
    for (ch=0; ch<layNumChan[lastAacLay]; ch++) {
      dec_lowpass(spectral_line_vector[0][ch], lopLong, lopShort, maxline,
                  sfbInfo[block_type[MONO_CHAN]]->bins_per_bk, block_type[MONO_CHAN],
                  sfbInfo[block_type[MONO_CHAN]]->nsbk);
    }
  }

  /* tns decoder */
  if ( ! ( (output_select == 0) && (lowRateChannelPresent) && (fd->tnsBevCore==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[1024];
        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[output_select],  
                             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];
      }
    }
  }
#ifdef DEBUGPLOT_FHG 
  plotSend("c", "mdctCore",  MTV_DOUBLE,1024, low_spec , NULL);

  plotSend("l", "mdctSpecL",  MTV_DOUBLE_SQA,1024, spectral_line_vector[0][0] , NULL);
/*   plotSend("r", "mdctSpecR" , MTV_DOUBLE,1024, spectral_line_vector[firstAacLay][1] , NULL); */
#endif    
 

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