/**********************************************************************
MPEG-4 Audio VM

This software module was originally developed by
  Y.B. Thomas Kim and S.H. Park (Samsung AIT)
and edited by
  Y.B. Thomas Kim (Samsung AIT) on 1997-11-06

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 <stdio.h>
#include <stdlib.h>
#include "common.h"
#include "block.h"
#include "bitstream.h"
#include "tf_main.h"
#include "sam_dec.h"
#include "sony_local.h"

#define ID_SCE  0x00
#define ID_CPE  0x01
#define MAX_PRED_SFB    40


static int	num_of_chan;
static int	sampling_frequency_index;
static int	sampling_frequency;
static int	frame_length_flag;
static int  block_size_samples;
static int  frameLength;
static int  encodedLayer;
static float    spectrums[2][1024];
static int              samples[2][1024];
int sam_profile;
static int  fs_index[16]={
	96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
	16000, 12000, 11025,  8000,     0,     0,     0,     0
};


static void sam_get_tns( int windowSequence, sam_TNS_frame_info *tns_frame_info );
#if 0
static void tns2samtns(TNS_frame_info *tns_frame_info, sam_TNS_frame_info *sam_tns_frame_info );
#endif
static void sam_ics_info(WINDOW_TYPE*  windowSequence,
                         Window_shape* windowShape,
                         int*          maxSfb,
                         int*          groupInfo,
                         int*          predict_data);
#ifdef  SRS
static int sam_get_gcBuf(int window_sequence, BsBitStream *gc_streamCh);
#endif /*SRS*/
int     sam_decode_frame(
                         BsBitStream *fixed_stream,
                         BsBitStream *gc_stream[MAX_TIME_CHANNELS],
                         int     target_br,
                         double  **coef,
                         int     *block_type,
                         Window_shape *window_Shape)
{
  int           i, ch, nch;
  int           usedBits;
  int           stereo_mode;
  int           id_syn_ele;
  int           element_instance_tag;
  int           nok_lt_data_present;
  int           common_window;
  WINDOW_TYPE   windowSequence[2];
  Window_shape  windowShape[2];
  int           maxSfb[2];
  int           groupInfo[2][7];
  int           predict_data[2][60];
  int           gain_control_data_present[2];
  int           tns_data_present[2];
  int           ms_mask[MAX_SCFAC_BANDS];
  int           is_intensity;
  int           is_info[MAX_SCFAC_BANDS];
  int           scalefactors[2][MAX_SCFAC_BANDS];
  int           pns_sfb_start;
  int           pns_sfb_flag[2][MAX_SCFAC_BANDS];
  int           pns_sfb_mode[MAX_SCFAC_BANDS];
  int           core_used_bits = 0;
  int           fsize_len;
  sam_TNS_frame_info tns[2];
  static int	frameStart=1;


  sam_setBsacdec2BitBuffer(fixed_stream);

  /********* READ BITSTREAM **********/
  /* ***************************************************** */
  /* # the side information part for Mulit-channel               */ 
  /* ***************************************************** */

  if(frameStart) {
	num_of_chan = sam_GetBits(3);
	sampling_frequency_index = sam_GetBits(4);

	sampling_frequency = fs_index[sampling_frequency_index];
	frame_length_flag = sam_GetBits(1);
	if(frame_length_flag == 0)
		block_size_samples = 1024;
	else
		block_size_samples = 960;
	frameStart = 0;
  }

  nch = num_of_chan;


  /* initialize variables */
  for(i = 0; i < 50; i++)
    predict_data[0][i] = predict_data[1][i] = 0;

  for(i = 0; i < MAX_SCFAC_BANDS; i++) {
    ms_mask[i] = 0;
    is_info[i] = 0;
	pns_sfb_flag[0][i] = 0;
	pns_sfb_flag[1][i] = 0;
	pns_sfb_mode[i] = 0;
  }

  sam_profile = 0;	/* set profile  Main_Profile */
  ms_mask[0] = 0;
  is_intensity = 0;
  stereo_mode = 0;
  common_window = 1;

  /* ***************************************************** */
  /*                    ics_info()                         */
  /* ***************************************************** */
  sam_ics_info ( &windowSequence[0], 
                 &windowShape[0], 
                 &maxSfb[0],
                 groupInfo[0], 
                 predict_data[0] );

  if(nch == 2 && common_window) {
    windowSequence[1] = windowSequence[0];
    maxSfb[1] = maxSfb[0];
    for(i = 0; i < 7; i++)
      groupInfo[1][i] = groupInfo[0][i];
    for(i = 0; i < 50; i++)
      predict_data[1][i] = predict_data[0][i];
  }

  /* ***************************************************** */
  /* #                  stereo mode                                                        * */
  /* ***************************************************** */
  if(nch == 2) {
    stereo_mode = sam_GetBits(2);
    if(stereo_mode == 1) {
      ms_mask[0] = 1;
    } else if(stereo_mode == 2) {
      ms_mask[0] = 2;
     for(i = 0; i < MAX_SCFAC_BANDS; i++)
        ms_mask[i+1] = 1;
    } else if(stereo_mode == 3) {
      ms_mask[0] = 1;
      is_intensity = 1;
    }
  }

  /* ***************************************************** */
  /* #                  the other side info                                        * */
  /* ***************************************************** */
  for(ch = 0; ch < nch; ch++) {
    tns_data_present[ch] = sam_GetBits(1);
    if(tns_data_present[ch]) {
      sam_get_tns(windowSequence[ch], &tns[ch]);
    }

    gain_control_data_present[ch] = sam_GetBits(1); 
    if(gain_control_data_present[ch]) {
#ifdef  SRS
      sam_get_gcBuf(windowSequence[ch], gc_stream[ch]);
	  sam_profile = 2; /* SSR_Profile */
#else
      CommonExit(1, "Gain control not implemented\n");
#endif
    }
  }

  fsize_len = 10;
  if(nch == 2) fsize_len = 11;
  frameLength = sam_GetBits(fsize_len) * 8;
  if(frameLength == 0)
	CommonExit(1, "Zero-length frame!\n");
  encodedLayer = sam_GetBits(6);

  /* ***************************************************** */
  /* #                  BSAC D E C O D I N G                               * */
  /* ***************************************************** */
  sam_decode_bsac_data(target_br,
					   frameLength,
					   encodedLayer,
                       core_used_bits,
                       stereo_mode,
                       windowSequence,
                       scalefactors,
                       groupInfo,
                       samples,
                       maxSfb,
                       ms_mask,
                       is_info,
					   &pns_sfb_start,
					   pns_sfb_flag,
					   pns_sfb_mode,
					   block_size_samples,
                       nch);

  /* ***************************************************** */
  /* #                  dequantization                   # */
  /* ***************************************************** */
  for(ch = 0; ch < nch; ch++) {
    sam_dequantization(target_br,
                       windowSequence[ch],
                       scalefactors[ch],
                       groupInfo[ch],
                       samples[ch],
                       maxSfb[ch],
                       is_info,
                       spectrums[ch],
                       ch);
  }

  /* ***************************************************** */
  /* #                  M/S stereo                       # */
  /* ***************************************************** */
  if(ms_mask[0])
    sam_ms_stereo(windowSequence[0], groupInfo[0], spectrums, ms_mask, maxSfb[0]);

  /* ***************************************************** */
  /* #                  PNS Spectrum                     # */
  /* ***************************************************** */
  sam_pns(windowSequence[0], groupInfo[0], maxSfb[0], pns_sfb_flag, pns_sfb_mode, spectrums, scalefactors, predict_data, nch);

  /* ***************************************************** */
  /* #                  Intensity/Prediction             # */
  /* ***************************************************** */
  for(ch = 0; ch < nch; ch++) {
    if(ch == 1 && is_intensity)
      sam_intensity(windowSequence[0], groupInfo[0], spectrums, scalefactors, is_info, ms_mask, predict_data, maxSfb[0]);

    sam_prediction(windowSequence[ch], predict_data[ch], spectrums[ch], ch);
  }

  for(ch = 0; ch < nch; ch++) {
    /* predictor reset */
    sam_predict_reset(windowSequence[ch], predict_data[ch], ch);

	sam_predict_pns_reset(windowSequence[ch], maxSfb[ch], pns_sfb_flag[ch], ch);

    /* ***************************************************** */
    /* #                        Temporal Noise Shaping                             * */
    /* ***************************************************** */
    if(tns_data_present[ch])
      sam_tns_data(windowSequence[ch], maxSfb[ch], spectrums[ch], &tns[ch]);

    for(i = 0; i < 1024; i++)
      coef[ch][i] = (double)spectrums[ch][i];
  }

  *block_type = windowSequence[0];
  *window_Shape = windowShape[0];

  usedBits = sam_getUsedBits();

  while(usedBits < frameLength) {
    int remain, read_bits;

    remain = frameLength - usedBits;
    read_bits = remain > 8 ? 8 : remain;
    i = sam_GetBits(read_bits);
    usedBits = sam_getUsedBits();
  }


  return usedBits;
}


int     sam_decode_core_frame ( BsBitStream* fixed_stream,
                               int          target_br,
                               double**     coef,
                               WINDOW_TYPE  block_type,
                               int          max_sfb,
                               int          gInfo,
                               int          stereo_mode,
                               int          msMask[8][60],
                               int          ubits,
                               int          core_used_bits,
                               int          AUlength,
                               int          n_chan_core_bsac)
{
  int             i, ch, nch;
  int             framelength;
  int             fsize_len;
  int             used_bits;
  int             usedBits;
  int             maxScaleFactor[2];
  int             common_window;
  int             predict_data[2][60];
  int             ms_mask[MAX_SCFAC_BANDS];
  int             is_intensity;
  int             is_info[MAX_SCFAC_BANDS];
  int             scalefactors[2][MAX_SCFAC_BANDS];
  WINDOW_TYPE     windowSequence[2];
  Window_shape    windowShape[2];
  int             maxSfb[2];
  int             groupInfo[2][7];
  int             pns_sfb_start=-1;
  int             pns_sfb_flag[2][MAX_SCFAC_BANDS];
  int             pns_sfb_mode[MAX_SCFAC_BANDS];
  static int      count = 0;


  sam_setBsacdec2BitBuffer(fixed_stream);

  /********* READ BITSTREAM **********/
  /* ***************************************************** */
  /* # the side information part for Mulit-channel               */ 
  /* ***************************************************** */

  nch = n_chan_core_bsac;
                

  /* initialize variables */
  windowSequence[0] = block_type;
  for (i = 0; i < 7; i++)
    groupInfo[0][6-i] =  (gInfo>>i) & 0x01;
  maxSfb[0] = max_sfb;

  for(i = 0; i < MAX_SCFAC_BANDS; i++) {
    ms_mask[i] = 0;
    is_info[i] = 0;
	pns_sfb_flag[0][i] = 0;
	pns_sfb_flag[1][i] = 0;
	pns_sfb_mode[i] = 0;
  }

  fsize_len = 10;
  if(nch == 2) fsize_len = 11;
  frameLength = sam_GetBits(fsize_len) * 8;
  if(frameLength == 0)
	CommonExit(1, "Zero-length frame!\n");
  encodedLayer = sam_GetBits(6);

  ms_mask[0] = 0;
  is_intensity = 0;
  common_window = 1;

  if(nch > 1 && common_window) {
    windowSequence[1] = windowSequence[0];
    maxSfb[1] = maxSfb[0];
    for(i = 0; i < 7; i++)
      groupInfo[1][i] = groupInfo[0][i];
  }

  used_bits = ubits + core_used_bits;
  /* ***************************************************** */
  /* #                  BSAC D E C O D I N G                               * */
  /* ***************************************************** */
  framelength = frameLength + core_used_bits;

  sam_decode_bsac_data(target_br,
                       framelength,
                       encodedLayer,
                       used_bits,
                       stereo_mode,
                       windowSequence,
                       scalefactors,
                       groupInfo,
                       samples,
                       maxSfb,
                       ms_mask,
                       is_info,
					   &pns_sfb_start,
					   pns_sfb_flag,
					   pns_sfb_mode,
                       block_size_samples,
                       nch);

  /* ***************************************************** */
  /* #                  dequantization                                     * */
  /* ***************************************************** */
  for(ch = 0; ch < nch; ch++)
    sam_dequantization(target_br,
                       windowSequence[ch],
                       scalefactors[ch],
                       groupInfo[ch],
                       samples[ch],
                       maxSfb[ch],
                       is_info,
                       spectrums[ch],
                       ch);

  /* ***************************************************** */
  /* #                  PNS Spectrum                     # */
  /* ***************************************************** */
  sam_pns(windowSequence[0], groupInfo[0], maxSfb[0], pns_sfb_flag, pns_sfb_mode, spectrums, scalefactors, predict_data, nch);

  for(ch = 0; ch < nch; ch++) {
    for(i = 0; i < 1024; i++)
      coef[ch][i] = (double)spectrums[ch][i];
  }

  if(stereo_mode == 1) {
	int w, b, sfb;
	int sb[8], eb[8];
	int num_win_group=1;

	if(windowSequence[0] == 2) {
		num_win_group = sam_get_region_info(groupInfo[0], sb, eb);
		for(w = 0; w < num_win_group; w++) {
			for(b = sb[w]; b < eb[w]; b++) for(sfb = 0; sfb < maxSfb[0]; sfb++)
				msMask[b][sfb] = ms_mask[(w*maxSfb[0])+sfb+1];
		}
	} else {
		for(b = 0; b < 8; b++) for(sfb = 0; sfb < maxSfb[0]; sfb++)
			msMask[b][sfb] = ms_mask[sfb+1];
	}
  }
  usedBits = sam_getUsedBits() + ubits+core_used_bits;

  while(usedBits < framelength) {
    int remain, read_bits;

    remain = framelength - usedBits;
    read_bits = remain > 8 ? 8 : remain;
    i = sam_GetBits(read_bits);
    usedBits = sam_getUsedBits() + ubits+core_used_bits; 
  }

  return usedBits - (ubits+core_used_bits);
}

int     sam_decode_core_bsac ( BsBitStream* fixed_stream,
                               int          target_br,
                               double**     coef,
                               WINDOW_TYPE  block_type,
                               Window_shape window_Shape,
                               int          max_sfb,
                               int          gInfo,
                               int          core_used_bits,
                               int          n_chan_core_bsac)
{
#ifdef	KKK
  int             i, ch, nch;
  int             frameLength;
  int             usedBits;
  int             stereo_mode;
  int             maxScaleFactor[2];
  int             common_window;
  int             ms_mask[MAX_SCFAC_BANDS];
  int             is_intensity;
  int             is_info[MAX_SCFAC_BANDS];
  int             scalefactors[2][MAX_SCFAC_BANDS];
  WINDOW_TYPE     windowSequence[2];
  Window_shape    windowShape[2];
  int             maxSfb[2];
  int             groupInfo[2][7];
  static int      count = 0;


  sam_setBsacdec2BitBuffer(fixed_stream);

  /********* READ BITSTREAM **********/
  /* ***************************************************** */
  /* # the side information part for Mulit-channel               */ 
  /* ***************************************************** */

  nch = n_chan_core_bsac;
                

  /* initialize variables */
  windowSequence[0] = block_type;
  windowShape[0] = window_Shape;
  for (i = 0; i < 7; i++)
    groupInfo[0][6-i] =  (gInfo>>i) & 0x01;
  maxSfb[0] = max_sfb;

  for(i = 0; i < MAX_SCFAC_BANDS; i++) {
    ms_mask[i] = 0;
    is_info[i] = 0;
  }

  ms_mask[0] = 0;
  is_intensity = 0;
  stereo_mode = 0;
  common_window = 1;

  /* ***************************************************** */
  /*   core_bsac_channel_stream()                               */
  /* ***************************************************** */

  for(ch = 0; ch < nch; ch++) 
    maxScaleFactor[ch] = sam_GetBits(8);

  if(nch > 1 && common_window) {
    windowSequence[1] = windowSequence[0];
    maxSfb[1] = maxSfb[0];
    for(i = 0; i < 7; i++)
      groupInfo[1][i] = groupInfo[0][i];
  }

  /* ***************************************************** */
  /* #                  stereo mode                                                        * */
  /* ***************************************************** */
  if(nch > 2) {
    stereo_mode = sam_GetBits(2);
    if(stereo_mode == 1) {
      ms_mask[0] = 2;
      for(i = 0; i < MAX_SCFAC_BANDS; i++)
        ms_mask[i+1] = 1;
    } else if(stereo_mode == 2) {
      ms_mask[0] = 1;
    } else if(stereo_mode == 3) {
      ms_mask[0] = 1;
      is_intensity = 1;
    }
  }

  core_used_bits += (11 + 47);
  /* ***************************************************** */
  /* #                  BSAC D E C O D I N G                               * */
  /* ***************************************************** */
  frameLength = sam_decode_bsac_data(target_br,
                                     core_used_bits,
                                     stereo_mode,
                                     windowSequence,
                                     scalefactors,
                                     groupInfo,
                                     samples,
                                     maxSfb,
                                     maxScaleFactor,
                                     ms_mask,
                                     is_info,
									 sampling_frequency,
									 frame_length_flag,
                                     nch);

  /* ***************************************************** */
  /* #                  dequantization                                     * */
  /* ***************************************************** */
  for(ch = 0; ch < nch; ch++) {
    sam_dequantization(target_br,
                       windowSequence[ch],
                       scalefactors[ch],
                       groupInfo[ch],
                       samples[ch],
                       maxSfb[ch],
                       is_info,
                       spectrums[ch],
                       ch);

    for(i = 0; i < 960; i++)
      coef[ch][i] = (double)spectrums[ch][i];
  }

  usedBits = sam_getUsedBits(); 

  while(usedBits < frameLength) {
    int remain, read_bits;

    remain = frameLength - usedBits;
    read_bits = remain > 8 ? 8 : remain;
    i = sam_GetBits(read_bits);
    usedBits = sam_getUsedBits(); 
  }

  count++;

  return usedBits;
#else /*KKK*/
  return ( 0 );
#endif /*KKK*/
}

/* ***************************************************** */
/* #                    ics_info()                             * */
/* ***************************************************** */
static void sam_ics_info ( WINDOW_TYPE*  windowSequence,
                           Window_shape* windowShape,
                           int*          maxSfb,
                           int*          groupInfo,
                           int*          predict_data )
{
  int      i, j, ics_reserved;

  /* ics_reserved_bit  */
  ics_reserved = sam_GetBits(1); 

  /*  window sequence */
  *windowSequence = (WINDOW_TYPE) sam_GetBits(2); 

  /*  window shape */
  *windowShape = (Window_shape) sam_GetBits(1); 

  if (*windowSequence == EIGHT_SHORT_SEQUENCE)
    {
      *maxSfb = sam_GetBits(4);

      for (i = 0; i < 7; i++)
        groupInfo[i] =  sam_GetBits(1); 
    }
  else 
    {
      *maxSfb = sam_GetBits(6);

      predict_data[0] = sam_GetBits(1);
      if(predict_data[0]) {
        predict_data[1] = sam_GetBits(1);       /* predictor reset */
        if(predict_data[1]) {
          for(i = 1; i < 6; i++)
            predict_data[1+i] = sam_GetBits(1);
        }
        j = ((*maxSfb < MAX_PRED_SFB) ? *maxSfb : MAX_PRED_SFB) + 1;
        for(i = 1; i < j; i++)
          predict_data[6+i] = sam_GetBits(1);
        for(; i < MAX_PRED_SFB+1; i++)
          predict_data[6+i] = 1;
      }
    }
}

static void sam_get_tns( int windowSequence, sam_TNS_frame_info *tns_frame_info )
{
  int                       f, t, top, res, res2, compress;
  int                       short_flag, s, k;
  int                       top_bands;
  short                     *sp, tmp, s_mask, n_mask;
  sam_TNSfilt                   *tns_filt;
  sam_TNSinfo                   *tns_info;
  static unsigned short     sgn_mask[] = { 
    0x2, 0x4, 0x8     };
  static unsigned short     neg_mask[] = { 
    0xfffc, 0xfff8, 0xfff0     };


  if(windowSequence == 2) {
    short_flag = 1;
    tns_frame_info->n_subblocks = 8;
    top_bands = 14;
  } else {
    short_flag = 0;
    tns_frame_info->n_subblocks = 1;
    top_bands = 49;
  }


  for (s=0; s<tns_frame_info->n_subblocks; s++) {
    tns_info = &tns_frame_info->info[s];

    tns_info->n_filt = sam_GetBits( short_flag ? 1 : 2 );
    if (!(tns_info->n_filt))
      continue;
                
    tns_info -> coef_res = res = sam_GetBits( 1 ) + 3;
    top = top_bands;
    tns_filt = &tns_info->filt[ 0 ];
    for (f=tns_info->n_filt; f>0; f--)  {
      tns_filt->stop_band = top;
      tns_filt->length = sam_GetBits( short_flag ? 4 : 6 );
      top = tns_filt->start_band = top - tns_filt->length;
      tns_filt->order = sam_GetBits( short_flag ? 3 : 5 );

      if (tns_filt->order)  {
        tns_filt->direction = sam_GetBits( 1 );
        compress = sam_GetBits( 1 );
        tns_filt->coef_compress = compress;

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

        sp = tns_filt -> coef;
        k = 0;
        for (t=tns_filt->order; t>0; t--)  {
          tmp = sam_GetBits( res2 );
          tns_filt->coef1[k++] = tmp;
          *sp++ = (tmp & s_mask) ? (tmp | n_mask) : tmp;
        }
      }
      tns_filt++;
    }
  }   /* subblock loop */
}

#if 0
static void tns2samtns(TNS_frame_info *tns_frame_info, sam_TNS_frame_info *sam_tns_frame_info )
{
  int                       f, t, res, res2, compress;
  int                       s, k;
  short                     *sp, tmp, s_mask, n_mask;
  TNSfilt                   *tns_filt;
  sam_TNSfilt               *sam_tns_filt;
  TNSinfo                   *tns_info;
  sam_TNSinfo               *sam_tns_info;
  static unsigned short     sgn_mask[] = { 
    0x2, 0x4, 0x8     };
  static unsigned short     neg_mask[] = { 
    0xfffc, 0xfff8, 0xfff0     };


  for (s=0; s<tns_frame_info->n_subblocks; s++) {
    tns_info = &tns_frame_info->info[s];
    sam_tns_info = &sam_tns_frame_info->info[s];

    sam_tns_info->n_filt = tns_info->n_filt;
    if (!(tns_info->n_filt))
      continue;
                
    sam_tns_info -> coef_res = tns_info -> coef_res;
    tns_filt = &tns_info->filt[ 0 ];
    sam_tns_filt = &sam_tns_info->filt[ 0 ];
    for (f=tns_info->n_filt; f>0; f--)  {
      sam_tns_filt->stop_band = tns_filt->stop_band;
      sam_tns_filt->start_band = tns_filt->start_band;
      sam_tns_filt->order = tns_filt->order;

      if (tns_filt->order)  {
        sam_tns_filt->direction = tns_filt->direction;
        compress = tns_filt->coef_compress;
        sam_tns_filt->coef_compress = compress;

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

        sp = tns_filt -> coef;
        k = 0;
        for (t=tns_filt->order; t>0; t--)  {
          sam_tns_filt->coef1[k++] = tns_filt->coef[k++];
          *sp++ = (tmp & s_mask) ? (tmp | n_mask) : tmp;
        }
      }
      tns_filt++;
      sam_tns_filt++;
    }
  }   /* subblock loop */
}
#endif

#ifdef  SRS
static int sam_get_gcBuf(int window_sequence, BsBitStream *gc_streamCh)
{
  int           wd;
  unsigned int  ad;
  unsigned int  bd;
  unsigned long max_band, natks, ltmp;
  int           loc;

  loc = gc_streamCh->currentBit;
  max_band = sam_GetBits(NBANDSBITS);
  BsPutBit(gc_streamCh, max_band, NBANDSBITS);/*   0 < max_band <= 3 */

  switch (window_sequence) {
  case ONLY_LONG_SEQUENCE:
    for (bd = 1; bd <= max_band; bd++) {
      for (wd = 0; wd < 1; wd++) {
        natks = sam_GetBits(NATKSBITS);
        BsPutBit(gc_streamCh, natks, NATKSBITS);
        for (ad = 0; ad < natks; ad++) {
          ltmp = sam_GetBits(IDGAINBITS);
          BsPutBit(gc_streamCh, ltmp, IDGAINBITS);
          ltmp = sam_GetBits(ATKLOCBITS);
          BsPutBit(gc_streamCh, ltmp, ATKLOCBITS);
        }
      }
    }
    break;
  case LONG_START_SEQUENCE:
    for (bd = 1; bd <= max_band; bd++) {
      for (wd = 0; wd < 2; wd++) {
        natks = sam_GetBits(NATKSBITS);
        BsPutBit(gc_streamCh, natks, NATKSBITS);
        for (ad = 0; ad < natks; ad++) {
          ltmp = sam_GetBits(IDGAINBITS);
          BsPutBit(gc_streamCh, ltmp, IDGAINBITS);
          if (wd == 0) {
            ltmp = sam_GetBits(ATKLOCBITS_START_A);
            BsPutBit(gc_streamCh, ltmp, ATKLOCBITS_START_A);
          }
          else {
            ltmp = sam_GetBits(ATKLOCBITS_START_B);
            BsPutBit(gc_streamCh, ltmp, ATKLOCBITS_START_B);
          }
        }
      }
    }
    break;
  case EIGHT_SHORT_SEQUENCE:
    for (bd = 1; bd <= max_band; bd++) {
      for (wd = 0; wd < 8; wd++) {
        natks = sam_GetBits(NATKSBITS);
        BsPutBit(gc_streamCh, natks, NATKSBITS);
        for (ad = 0; ad < natks; ad++) {
          ltmp = sam_GetBits(IDGAINBITS);
          BsPutBit(gc_streamCh, ltmp, IDGAINBITS);
          ltmp = sam_GetBits(ATKLOCBITS_SHORT);
          BsPutBit(gc_streamCh, ltmp, ATKLOCBITS_SHORT);
        }
      }
    }
    break;
  case LONG_STOP_SEQUENCE:
    for (bd = 1; bd <= max_band; bd++) {
      for (wd = 0; wd < 2; wd++) {
        natks = sam_GetBits(NATKSBITS);
        BsPutBit(gc_streamCh, natks, NATKSBITS);
        for (ad = 0; ad < natks; ad++) {
          ltmp = sam_GetBits(IDGAINBITS);
          BsPutBit(gc_streamCh, ltmp, IDGAINBITS);
          if (wd == 0) {
            ltmp = sam_GetBits(ATKLOCBITS_STOP_A);
            BsPutBit(gc_streamCh, ltmp, ATKLOCBITS_STOP_A);
          }
          else {
            ltmp = sam_GetBits(ATKLOCBITS_STOP_B);
            BsPutBit(gc_streamCh, ltmp, ATKLOCBITS_STOP_B);
          }
        }
      }
    }
    break;
  default:
    return  -1;
  }
  return  gc_streamCh->currentBit - loc;
}
#endif  /* SRS */

void my_debug(char *str)
{
/*   write(2, str, strlen(str)); */
}
