/* layer3.cpp

	Implementation of the layer III decoder

   01/31/97 : Layer III routines adopted from the ISO MPEG Audio Subgroup
   Software Simulation Group's public c source for its MPEG audio decoder.
   These routines were in the file "decoder.c". Rearrangement of the routines
   as member functions of a layer III decoder object, and optimizations by
   Jeff Tsay (ctsay@pasteur.eecs.berkeley.edu).

   04/14/97 : Several performance improvements. Inverse IMDCT moved to
   an external source file. No huffman tables needed, so no need for
   initialization. Put get_side_info() in this source file, and made
   one function inline for better speed and elegance. Also added support
   for mono decoding of stereo streams as well as downmixing. Bug fix
   in dequantize_samples(). */

#ifdef  __WIN32__
#define STRICT
#include <windows.h>
#endif   // __WIN32__

#include <math.h>


/* Data structures for layer III decoding. Taken from the ISO MPEG Audio
   Subgroup Software Simulation Group's public c source of the MPEG audio
   decoder.

   Last modified : 01/27/97  */





//#include "all.h"
//#include "l3type.h"
#include "ibitstream.h"
#include "obuffer.h"
#include "bit_res.h"
#include "header.h"
#include "synthesis_filter.h"
#include "huffman.h"
#include "layer3.h"
#include "inv_mdct.h"

LayerIII_Decoder::LayerIII_Decoder(Ibitstream *stream0,
                                   Header *header0,
                                   SynthesisFilter *filtera,
                                   SynthesisFilter *filterb,
                 						  Obuffer *buffer0,
                                   enum e_channels which_ch0)
{
  stream         = stream0;
  header         = header0;
  filter1        = filtera;
  filter2        = filterb;
  buffer         = buffer0;
  which_channels = which_ch0;

  frame_start = 0;
  channels    = (header->mode() == single_channel) ? 1 : 2;
  max_gr      = (header->version() == MPEG1) ? 2 : 1;

  if (channels == 2) {

  	  switch (which_channels) {

     case left:
     case downmix:
     first_channel = last_channel = 0;
     break;

     case right:
     first_channel = last_channel = 1;
     break;

     case both:
     first_channel  = 0;
     last_channel   = 1;
     break;

	  default:
     // uh oh
     break;

     }
  } else {

    first_channel = last_channel = 0;
  }

  for(uint32 i=0;i<2;i++)
  		for(uint32 j=0;j<SBLIMIT;j++)
  			for(uint32 k=0;k<SSLIMIT;k++)
  				prevblck[i][j][k] = 0.0f;

  br = new Bit_Reserve();
  si = new III_side_info_t;
}

LayerIII_Decoder::~LayerIII_Decoder()
{
   delete br;
   delete si;
}

void LayerIII_Decoder::seek_notify()
{
	frame_start = 0;

  	for(uint32 i=0;i<2;i++)
  		for(uint32 j=0;j<SBLIMIT;j++)
  			for(uint32 k=0;k<SSLIMIT;k++)
  				prevblck[i][j][k]=0.0f;

   delete br;
   br = new Bit_Reserve;
}


BOOL LayerIII_Decoder::get_side_info()
// Reads the side info from the stream, assuming the entire
// frame has been read already.

// Mono   : 136 bits (= 17 bytes)
// Stereo : 256 bits (= 32 bytes)

{
	if (header->version() == MPEG1) {

		si->main_data_begin = stream->get_bits(9);
		if (channels == 1)
			si->private_bits = stream->get_bits(5);
		else si->private_bits = stream->get_bits(3);

		for (uint32 ch=0; ch<channels; ch++) {
			si->ch[ch].scfsi[0] = stream->get_bits(1);
			si->ch[ch].scfsi[1] = stream->get_bits(1);
			si->ch[ch].scfsi[2] = stream->get_bits(1);
			si->ch[ch].scfsi[3] = stream->get_bits(1);
	   }

		for (uint32 gr=0; gr<2; gr++) {
			for (uint32 ch=0; ch<channels; ch++) {
				si->ch[ch].gr[gr].part2_3_length = stream->get_bits(12);
  				si->ch[ch].gr[gr].big_values = stream->get_bits(9);
				si->ch[ch].gr[gr].global_gain = stream->get_bits(8);
				si->ch[ch].gr[gr].scalefac_compress = stream->get_bits(4);
				si->ch[ch].gr[gr].window_switching_flag = stream->get_bits(1);
				if (si->ch[ch].gr[gr].window_switching_flag) {
					si->ch[ch].gr[gr].block_type       = stream->get_bits(2);
					si->ch[ch].gr[gr].mixed_block_flag = stream->get_bits(1);

					si->ch[ch].gr[gr].table_select[0]  = stream->get_bits(5);
					si->ch[ch].gr[gr].table_select[1]  = stream->get_bits(5);

					si->ch[ch].gr[gr].subblock_gain[0] = stream->get_bits(3);
					si->ch[ch].gr[gr].subblock_gain[1] = stream->get_bits(3);
					si->ch[ch].gr[gr].subblock_gain[2] = stream->get_bits(3);

					// Set region_count parameters since they are implicit in this case.

					if (si->ch[ch].gr[gr].block_type == 0) {
						//	 Side info bad: block_type == 0 in split block
						return(FALSE);
					} else if (si->ch[ch].gr[gr].block_type == 2
	  							  && si->ch[ch].gr[gr].mixed_block_flag == 0) {
						si->ch[ch].gr[gr].region0_count = 8;
               } else {
	               si->ch[ch].gr[gr].region0_count = 7;
               }
					si->ch[ch].gr[gr].region1_count = 20 -
							si->ch[ch].gr[gr].region0_count;
				} else {
					si->ch[ch].gr[gr].table_select[0] = stream->get_bits(5);
					si->ch[ch].gr[gr].table_select[1] = stream->get_bits(5);
					si->ch[ch].gr[gr].table_select[2] = stream->get_bits(5);
					si->ch[ch].gr[gr].region0_count = stream->get_bits(4);
					si->ch[ch].gr[gr].region1_count = stream->get_bits(3);
					si->ch[ch].gr[gr].block_type = 0;
				}
				si->ch[ch].gr[gr].preflag = stream->get_bits(1);
				si->ch[ch].gr[gr].scalefac_scale = stream->get_bits(1);
				si->ch[ch].gr[gr].count1table_select = stream->get_bits(1);
         }
      }

   } else {  	// MPEG-2 LSF

      si->main_data_begin = stream->get_bits(8);
      if (channels == 1)
      	si->private_bits = stream->get_bits(1);
      else si->private_bits = stream->get_bits(2);


      for (uint32 ch=0; ch<channels; ch++) {

          si->ch[ch].gr[0].part2_3_length = stream->get_bits(12);
          si->ch[ch].gr[0].big_values = stream->get_bits(9);
          si->ch[ch].gr[0].global_gain = stream->get_bits(8);
          si->ch[ch].gr[0].scalefac_compress = stream->get_bits(9);
          si->ch[ch].gr[0].window_switching_flag = stream->get_bits(1);

          if (si->ch[ch].gr[0].window_switching_flag) {

             si->ch[ch].gr[0].block_type = stream->get_bits(2);
             si->ch[ch].gr[0].mixed_block_flag = stream->get_bits(1);
             si->ch[ch].gr[0].table_select[0] = stream->get_bits(5);
             si->ch[ch].gr[0].table_select[1] = stream->get_bits(5);

             si->ch[ch].gr[0].subblock_gain[0] = stream->get_bits(3);
             si->ch[ch].gr[0].subblock_gain[1] = stream->get_bits(3);
             si->ch[ch].gr[0].subblock_gain[2] = stream->get_bits(3);

            // Set region_count parameters since they are implicit in this case.

             if (si->ch[ch].gr[0].block_type == 0) {
                // Side info bad: block_type == 0 in split block
                return(FALSE);
             } else if (si->ch[ch].gr[0].block_type == 2
                      && si->ch[ch].gr[0].mixed_block_flag == 0) {
             	 si->ch[ch].gr[0].region0_count = 8;
				 } else {
             	 si->ch[ch].gr[0].region0_count = 7;
                si->ch[ch].gr[0].region1_count = 20 -
                											si->ch[ch].gr[0].region0_count;
             }

          } else {
             si->ch[ch].gr[0].table_select[0] = stream->get_bits(5);
             si->ch[ch].gr[0].table_select[1] = stream->get_bits(5);
             si->ch[ch].gr[0].table_select[2] = stream->get_bits(5);
             si->ch[ch].gr[0].region0_count = stream->get_bits(4);
             si->ch[ch].gr[0].region1_count = stream->get_bits(3);
             si->ch[ch].gr[0].block_type = 0;
          }

          si->ch[ch].gr[0].scalefac_scale = stream->get_bits(1);
          si->ch[ch].gr[0].count1table_select = stream->get_bits(1);
      }   // for(ch=0; ch<channels; ch++)
   } // if (header->version() == MPEG1)
	return(TRUE);
}

struct {
	int32 l[5];
	int32 s[3];} sfbtable = {{0, 6, 11, 16, 21},
								    {0, 6, 12}};

int32 slen[2][16] = {{0, 0, 0, 0, 3, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4},
                     {0, 1, 2, 3, 0, 1, 2, 3, 1, 2, 3, 1, 2, 3, 2, 3}};

void LayerIII_Decoder::get_scale_factors(uint32 ch, uint32 gr)
{
	int32 sfb, window;
	gr_info_s *gr_info = &(si->ch[ch].gr[gr]);
   int32 scale_comp   = gr_info->scalefac_compress;
   int32 length0      = slen[0][scale_comp];
   int32 length1      = slen[1][scale_comp];

	 if (gr_info->window_switching_flag && (gr_info->block_type == 2)) {
		if (gr_info->mixed_block_flag) { // MIXED  -  NEW - ag 11/25
			for (sfb = 0; sfb < 8; sfb++)
				scalefac[ch].l[sfb] = br->hgetbits(
					  slen[0][gr_info->scalefac_compress]);
			for (sfb = 3; sfb < 6; sfb++)
				for (window=0; window<3; window++)
					scalefac[ch].s[window][sfb] = br->hgetbits(
					  slen[0][gr_info->scalefac_compress]);
			for (sfb = 6; sfb < 12; sfb++)
				for (window=0; window<3; window++)
					scalefac[ch].s[window][sfb] = br->hgetbits(
					  slen[1][gr_info->scalefac_compress]);
			for (sfb=12,window=0; window<3; window++)
				scalefac[ch].s[window][sfb] = 0;
		}
		else {  // SHORT

         scalefac[ch].s[0][0]  = br->hgetbits(length0);
         scalefac[ch].s[1][0]  = br->hgetbits(length0);
         scalefac[ch].s[2][0]  = br->hgetbits(length0);
         scalefac[ch].s[0][1]  = br->hgetbits(length0);
         scalefac[ch].s[1][1]  = br->hgetbits(length0);
         scalefac[ch].s[2][1]  = br->hgetbits(length0);
         scalefac[ch].s[0][2]  = br->hgetbits(length0);
         scalefac[ch].s[1][2]  = br->hgetbits(length0);
         scalefac[ch].s[2][2]  = br->hgetbits(length0);
         scalefac[ch].s[0][3]  = br->hgetbits(length0);
         scalefac[ch].s[1][3]  = br->hgetbits(length0);
         scalefac[ch].s[2][3]  = br->hgetbits(length0);
         scalefac[ch].s[0][4]  = br->hgetbits(length0);
         scalefac[ch].s[1][4]  = br->hgetbits(length0);
         scalefac[ch].s[2][4]  = br->hgetbits(length0);
         scalefac[ch].s[0][5]  = br->hgetbits(length0);
         scalefac[ch].s[1][5]  = br->hgetbits(length0);
         scalefac[ch].s[2][5]  = br->hgetbits(length0);
         scalefac[ch].s[0][6]  = br->hgetbits(length1);
         scalefac[ch].s[1][6]  = br->hgetbits(length1);
         scalefac[ch].s[2][6]  = br->hgetbits(length1);
         scalefac[ch].s[0][7]  = br->hgetbits(length1);
         scalefac[ch].s[1][7]  = br->hgetbits(length1);
         scalefac[ch].s[2][7]  = br->hgetbits(length1);
         scalefac[ch].s[0][8]  = br->hgetbits(length1);
         scalefac[ch].s[1][8]  = br->hgetbits(length1);
         scalefac[ch].s[2][8]  = br->hgetbits(length1);
         scalefac[ch].s[0][9]  = br->hgetbits(length1);
         scalefac[ch].s[1][9]  = br->hgetbits(length1);
         scalefac[ch].s[2][9]  = br->hgetbits(length1);
         scalefac[ch].s[0][10] = br->hgetbits(length1);
         scalefac[ch].s[1][10] = br->hgetbits(length1);
         scalefac[ch].s[2][10] = br->hgetbits(length1);
         scalefac[ch].s[0][11] = br->hgetbits(length1);
         scalefac[ch].s[1][11] = br->hgetbits(length1);
         scalefac[ch].s[2][11] = br->hgetbits(length1);
         scalefac[ch].s[0][12] = 0;
			scalefac[ch].s[1][12] = 0;
			scalefac[ch].s[2][12] = 0;

		}
	 }
	 else {   // LONG types 0,1,3

        if ((si->ch[ch].scfsi[0] == 0) || (gr == 0)) {
           scalefac[ch].l[0]  = br->hgetbits(length0);
           scalefac[ch].l[1]  = br->hgetbits(length0);
           scalefac[ch].l[2]  = br->hgetbits(length0);
           scalefac[ch].l[3]  = br->hgetbits(length0);
           scalefac[ch].l[4]  = br->hgetbits(length0);
           scalefac[ch].l[5]  = br->hgetbits(length0);
		  }
        if ((si->ch[ch].scfsi[1] == 0) || (gr == 0)) {
           scalefac[ch].l[6]  = br->hgetbits(length0);
           scalefac[ch].l[7]  = br->hgetbits(length0);
           scalefac[ch].l[8]  = br->hgetbits(length0);
           scalefac[ch].l[9]  = br->hgetbits(length0);
           scalefac[ch].l[10] = br->hgetbits(length0);
		  }
        if ((si->ch[ch].scfsi[2] == 0) || (gr == 0)) {
           scalefac[ch].l[11] = br->hgetbits(length1);
           scalefac[ch].l[12] = br->hgetbits(length1);
           scalefac[ch].l[13] = br->hgetbits(length1);
           scalefac[ch].l[14] = br->hgetbits(length1);
           scalefac[ch].l[15] = br->hgetbits(length1);
		  }
        if ((si->ch[ch].scfsi[3] == 0) || (gr == 0)) {
           scalefac[ch].l[16] = br->hgetbits(length1);
           scalefac[ch].l[17] = br->hgetbits(length1);
           scalefac[ch].l[18] = br->hgetbits(length1);
           scalefac[ch].l[19] = br->hgetbits(length1);
           scalefac[ch].l[20] = br->hgetbits(length1);
		  }

        scalefac[ch].l[21] = 0;
		  scalefac[ch].l[22] = 0;
	 }
}

struct  {
	int32 l[23];
	int32 s[14];} sfBandIndex[3] =
	{{{0,4,8,12,16,20,24,30,36,44,52,62,74,90,110,134,162,196,238,288,342,418,576},
	  {0,4,8,12,16,22,30,40,52,66,84,106,136,192}},
	 {{0,4,8,12,16,20,24,30,36,42,50,60,72,88,106,128,156,190,230,276,330,384,576},
	  {0,4,8,12,16,22,28,38,50,64,80,100,126,192}},
	 {{0,4,8,12,16,20,24,30,36,44,54,66,82,102,126,156,194,240,296,364,448,550,576},
	  {0,4,8,12,16,22,30,42,58,78,104,138,180,192}}};

void LayerIII_Decoder::huffman_decode(uint32 ch, uint32 gr)
{
	int32 i, x, y;
	int32 v, w;
   int32 part2_3_end = part2_start + si->ch[ch].gr[gr].part2_3_length;
   int32 num_bits;
	int32 region1Start;
	int32 region2Start;
   int32 sf_index;
   int32 ssindex, sbindex;
 	struct huffcodetab *h;

	// Find region boundary for short block case

	if ( (si->ch[ch].gr[gr].window_switching_flag) &&
		  (si->ch[ch].gr[gr].block_type == 2) ) {

		// Region2.

		region1Start = 36;  // sfb[9/3]*3=36
		region2Start = 576; // No Region2 for short block case
	}

	else {          // Find region boundary for long block case

   	sf_index = header->sample_frequency();

		region1Start = sfBandIndex[sf_index].l[si->ch[ch].gr[gr].region0_count
                                             + 1]; /* MI */
		region2Start = sfBandIndex[sf_index].l[si->ch[ch].gr[gr].region0_count +
										   si->ch[ch].gr[gr].region1_count + 2]; /* MI */
		}

   sbindex = 0; ssindex = 0;
	// Read bigvalues area
	for (i=0; i< (int32)(si->ch[ch].gr[gr].big_values<<1); i+=2) {
		if      (i<region1Start) h = &ht[si->ch[ch].gr[gr].table_select[0]];
		else if (i<region2Start) h = &ht[si->ch[ch].gr[gr].table_select[1]];
			  else                h = &ht[si->ch[ch].gr[gr].table_select[2]];

		huffman_decoder(h, &x, &y, &v, &w, br);

      is[sbindex][ssindex]   = x;
      is[sbindex][ssindex+1] = y;

      ssindex += 2;
      if (ssindex >= SSLIMIT) {
      	ssindex = 0;
         sbindex++;
      }
	}

	// Read count1 area
	h = &ht[(*si).ch[ch].gr[gr].count1table_select+32];
   num_bits = br->hsstell();

	while ((num_bits < part2_3_end) && (sbindex < SBLIMIT)) {

		huffman_decoder(h, &x, &y, &v, &w, br);
      is[sbindex][ssindex]   = v;
      is[sbindex][ssindex+1] = w;

      ssindex += 2;
      if (ssindex >= SSLIMIT) {
      	ssindex = 0;
         sbindex++;
      }

		if (sbindex < SBLIMIT) {
			is[sbindex][ssindex]   = x;
			is[sbindex][ssindex+1] = y;
      }

      ssindex += 2;
      if (ssindex >= SSLIMIT) {
      	ssindex = 0;
         sbindex++;
      }
      num_bits = br->hsstell();
   }

	if (num_bits > part2_3_end) {
		br->rewindNbits(num_bits - part2_3_end);
      ssindex -= 4;
      if (ssindex < 0) {
      	ssindex += SSLIMIT;
         sbindex--;
      }
    }

   num_bits = br->hsstell();

	// Dismiss stuffing bits
	if (num_bits < part2_3_end)
   	br->hgetbits(part2_3_end - num_bits);

	// Zero out rest
   for (; ssindex < SSLIMIT; ssindex++)
   	is[sbindex][ssindex] = 0;

   sbindex++;

   for(; sbindex < SBLIMIT; sbindex++)
   	for(ssindex = 0; ssindex < SSLIMIT; ssindex+=3) {
      	is[sbindex][ssindex]   = 0;
         is[sbindex][ssindex+1] = 0;
         is[sbindex][ssindex+2] = 0;
      }
}

int32 pretab[22] = {0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,2,2,3,3,3,2,0};

void LayerIII_Decoder::dequantize_sample(real xr[SBLIMIT][SSLIMIT],
												     uint32 ch, uint32 gr)
{
   static real TO_FOUR_THIRDS[POW_TABLE_LIMIT];
	static real two_to_negative_half_pow[40];
   static BOOL Dequant_init = FALSE;
	gr_info_s *gr_info = &(si->ch[ch].gr[gr]);
	int32  ss, sb, cb=0, sfreq=header->sample_frequency();
	int32  next_cb_boundary=0, cb_begin=0, cb_width=0;
	int32  index=0, t_index;
   int32 *is1d;
   real   g_gain;
   real  *xr1d;

   if (!Dequant_init) {

   	uint32 i;

   	for(i=0; i<POW_TABLE_LIMIT; i++)
	  		TO_FOUR_THIRDS[i] = (real) pow((double) i, 4.0/3.0);

      for(i=0; i<40; i++)
      	two_to_negative_half_pow[i] = (real) pow(2.0, -0.5 * (double) i);

      Dequant_init = TRUE;
   }

	// choose correct scalefactor band per block type, initalize boundary

	if (gr_info->window_switching_flag && (gr_info->block_type == 2) ) {
		if (gr_info->mixed_block_flag)
			next_cb_boundary=sfBandIndex[sfreq].l[1];  // LONG blocks: 0,1,3
		else {
         cb_width = sfBandIndex[sfreq].s[1];
		   next_cb_boundary = (cb_width << 2) - cb_width;
	 	   cb_begin = 0;
		}
	} else {
		next_cb_boundary=sfBandIndex[sfreq].l[1];  // LONG blocks: 0,1,3
   }

   // Compute overall (global) scaling.

	g_gain = (real) pow(2.0 , (0.25 * (gr_info->global_gain - 210.0)));

   for (sb=0; sb < SBLIMIT; sb++) {

   	is1d = is[sb];		xr1d = xr[sb];
   	for(ss=0; ss < SSLIMIT; ss++) {

      	if (is1d[ss] == 0) {
				xr1d[ss] = 0.0f;
         } else {
         	uint32 abv = abs(is1d[ss]);
            if (abv < POW_TABLE_LIMIT)
               xr1d[ss] = g_gain * TO_FOUR_THIRDS[abv];
            else
	            xr1d[ss] = g_gain * pow((double) abv, 1.333333333);

            if (is1d[ss] < 0)   xr1d[ss] = -xr1d[ss];
         }
      }
	}

	// apply formula per block type

	for (sb=0; sb < SBLIMIT; sb++) {

		for (ss=0; ss < SSLIMIT; ss++) {

			if (index == next_cb_boundary)  { /* Adjust critical band boundary */
				if (gr_info->window_switching_flag && (gr_info->block_type == 2)) {
					if (gr_info->mixed_block_flag)  {

						if (index == sfBandIndex[sfreq].l[8])  {
                     next_cb_boundary = sfBandIndex[sfreq].s[4];
                     next_cb_boundary = (next_cb_boundary << 2) -
                     			           next_cb_boundary;
							cb = 3;
						   cb_width = sfBandIndex[sfreq].s[4] -
                     			  sfBandIndex[sfreq].s[3];

					      cb_begin = sfBandIndex[sfreq].s[3];
                     cb_begin = (cb_begin << 2) - cb_begin;
						}

						else if (index < sfBandIndex[sfreq].l[8])
							next_cb_boundary = sfBandIndex[sfreq].l[(++cb)+1];
						else {
                  	next_cb_boundary = sfBandIndex[sfreq].s[(++cb)+1];
                     next_cb_boundary = (next_cb_boundary << 2) -
                     				        next_cb_boundary;

                     cb_begin = sfBandIndex[sfreq].s[cb];
							cb_width = sfBandIndex[sfreq].s[cb+1] -
                                cb_begin;
                     cb_begin = (cb_begin << 2) - cb_begin;
						}
					}
					else  {
                  next_cb_boundary = sfBandIndex[sfreq].s[(++cb)+1];
                  next_cb_boundary = (next_cb_boundary << 2) -
                                      next_cb_boundary;

                  cb_begin = sfBandIndex[sfreq].s[cb];
						cb_width = sfBandIndex[sfreq].s[cb+1] -
                               cb_begin;
                  cb_begin = (cb_begin << 2) - cb_begin;
					}
				}
				else // long blocks
					next_cb_boundary = sfBandIndex[sfreq].l[(++cb)+1];
			}

			// Do long/short dependent scaling operations

			if (gr_info->window_switching_flag &&
				 (((gr_info->block_type == 2) && (gr_info->mixed_block_flag == 0)) ||
				  ((gr_info->block_type == 2) && gr_info->mixed_block_flag && (sb >= 2)) ))
         {

				t_index = (index - cb_begin) / cb_width;
            xr[sb][ss] *= pow(2.0, ((-2.0 * gr_info->subblock_gain[t_index])
                                    -(0.5 * (1.0 + gr_info->scalefac_scale)
                                      * scalefac[ch].s[t_index][cb])));
			} else {   // LONG block types 0,1,3 & 1st 2 subbands of switched blocks
/*				xr[sb][ss] *= pow(2.0, -0.5 * (1.0+gr_info->scalefac_scale)
													 * (scalefac[ch].l[cb]
													 + gr_info->preflag * pretab[cb])); */
				uint32 idx = scalefac[ch].l[cb];

   			if (gr_info->preflag)
			   	idx += pretab[cb];

			   idx = idx << gr_info->scalefac_scale;

            xr[sb][ss] *= two_to_negative_half_pow[idx];
			}
         index++;
		}
   }
}

void LayerIII_Decoder::reorder (real xr[SBLIMIT][SSLIMIT], uint32 ch, uint32 gr)
{

	gr_info_s *gr_info = &(si->ch[ch].gr[gr]);
	uint32 sfreq = (uint32) header->sample_frequency();
   uint32 freq, freq3;
	int32 sfb, sfb_start, sfb_lines;
   int32 src_line, des_line;
   real *ho, *xr1d;

	if (gr_info->window_switching_flag && (gr_info->block_type == 2)) {

		for(uint32 sb=0;sb<SBLIMIT;sb++) {
      	ho = re_hybridOut[sb];
         ho[0]  = 0.0f;		ho[1]  = 0.0f;		ho[2]  = 0.0f;
         ho[3]  = 0.0f;		ho[4]  = 0.0f;		ho[5]  = 0.0f;
         ho[6]  = 0.0f;		ho[7]  = 0.0f;		ho[8]  = 0.0f;
         ho[9]  = 0.0f;		ho[10] = 0.0f;		ho[11] = 0.0f;
         ho[12] = 0.0f;		ho[13] = 0.0f;		ho[14] = 0.0f;
         ho[15] = 0.0f;		ho[16] = 0.0f;		ho[17] = 0.0f;
		}

		if (gr_info->mixed_block_flag) {
			// NO REORDER FOR LOW 2 SUBBANDS
			   for (uint32 ss=0; ss < SSLIMIT; ss+=3) {
					re_hybridOut[0][ss]   = xr[0][ss];
               re_hybridOut[0][ss+1] = xr[0][ss+1];
               re_hybridOut[0][ss+2] = xr[0][ss+2];
            }

            for (uint32 ss=0; ss < SSLIMIT; ss+=3) {
            	re_hybridOut[1][ss]   = xr[1][ss];
               re_hybridOut[1][ss+1] = xr[1][ss+1];
               re_hybridOut[1][ss+2] = xr[1][ss+2];
            }

			// REORDERING FOR REST SWITCHED SHORT
				for(sfb=3,sfb_start=sfBandIndex[sfreq].s[3],
	  				 sfb_lines=sfBandIndex[sfreq].s[4] - sfb_start;
	  				 sfb < 13; sfb++,sfb_start = sfBandIndex[sfreq].s[sfb],
				    (sfb_lines=sfBandIndex[sfreq].s[sfb+1] - sfb_start))
            {
					   int32 sfb_start3 = (sfb_start << 2) - sfb_start;

						for(freq=0, freq3=0; freq<(uint32)sfb_lines;
                      freq++, freq3+=3) {

							src_line = sfb_start3 + freq;
							des_line = sfb_start3 + freq3;
							re_hybridOut[des_line/SSLIMIT][des_line%SSLIMIT] =
												xr[src_line/SSLIMIT][src_line%SSLIMIT];
							src_line += sfb_lines;
							des_line++;
							re_hybridOut[des_line/SSLIMIT][des_line%SSLIMIT] =
												xr[src_line/SSLIMIT][src_line%SSLIMIT];
							src_line += sfb_lines;
							des_line++;
							re_hybridOut[des_line/SSLIMIT][des_line%SSLIMIT] =
												xr[src_line/SSLIMIT][src_line%SSLIMIT];
					   }
            }
		}
		else {  // pure short
			for(sfb=0,sfb_start=0,sfb_lines=sfBandIndex[sfreq].s[1];
				sfb < 13; sfb++,sfb_start=sfBandIndex[sfreq].s[sfb],
				(sfb_lines=sfBandIndex[sfreq].s[sfb+1] - sfb_start))
            {
					   int32 sfb_start3 = (sfb_start << 2) - sfb_start;

						for(freq=0, freq3=0; freq<(uint32)sfb_lines;
                      freq++, freq3+=3) {

							src_line = sfb_start3 + freq;
							des_line = sfb_start3 + freq3;
							re_hybridOut[des_line/SSLIMIT][des_line%SSLIMIT] =
												xr[src_line/SSLIMIT][src_line%SSLIMIT];
							src_line += sfb_lines;
							des_line++;
							re_hybridOut[des_line/SSLIMIT][des_line%SSLIMIT] =
												xr[src_line/SSLIMIT][src_line%SSLIMIT];
							src_line += sfb_lines;
							des_line++;
							re_hybridOut[des_line/SSLIMIT][des_line%SSLIMIT] =
												xr[src_line/SSLIMIT][src_line%SSLIMIT];
					   }
            }
		}
	}
	else {   // long blocks
		for (uint32 sb=0; sb < SBLIMIT; sb++) {
       	ho = re_hybridOut[sb];	    xr1d = xr[sb];
         ho[0]  = xr1d[0];         ho[1]  = xr1d[1];
         ho[2]  = xr1d[2];         ho[3]  = xr1d[3];
         ho[4]  = xr1d[4];         ho[5]  = xr1d[5];
         ho[6]  = xr1d[6];         ho[7]  = xr1d[7];
         ho[8]  = xr1d[8];         ho[9]  = xr1d[9];
         ho[10] = xr1d[10];        ho[11] = xr1d[11];
         ho[12] = xr1d[12];        ho[13] = xr1d[13];
         ho[14] = xr1d[14];        ho[15] = xr1d[15];
         ho[16] = xr1d[16];        ho[17] = xr1d[17];
      }
	}
}

real TAN12[16]={0.0, 0.26794919, 0.57735027, 1.0,
                1.73205081, 3.73205081, 9.9999999e10 /*unbounded*/, -3.73205081,
                -1.73205081, -1.0, -0.57735027, -0.26794919,
                0.0, 0.26794919, 0.57735027, 1.0};

void LayerIII_Decoder::stereo(uint32 gr)
{
	int32 is_pos[576];
	real  is_ratio[576];
	gr_info_s *gr_info = &(si->ch[0].gr[gr]);
	uint32 sfreq    = (uint32) header->sample_frequency();
   uint32 mode_ext = header->mode_extension();
	int32 sfb;
	int32 i, j;
   int32 sb, ss;
   int32 lines, temp, temp2;
	BOOL ms_stereo = (header->mode() == joint_stereo) && (mode_ext & 0x2);
	BOOL i_stereo  = (header->mode() == joint_stereo) && (mode_ext & 0x1);

	if  (channels == 1) { // mono , bypass xr[0][][] to lr[0][][]

		for(sb=0;sb<SBLIMIT;sb++)
			for(ss=0;ss<SSLIMIT;ss+=3) {
				lr[0][sb][ss]   = ro[0][sb][ss];
            lr[0][sb][ss+1] = ro[0][sb][ss+1];
				lr[0][sb][ss+2] = ro[0][sb][ss+2];
         }

   } else {

 	// initialization
   for (i=0; i<576; i+=8) {
      is_pos[i]   = 7; is_pos[i+1] = 7; is_pos[i+2] = 7; is_pos[i+3] = 7;
      is_pos[i+4] = 7; is_pos[i+5] = 7; is_pos[i+6] = 7; is_pos[i+7] = 7;
   }

	if (i_stereo)
	{  if (gr_info->window_switching_flag && (gr_info->block_type == 2))
		{  if (gr_info->mixed_block_flag)
			{  int32 max_sfb = 0;

				for (j=0; j<3; j++)
				{  int32 sfbcnt;
					sfbcnt = 2;
					for( sfb=12; sfb >=3; sfb-- )
					{
               	i = sfBandIndex[sfreq].s[sfb];
						lines = sfBandIndex[sfreq].s[sfb+1] - i;
                  i = (i << 2) - i + (j+1) * lines - 1;
						while ( lines > 0 )
						{  if ( ro[1][i/SSLIMIT][i%SSLIMIT] != 0.0f )
							{  sfbcnt = sfb;
								sfb = -10;
								lines = -10;
							}
							lines--;
							i--;
						}
					}
					sfb = sfbcnt + 1;

					if (sfb > max_sfb)
						max_sfb = sfb;

					while(sfb < 12)
					{	temp = sfBandIndex[sfreq].s[sfb];
               	sb   = sfBandIndex[sfreq].s[sfb+1] - temp;
                  i    = (temp << 2) - temp + j * sb;

						for ( ; sb > 0; sb--)
						{  is_pos[i] = scalefac[1].s[j][sfb];
							if (is_pos[i] != 7)
                        is_ratio[i] = TAN12[is_pos[i]];

							i++;
						}
						sfb++;
					}
					sfb = sfBandIndex[sfreq].s[10];
               sb  = sfBandIndex[sfreq].s[11] - sfb;
               sfb = (sfb << 2) - sfb + j * sb;
               temp  = sfBandIndex[sfreq].s[11];
               sb = sfBandIndex[sfreq].s[12] - temp;
               i = (temp << 2) - temp + j * sb;

					for ( ; sb > 0; sb-- )
					{  is_pos[i] = is_pos[sfb];
						is_ratio[i] = is_ratio[sfb];
						i++;
					}
				 }
				 if (max_sfb <= 3)
				 {  i = 2;
					 ss = 17;
					 sb = -1;
					 while (i >= 0)
					 {  if (ro[1][i][ss] != 0.0f)
						 {
                   	 sb = (i<<4) + (i<<1) + ss;
							 i = -1;
						 } else
						 {  ss--;
							 if (ss < 0)
							 {  i--;
								 ss = 17;
							 }
						 }
					 }
					 i = 0;
					 while ( sfBandIndex[sfreq].l[i] <= sb )
						 i++;
					 sfb = i;
					 i = sfBandIndex[sfreq].l[i];
					 for (; sfb<8; sfb++)
					 {  sb = sfBandIndex[sfreq].l[sfb+1]-sfBandIndex[sfreq].l[sfb];
						 for (; sb>0; sb--)
						 {  is_pos[i] = scalefac[1].l[sfb];
							 if (is_pos[i] != 7)
                      	 is_ratio[i] = TAN12[is_pos[i]];

							 i++;
						 }
					 }
				}
			} else
			{  for (j=0; j<3; j++)
				{  int32 sfbcnt;
					sfbcnt = -1;
					for( sfb=12; sfb >=0; sfb-- )
					{
						temp = sfBandIndex[sfreq].s[sfb];
                  lines = sfBandIndex[sfreq].s[sfb+1] - temp;
                  i = (temp << 2) - temp + (j+1) * lines - 1;

						while ( lines > 0 )
						{  if (ro[1][i/SSLIMIT][i%SSLIMIT] != 0.0f)
							{  sfbcnt = sfb;
								sfb = -10;
								lines = -10;
							}
							lines--;
							i--;
						}
					}
					sfb = sfbcnt + 1;
					while( sfb<12 )
					{
						temp = sfBandIndex[sfreq].s[sfb];
                  sb   = sfBandIndex[sfreq].s[sfb+1] - temp;
                  i    = (temp << 2) - temp + j * sb;
						for ( ; sb > 0; sb--)
						{  is_pos[i] = scalefac[1].s[j][sfb];
							if (is_pos[i] != 7)
						      is_ratio[i] = TAN12[is_pos[i]];

							i++;
						}
						sfb++;
					}

					temp = sfBandIndex[sfreq].s[10];
               temp2= sfBandIndex[sfreq].s[11];
               sb   = temp2 - temp;
               sfb  = (temp << 2) - temp + j * sb;
               sb   = sfBandIndex[sfreq].s[12] - temp2;
               i    = (temp2 << 2) - temp2 + j * sb;

					for (; sb>0; sb--)
					{  is_pos[i] = is_pos[sfb];
						is_ratio[i] = is_ratio[sfb];
						i++;
					}
				}
			}
		} else // ms-stereo
		{  i = 31;
			ss = 17;
			sb = 0;
			while (i >= 0)
			{  if (ro[1][i][ss] != 0.0f)
				{
            	sb = (i<<4) + (i<<1) + ss;
					i = -1;
				} else
				{  ss--;
					if (ss < 0)
					{  i--;
						ss = 17;
					}
				}
			}
			i = 0;
			while ( sfBandIndex[sfreq].l[i] <= sb )
				i++;
			sfb = i;
			i = sfBandIndex[sfreq].l[i];
			for ( ; sfb<21; sfb++ )
			{  sb = sfBandIndex[sfreq].l[sfb+1] - sfBandIndex[sfreq].l[sfb];
				for ( ; sb > 0; sb--)
				{  is_pos[i] = scalefac[1].l[sfb];
					if (is_pos[i] != 7)
               	is_ratio[i] = TAN12[is_pos[i]];

					i++;
				}
			}
			sfb = sfBandIndex[sfreq].l[20];
			for ( sb = 576 - sfBandIndex[sfreq].l[21]; sb > 0; sb-- )
			{  is_pos[i] = is_pos[sfb];
				is_ratio[i] = is_ratio[sfb];
				i++;
			}
		}
	}

   	i = 0;
		for(sb=0;sb<SBLIMIT;sb++)
			for(ss=0;ss<SSLIMIT;ss++) {
				if (is_pos[i] == 7) {
					if (ms_stereo) {
						lr[0][sb][ss] = (ro[0][sb][ss]+ro[1][sb][ss]) * 0.707106781f;
						lr[1][sb][ss] = (ro[0][sb][ss]-ro[1][sb][ss]) * 0.707106781f;
					}
					else {
						lr[0][sb][ss] = ro[0][sb][ss];
						lr[1][sb][ss] = ro[1][sb][ss];
					}
				}
				else if (i_stereo) {
               lr[1][sb][ss] = ro[0][sb][ss] / (real) (1 + is_ratio[i]);
  				   lr[0][sb][ss] = lr[1][sb][ss] * is_ratio[i];
				}
/*				else {
					printf("Error in stereo processing\n");
				} */
            i++;
			}

    } // channels == 2
}

real Ci[8]={-0.6f,-0.535f,-0.33f,-0.185f,-0.095f,-0.041f,-0.0142f,-0.0037f};

void LayerIII_Decoder::antialias(uint32 ch, uint32 gr)
{
 	static real   ca[8],cs[8];
 	static BOOL   antialias_init = FALSE;
   gr_info_s *gr_info = &(si->ch[ch].gr[gr]);
   real *hi, *hi1;
   real *ho, *ho1;

	if (!antialias_init) {
		for (int32 i=0;i<8;i++) {
			real sq = sqrt(1.0f + Ci[i]*Ci[i]);
			cs[i] = 1.0f/sq;
         ca[i] = Ci[i] * cs[i];
		}
		antialias_init = TRUE;
	}

	// 31 alias-reduction operations between each pair of sub-bands
	// with 8 butterflies between each pair

	if  (gr_info->window_switching_flag && (gr_info->block_type == 2) &&
		 !gr_info->mixed_block_flag ) {

   	for(uint32 sb=0;sb<SBLIMIT;sb++) {
      	hi    = hybridIn[sb];	ho    = re_hybridOut[sb];
        	hi[0] = ho[0];	         hi[1] = ho[1];
        	hi[2] = ho[2];	 	      hi[3] = ho[3];
        	hi[4] = ho[4];        	hi[5] = ho[5];
        	hi[6] = ho[6];        	hi[7] = ho[7];
        	hi[8] = ho[8];        	hi[9] = ho[9];
        	hi[10]= ho[10];        	hi[11]= ho[11];
        	hi[12]= ho[12];        	hi[13]= ho[13];
        	hi[14]= ho[14];        	hi[15]= ho[15];
       	hi[16]= ho[16];        	hi[17]= ho[17];
      }

	} else if (gr_info->window_switching_flag && gr_info->mixed_block_flag &&
	  (gr_info->block_type == 2)) {

      hi    = hybridIn[0];		ho    = re_hybridOut[0];
      hi[0] = ho[0];	         hi[1] = ho[1];
      hi[2] = ho[2];	 	      hi[3] = ho[3];
      hi[4] = ho[4];        	hi[5] = ho[5];
      hi[6] = ho[6];        	hi[7] = ho[7];
      hi[8] = ho[8];        	hi[9] = ho[9];

      hi1 = hybridIn[1];      ho1 = re_hybridOut[1];

      for(uint32 ss=0;ss<8;ss++) {
			real bu = ho[17-ss];
			real bd = ho1[ss];
			hi[17-ss] = (bu * cs[ss]) - (bd * ca[ss]);
			hi1[ss]   = (bd * cs[ss]) + (bu * ca[ss]);
      }

      hi1[8]  = ho1[8];         hi1[9]  = ho1[9];
      hi1[10] = ho1[10];        hi1[11] = ho1[11];
      hi1[12] = ho1[12];        hi1[13] = ho1[13];
      hi1[14] = ho1[14];        hi1[15] = ho1[15];
      hi1[16] = ho1[16];        hi1[17] = ho1[17];

		for(uint32 sb=2;sb<SBLIMIT;sb++) {
      	hi    = hybridIn[sb];   ho    = re_hybridOut[sb];
        	hi[0] = ho[0];          hi[1] = ho[1];
        	hi[2] = ho[2];        	hi[3] = ho[3];
        	hi[4] = ho[4];        	hi[5] = ho[5];
        	hi[6] = ho[6];        	hi[7] = ho[7];
        	hi[8] = ho[8];        	hi[9] = ho[9];
        	hi[10]= ho[10];        	hi[11]= ho[11];
        	hi[12]= ho[12];        	hi[13]= ho[13];
        	hi[14]= ho[14];        	hi[15]= ho[15];
        	hi[16]= ho[16];        	hi[17]= ho[17];
      }

	} else {

   	hi    = hybridIn[0];	ho    = re_hybridOut[0];
      hi[0] = ho[0];			hi[1] = ho[1];
      hi[2] = ho[2];       hi[3] = ho[3];
      hi[4] = ho[4];       hi[5] = ho[5];
      hi[6] = ho[6];       hi[7] = ho[7];

		for(uint32 sb=0; sb < (SBLIMIT - 1); sb++) {
      	hi  = hybridIn[sb];	  ho  = re_hybridOut[sb];
         hi1 = hybridIn[sb+1];  ho1 = re_hybridOut[sb+1];

			for(uint32 ss=0;ss<8;ss++) {
				real bu = ho[17-ss];
				real bd = ho1[ss];
				hi[17-ss]  = (bu * cs[ss]) - (bd * ca[ss]);
				hi1[ss]    = (bd * cs[ss]) + (bu * ca[ss]);
			}

         hi[8]   = ho[8];   hi[9]   = ho[9];
      }
      // now hi1 = hybridIn[31] and ho1 = re_hybridOut[31]
      hi1[8]  = ho1[8];     hi1[9]  = ho1[9];
      hi1[10] = ho1[10];    hi1[11] = ho1[11];
      hi1[12] = ho1[12];    hi1[13] = ho1[13];
      hi1[14] = ho1[14];    hi1[15] = ho1[15];
      hi1[16] = ho1[16];    hi1[17] = ho1[17];
   }
}

void LayerIII_Decoder::hybrid(uint32 ch, uint32 gr)
{
	real rawout[36];
   uint32 bt;
   gr_info_s *gr_info = &(si->ch[ch].gr[gr]);
   real *tsOut;
   real *prvblk;

   for(uint32 sb=0;sb<SBLIMIT;sb++) {

		bt = (gr_info->window_switching_flag && gr_info->mixed_block_flag &&
				 (sb < 2)) ? 0 : gr_info->block_type;

		inv_mdct(hybridIn[sb], rawout, bt);

		// overlap addition

	   tsOut  = re_hybridOut[sb];
   	prvblk = prevblck[ch][sb];

	   tsOut[0]   = rawout[0]  + prvblk[0];
	   prvblk[0]  = rawout[18];
	   tsOut[1]   = rawout[1]  + prvblk[1];
	   prvblk[1]  = rawout[19];
	   tsOut[2]   = rawout[2]  + prvblk[2];
	   prvblk[2]  = rawout[20];
	   tsOut[3]   = rawout[3]  + prvblk[3];
	   prvblk[3]  = rawout[21];
	   tsOut[4]   = rawout[4]  + prvblk[4];
	   prvblk[4]  = rawout[22];
	   tsOut[5]   = rawout[5]  + prvblk[5];
	   prvblk[5]  = rawout[23];
	   tsOut[6]   = rawout[6]  + prvblk[6];
	   prvblk[6]  = rawout[24];
	   tsOut[7]   = rawout[7]  + prvblk[7];
	   prvblk[7]  = rawout[25];
	   tsOut[8]   = rawout[8]  + prvblk[8];
	   prvblk[8]  = rawout[26];
	   tsOut[9]   = rawout[9]  + prvblk[9];
	   prvblk[9]  = rawout[27];
   	tsOut[10]  = rawout[10] + prvblk[10];
   	prvblk[10] = rawout[28];
   	tsOut[11]  = rawout[11] + prvblk[11];
      prvblk[11] = rawout[29];
   	tsOut[12]  = rawout[12] + prvblk[12];
   	prvblk[12] = rawout[30];
   	tsOut[13]  = rawout[13] + prvblk[13];
   	prvblk[13] = rawout[31];
   	tsOut[14]  = rawout[14] + prvblk[14];
   	prvblk[14] = rawout[32];
   	tsOut[15]  = rawout[15] + prvblk[15];
   	prvblk[15] = rawout[33];
   	tsOut[16]  = rawout[16] + prvblk[16];
   	prvblk[16] = rawout[34];
   	tsOut[17]  = rawout[17] + prvblk[17];
   	prvblk[17] = rawout[35];
   }
}

void LayerIII_Decoder::do_downmix()
{
	for (uint32 sb=0; sb<SSLIMIT; sb++)
   	for (uint32 ss=0; ss<SSLIMIT; ss+=3) {
      	lr[0][sb][ss]   = (lr[0][sb][ss]   + lr[1][sb][ss])   * 0.5f;
      	lr[0][sb][ss+1] = (lr[0][sb][ss+1] + lr[1][sb][ss+1]) * 0.5f;
      	lr[0][sb][ss+2] = (lr[0][sb][ss+2] + lr[1][sb][ss+2]) * 0.5f;
      }
}

void LayerIII_Decoder::decode()
{
	 uint32 nSlots = header->slots();
    int32 main_data_end;
	 int32 bytes_to_discard;

	 get_side_info();

    for (uint32 i=0; i<nSlots; i++)
    	br->hputbuf((uint32) stream->get_8bits());
//    	br->hputbuf((uint32) stream->get_bits(8));

    main_data_end = br->hsstell() >> 3; // of previous frame

    if (uint32 flush_main = (br->hsstell() & 0x7)) {
         br->hgetbits(8 - flush_main);
			main_data_end++;
	 }

	 bytes_to_discard = frame_start - main_data_end
							  - si->main_data_begin;

	 frame_start += nSlots;

    if (bytes_to_discard < 0)
			return;

	 if (main_data_end > 4096) {
			frame_start -= 4096;
			br->rewindNbytes(4096);
	 }

	 for (; bytes_to_discard > 0; bytes_to_discard--)
    		br->hgetbits(8);

	 for (uint32 gr=0;gr<max_gr;gr++) {

			for (uint32 ch=0; ch<channels; ch++) {
           part2_start = br->hsstell();
			  get_scale_factors(ch, gr);
			  huffman_decode(ch, gr);
			  dequantize_sample(ro[ch], ch, gr);
			}

			stereo(gr);

         if ((which_channels == downmix) && (channels > 1))
            do_downmix();

			for (uint32 ch=first_channel; ch<=last_channel; ch++) {

					reorder (lr[ch], ch, gr);
					antialias(ch, gr);
               hybrid(ch, gr);

					for (uint32 ss=1;ss<SSLIMIT;ss+=2) // Frequency inversion
						  for (uint32 sb=1;sb<SBLIMIT;sb+=2)
								  re_hybridOut[sb][ss] = -re_hybridOut[sb][ss];

					if ((ch == 0) || (which_channels == right)) {
					  for (uint32 ss=0;ss<SSLIMIT;ss++) { // Polyphase synthesis
							for (uint32 sb=0;sb<SBLIMIT;sb++)
								filter1->input_sample(re_hybridOut[sb][ss], sb);

							filter1->calculate_pcm_samples(buffer);
					  }
					} else {
					  for (uint32 ss=0;ss<SSLIMIT;ss++) { // Polyphase synthesis
							for (uint32 sb=0;sb<SBLIMIT;sb++)
								filter2->input_sample(re_hybridOut[sb][ss], sb);

							filter2->calculate_pcm_samples(buffer);
					  }
               }
			}	// channels
	 }	// granule
  	 buffer->write_buffer(1);
}

