/*
layer3.c - compact version of famous library mpg123
Copyright (C) 2017 Uncle Mike

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
*/

#include "mpg123.h"
#include "huffman.h"
#include "getbits.h"
#include <math.h>

// static one-time calculated tables... or so
float		COS6_1;		// dct12 wants to use that
float		COS6_2;		// dct12 wants to use that
float		cos9[3];		// dct36 wants to use that
float		cos18[3];		// dct36 wants to use that
float		tfcos12[3];	// dct12 wants to use that
float		tfcos36[9];	// dct36 wants to use that
static float	ispow[8207];
static float	COS9[9];
static float	aa_ca[8];
static float	aa_cs[8];
static float	win[4][36];
static float	win1[4][36];
static float	tan1_1[16];
static float	tan2_1[16];
static float	tan1_2[16];
static float	tan2_2[16];
static float	pow1_1[2][16];
static float	pow2_1[2][16];
static float	pow1_2[2][16];
static float	pow2_2[2][16];
static int	mapbuf0[9][152];
static int	mapbuf1[9][156];
static int	mapbuf2[9][44];
static int	*map[9][3];
static int	*mapend[9][3];
static uint	n_slen2[512];	// MPEG 2.0 slen for 'normal' mode
static uint	i_slen2[256];	// MPEG 2.0 slen for intensity stereo

// Decoder state data, living on the stack of do_layer3.
typedef struct gr_info_s
{
	int	scfsi;
	uint	part2_3_length;
	uint	big_values;
	uint	scalefac_compress;
	uint	block_type;
	uint	mixed_block_flag;
	uint	table_select[3];

	// making those two signed int as workaround for open64/pathscale/sun compilers,
	// and also for consistency, since they're worked on together with other signed variables.
	int	maxband[3];
	int	maxbandl;
	uint	maxb;
	uint	region1start;
	uint	region2start;
	uint	preflag;
	uint	scalefac_scale;
	uint	count1table_select;
	float	*full_gain[3];
	float	*pow2gain;
} gr_info_t;

typedef struct
{
	uint	main_data_begin;
	uint	private_bits;

	// hm, funny... struct inside struct...
	struct
	{
		gr_info_t	gr[2];
	} ch[2];
} III_sideinfo;

typedef struct
{
	word	longIdx[23];
	byte	longDiff[22];
	word	shortIdx[14];
	byte	shortDiff[13];
} bandInfoStruct;

// techy details about our friendly MPEG data. Fairly constant over the years ;-)
static const bandInfoStruct bandInfo[9] =
{
	{ // MPEG 1.0
	{0,4,8,12,16,20,24,30,36,44,52,62,74, 90,110,134,162,196,238,288,342,418,576},
	{4,4,4,4,4,4,6,6,8, 8,10,12,16,20,24,28,34,42,50,54, 76,158},
	{0,4*3,8*3,12*3,16*3,22*3,30*3,40*3,52*3,66*3, 84*3,106*3,136*3,192*3},
	{4,4,4,4,6,8,10,12,14,18,22,30,56}
	},
	{
	{0,4,8,12,16,20,24,30,36,42,50,60,72, 88,106,128,156,190,230,276,330,384,576},
	{4,4,4,4,4,4,6,6,6, 8,10,12,16,18,22,28,34,40,46,54, 54,192},
	{0,4*3,8*3,12*3,16*3,22*3,28*3,38*3,50*3,64*3, 80*3,100*3,126*3,192*3},
	{4,4,4,4,6,6,10,12,14,16,20,26,66}
	},
	{
	{0,4,8,12,16,20,24,30,36,44,54,66,82,102,126,156,194,240,296,364,448,550,576},
	{4,4,4,4,4,4,6,6,8,10,12,16,20,24,30,38,46,56,68,84,102, 26},
	{0,4*3,8*3,12*3,16*3,22*3,30*3,42*3,58*3,78*3,104*3,138*3,180*3,192*3},
	{4,4,4,4,6,8,12,16,20,26,34,42,12}
	},
	{ // MPEG 2.0
	{0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576},
	{6,6,6,6,6,6,8,10,12,14,16,20,24,28,32,38,46,52,60,68,58,54 } ,
	{0,4*3,8*3,12*3,18*3,24*3,32*3,42*3,56*3,74*3,100*3,132*3,174*3,192*3} ,
	{4,4,4,6,6,8,10,14,18,26,32,42,18 }
	},
	{ // twiddling 3 values here (not just 330->332!) fixed bug 1895025.
	{0,6,12,18,24,30,36,44,54,66,80,96,114,136,162,194,232,278,332,394,464,540,576},
	{6,6,6,6,6,6,8,10,12,14,16,18,22,26,32,38,46,54,62,70,76,36 },
	{0,4*3,8*3,12*3,18*3,26*3,36*3,48*3,62*3,80*3,104*3,136*3,180*3,192*3},
	{4,4,4,6,8,10,12,14,18,24,32,44,12 }
	},
	{
	{0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576},
	{6,6,6,6,6,6,8,10,12,14,16,20,24,28,32,38,46,52,60,68,58,54 },
	{0,4*3,8*3,12*3,18*3,26*3,36*3,48*3,62*3,80*3,104*3,134*3,174*3,192*3},
	{4,4,4,6,8,10,12,14,18,24,30,40,18 }
	},
	{ // MPEG 2.5
	{0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576},
	{6,6,6,6,6,6,8,10,12,14,16,20,24,28,32,38,46,52,60,68,58,54},
	{0,12,24,36,54,78,108,144,186,240,312,402,522,576},
	{4,4,4,6,8,10,12,14,18,24,30,40,18}
	},
	{
	{0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576},
	{6,6,6,6,6,6,8,10,12,14,16,20,24,28,32,38,46,52,60,68,58,54},
	{0,12,24,36,54,78,108,144,186,240,312,402,522,576},
	{4,4,4,6,8,10,12,14,18,24,30,40,18}
	},
	{
	{0,12,24,36,48,60,72,88,108,132,160,192,232,280,336,400,476,566,568,570,572,574,576},
	{12,12,12,12,12,12,16,20,24,28,32,40,48,56,64,76,90,2,2,2,2,2},
	{0, 24, 48, 72,108,156,216,288,372,480,486,492,498,576},
	{8,8,8,12,16,20,24,28,36,2,2,2,26}
	}
};

static byte pretab_choice[2][22] =
{
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,2,2,3,3,3,2,0}
};

// init tables for layer-3 ... specific with the downsampling...
void init_layer3( void )
{
	int	i, j, k, l;

	for( i = 0; i < 8207; i++ )
		ispow[i] = DOUBLE_TO_REAL_POW43( pow( (double)i, (double)4.0 / 3.0 ));

	for( i = 0; i < 8; i++ )
	{
		const double Ci[8] = { -0.6, -0.535, -0.33, -0.185, -0.095, -0.041, -0.0142, -0.0037 };
		double sq = sqrt( 1.0 + Ci[i] * Ci[i] );
		aa_cs[i] = DOUBLE_TO_REAL( 1.0 / sq );
		aa_ca[i] = DOUBLE_TO_REAL( Ci[i] / sq );
	}

	for( i = 0; i < 18; i++ )
	{
		win[0][i] = win[1][i] = DOUBLE_TO_REAL( 0.5 * sin( M_PI / 72.0 * (double)(2 * (i + 0) + 1)) / cos( M_PI * (double)(2 * (i + 0) + 19) / 72.0) );
		win[0][i+18] = win[3][i+18] = DOUBLE_TO_REAL( 0.5 * sin( M_PI/72.0 * (double)(2 * (i + 18) + 1)) / cos( M_PI * (double)(2 * (i + 18) + 19) / 72.0) );
	}

	for( i = 0; i < 6; i++ )
	{
		win[1][i+18] = DOUBLE_TO_REAL( 0.5 / cos ( M_PI * (double)(2 * (i + 18) + 19) / 72.0 ));
		win[3][i+12] = DOUBLE_TO_REAL( 0.5 / cos ( M_PI * (double)(2 * (i + 12) + 19) / 72.0 ));
		win[1][i+24] = DOUBLE_TO_REAL( 0.5 * sin( M_PI / 24.0 * (double)(2 * i + 13)) / cos( M_PI * (double)(2 * (i + 24) + 19) / 72.0 ));
		win[1][i+30] = win[3][i] = DOUBLE_TO_REAL( 0.0 );
		win[3][i+6 ] = DOUBLE_TO_REAL( 0.5 * sin( M_PI / 24.0 * (double)(2 * i + 1)) / cos( M_PI * (double)(2 * (i + 6 ) + 19) / 72.0 ));
	}

	for( i = 0; i < 9; i++ )
		COS9[i] = DOUBLE_TO_REAL( cos( M_PI / 18.0 * (double)i ));

	for( i = 0; i < 9; i++ )
		tfcos36[i] = DOUBLE_TO_REAL( 0.5 / cos( M_PI * (double)(i * 2 + 1) / 36.0 ));

	for( i = 0; i < 3; i++ )
		tfcos12[i] = DOUBLE_TO_REAL( 0.5 / cos( M_PI * (double)(i * 2 + 1) / 12.0 ));

	COS6_1 = DOUBLE_TO_REAL( cos( M_PI / 6.0 * (double)1 ));
	COS6_2 = DOUBLE_TO_REAL( cos( M_PI / 6.0 * (double)2 ));

	cos9[0]  = DOUBLE_TO_REAL( cos( 1.0 * M_PI / 9.0));
	cos9[1]  = DOUBLE_TO_REAL( cos( 5.0 * M_PI / 9.0));
	cos9[2]  = DOUBLE_TO_REAL( cos( 7.0 * M_PI / 9.0));
	cos18[0] = DOUBLE_TO_REAL( cos( 1.0 * M_PI / 18.0));
	cos18[1] = DOUBLE_TO_REAL( cos( 11.0 * M_PI / 18.0));
	cos18[2] = DOUBLE_TO_REAL( cos( 13.0 * M_PI / 18.0));

	for( i = 0; i < 12; i++ )
		win[2][i] = DOUBLE_TO_REAL( 0.5 * sin( M_PI / 24.0 * (double)(2 * i + 1) ) / cos( M_PI * (double)(2 * i + 7) / 24.0 ));

	for( i = 0; i < 16; i++ )
	{
		double t = tan((double)i * M_PI / 12.0 );
		tan1_1[i] = DOUBLE_TO_REAL_15( t / (1.0 + t));
		tan2_1[i] = DOUBLE_TO_REAL_15( 1.0 / (1.0 + t));
		tan1_2[i] = DOUBLE_TO_REAL_15( M_SQRT2 * t / (1.0 + t));
		tan2_2[i] = DOUBLE_TO_REAL_15( M_SQRT2 / (1.0 + t));

		for( j = 0; j < 2; j++ )
		{
			double base = pow( 2.0, -0.25 * (j + 1.0));
			double p1 = 1.0, p2 = 1.0;

			if( i > 0 )
			{
				if( i & 1 ) p1 = pow( base,(i + 1.0) * 0.5);
				else p2 = pow( base, i * 0.5 );
			}

			pow1_1[j][i] = DOUBLE_TO_REAL_15( p1 );
			pow2_1[j][i] = DOUBLE_TO_REAL_15( p2 );
			pow1_2[j][i] = DOUBLE_TO_REAL_15( M_SQRT2 * p1 );
			pow2_2[j][i] = DOUBLE_TO_REAL_15( M_SQRT2 * p2 );
		}
	}

	for( j = 0; j < 4; j++ )
	{
		const int len[4] = { 36, 36, 12, 36 };

		for( i = 0; i < len[j]; i += 2 )
			win1[j][i] = +win[j][i];

		for( i = 1; i < len[j]; i += 2 )
			win1[j][i] = -win[j][i];
	}

	for( j = 0; j < 9; j++ )
	{
		const bandInfoStruct	*bi = &bandInfo[j];
		int			cb, lwin;
		const byte		*bdf;
		int			*mp;

		mp = map[j][0] = mapbuf0[j];
		bdf = bi->longDiff;

		for( i = 0, cb = 0; cb < 8 ; cb++, i += *bdf++ )
		{
			*mp++ = (*bdf) >> 1;
			*mp++ = i;
			*mp++ = 3;
			*mp++ = cb;
		}

		bdf = bi->shortDiff + 3;
		for( cb = 3;cb < 13; cb++ )
		{
			int l = (*bdf++) >> 1;
			for( lwin = 0; lwin < 3; lwin++ )
			{
				*mp++ = l;
				*mp++ = i + lwin;
				*mp++ = lwin;
				*mp++ = cb;
			}
			i += 6 * l;
		}

		mapend[j][0] = mp;
		mp = map[j][1] = mapbuf1[j];
		bdf = bi->shortDiff + 0;

		for( i = 0, cb = 0; cb < 13; cb++ )
		{
			int l = (*bdf++) >> 1;
			for( lwin = 0; lwin < 3; lwin++ )
			{
				*mp++ = l;
				*mp++ = i + lwin;
				*mp++ = lwin;
				*mp++ = cb;
			}
			i += 6 * l;
		}

		mapend[j][1] = mp;
		mp = map[j][2] = mapbuf2[j];
		bdf = bi->longDiff;

		for( cb = 0; cb < 22; cb++ )
		{
			*mp++ = (*bdf++) >> 1;
			*mp++ = cb;
		}
		mapend[j][2] = mp;
	}

	// now for some serious loopings!
	for( i = 0; i < 5; i++ )
	{
		for( j = 0; j < 6; j++ )
		{
			for( k = 0; k < 6; k++ )
			{
				int n = k + j * 6 + i * 36;
				i_slen2[n] = i|(j<<3)|(k<<6)|(3<<12);
			}
		}
	}

	for( i = 0; i < 4; i++ )
	{
		for( j = 0; j < 4; j++ )
		{
			for( k = 0; k < 4; k++ )
			{
				int n = k + j * 4 + i * 16;
				i_slen2[n+180] = i|(j<<3)|(k<<6)|(4<<12);
			}
		}
	}

	for( i = 0; i < 4; i++ )
	{
		for( j = 0; j < 3; j++ )
		{
			int n = j + i * 3;
			i_slen2[n+244] = i|(j<<3) | (5<<12);
			n_slen2[n+500] = i|(j<<3) | (2<<12) | (1<<15);
		}
	}

	for( i = 0; i < 5; i++ )
	{
		for( j = 0; j < 5; j++ )
		{
			for( k = 0; k < 4; k++ )
			{
				for( l = 0; l < 4; l++ )
				{
					int n = l + k * 4 + j * 16 + i * 80;
					n_slen2[n] = i|(j<<3)|(k<<6)|(l<<9)|(0<<12);
				}
			}
		}
	}

	for( i = 0; i < 5; i++ )
	{
		for( j = 0; j < 5; j++ )
		{
			for( k = 0; k < 4; k++ )
			{
				int n = k + j * 4 + i * 20;
				n_slen2[n+400] = i|(j<<3)|(k<<6)|(1<<12);
			}
		}
	}
}

void init_layer3_stuff( mpg123_handle_t *fr )
{
	int i,j;

	for( i = -256; i < 118 + 4; i++ )
		fr->gainpow2[i+256] = DOUBLE_TO_REAL_SCALE_LAYER3( pow((double)2.0, -0.25 * (double)(i + 210)), i + 256 );

	for( j = 0; j < 9; j++ )
	{
		for( i = 0; i < 23; i++ )
		{
			fr->longLimit[j][i] = (bandInfo[j].longIdx[i] - 1 + 8) / 18 + 1;

			if( fr->longLimit[j][i] > fr->down_sample_sblimit )
				fr->longLimit[j][i] = fr->down_sample_sblimit;
		}

		for( i = 0; i < 14; i++ )
		{
			fr->shortLimit[j][i] = (bandInfo[j].shortIdx[i] - 1) / 18 + 1;

			if( fr->shortLimit[j][i] > fr->down_sample_sblimit )
				fr->shortLimit[j][i] = fr->down_sample_sblimit;
		}
	}
}

// read additional side information (for MPEG 1 and MPEG 2)
static int III_get_side_info( mpg123_handle_t *fr, III_sideinfo *si, int stereo, int ms_stereo, long sfreq, int single )
{
	int	powdiff = (single == SINGLE_MIX) ? 4 : 0;
	const int	tabs[2][5] = { { 2,9,5,3,4 } , { 1,8,1,2,9 } };
	const int	*tab = tabs[fr->lsf];
	int	ch, gr;

	si->main_data_begin = getbits( fr, tab[1] );

	if( si->main_data_begin > fr->bitreservoir )
	{
		//  overwrite main_data_begin for the floatly available bit reservoir
		backbits( fr, tab[1] );

		if( fr->lsf == 0 )
		{
			fr->wordpointer[0] = (byte)(fr->bitreservoir >> 1);
			fr->wordpointer[1] = (byte)((fr->bitreservoir & 1) << 7);
		}
		else fr->wordpointer[0] = (byte)fr->bitreservoir;

		// zero "side-info" data for a silence-frame
		// without touching audio data used as bit reservoir for following frame
		memset( fr->wordpointer + 2, 0, fr->ssize - 2 );

		// reread the new bit reservoir offset
		si->main_data_begin = getbits( fr, tab[1] );
	}

	// keep track of the available data bytes for the bit reservoir.
	// think: Substract the 2 crc bytes in parser already?
	fr->bitreservoir = fr->bitreservoir + fr->framesize - fr->ssize - (fr->error_protection ? 2 : 0);
	// limit the reservoir to the max for MPEG 1.0 or 2.x.
	if( fr->bitreservoir > (uint)(fr->lsf == 0 ? 511 : 255 ))
		fr->bitreservoir = (fr->lsf == 0 ? 511 : 255);

	// now back into less commented territory. It's code. It works.

	if( stereo == 1 ) si->private_bits = getbits_fast( fr, tab[2] );
	else si->private_bits = getbits_fast( fr, tab[3] );

	if( !fr->lsf )
	{
		for( ch = 0; ch < stereo; ch++ )
		{
			si->ch[ch].gr[0].scfsi = -1;
			si->ch[ch].gr[1].scfsi = getbits_fast( fr, 4 );
		}
	}

	for( gr = 0; gr < tab[0]; gr++ )
	{
		for( ch = 0; ch < stereo; ch++ )
		{
			register gr_info_t	*gr_info = &( si->ch[ch].gr[gr] );

			gr_info->part2_3_length = getbits( fr, 12 );
			gr_info->big_values = getbits( fr, 9 );

			if( gr_info->big_values > 288 )
				gr_info->big_values = 288;

			gr_info->pow2gain = fr->gainpow2 + 256 - getbits_fast( fr, 8 ) + powdiff;
			if( ms_stereo ) gr_info->pow2gain += 2;

			gr_info->scalefac_compress = getbits( fr, tab[4] );

			if( get1bit( fr ))
			{
				int	i;

				// window switch flag
				gr_info->block_type = getbits_fast( fr, 2 );
				gr_info->mixed_block_flag = get1bit( fr );
				gr_info->table_select[0] = getbits_fast( fr, 5 );
				gr_info->table_select[1] = getbits_fast( fr, 5 );

				// table_select[2] not needed, because there is no region2,
				// but to satisfy some verification tools we set it either.
				gr_info->table_select[2] = 0;

				for( i = 0; i < 3; i++ )
					gr_info->full_gain[i] = gr_info->pow2gain + (getbits_fast( fr, 3 ) << 3);

				if( gr_info->block_type == 0 )
					return 1;

				// region_count/start parameters are implicit in this case.
				if(( !fr->lsf || ( gr_info->block_type == 2 )) && !fr->mpeg25 )
				{
					gr_info->region1start = 36 >> 1;
					gr_info->region2start = 576 >> 1;
				}
				else
				{
					if( fr->mpeg25 )
					{
						int	r0c, r1c;

						if(( gr_info->block_type == 2 ) && ( !gr_info->mixed_block_flag ))
							r0c = 5;
						else r0c = 7;

						// r0c + 1 + r1c + 1 == 22, always.
						r1c = 20 - r0c;
						gr_info->region1start = bandInfo[sfreq].longIdx[r0c+1] >> 1 ;
						gr_info->region2start = bandInfo[sfreq].longIdx[r0c+1+r1c+1] >> 1;
					}
					else
					{
						gr_info->region1start = 54 >> 1;
						gr_info->region2start = 576 >> 1;
					}
				}
			}
			else
			{
				int	i, r0c, r1c;

				for( i = 0; i < 3; i++ )
					gr_info->table_select[i] = getbits_fast( fr, 5 );

				r0c = getbits_fast( fr, 4 ); // 0 .. 15
				r1c = getbits_fast( fr, 3 ); // 0 .. 7
				gr_info->region1start = bandInfo[sfreq].longIdx[r0c+1] >> 1 ;

				// max( r0c + r1c + 2 ) = 15 + 7 + 2 = 24
				if( r0c + 1 + r1c + 1 > 22 )
					gr_info->region2start = 576 >> 1;
				else gr_info->region2start = bandInfo[sfreq].longIdx[r0c+1+r1c+1] >> 1;

				gr_info->block_type = 0;
				gr_info->mixed_block_flag = 0;
			}

			if( !fr->lsf )
				gr_info->preflag = get1bit( fr );

			gr_info->scalefac_scale = get1bit( fr );
			gr_info->count1table_select = get1bit( fr );
		}
	}

	return 0;
}

// read scalefactors
static int III_get_scale_factors_1( mpg123_handle_t *fr, int *scf, gr_info_t *gr_info )
{
	const byte 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 }
	};
	int	num0 = slen[0][gr_info->scalefac_compress];
	int	num1 = slen[1][gr_info->scalefac_compress];
	int	numbits;

	if( gr_info->block_type == 2 )
	{
		int i = 18;
		numbits = (num0 + num1) * 18;

		if( gr_info->mixed_block_flag )
		{
			for( i = 8; i; i-- )
				*scf++ = getbits_fast( fr, num0 );

			i = 9;
			numbits -= num0; // num0 * 17 + num1 * 18
		}

		for( ; i; i-- )
			*scf++ = getbits_fast( fr, num0 );

		for( i = 18; i; i-- )
			*scf++ = getbits_fast( fr, num1 );

		// short[13][0..2] = 0
		*scf++ = 0;
		*scf++ = 0;
		*scf++ = 0;
	}
	else
	{
		int	i, scfsi = gr_info->scfsi;

		if( scfsi < 0 )
		{
			// scfsi < 0 => granule == 0
			for( i = 11; i; i-- )
				*scf++ = getbits_fast( fr, num0 );

			for( i = 10; i; i-- )
				*scf++ = getbits_fast( fr, num1 );

			numbits = (num0 + num1) * 10 + num0;
			*scf++ = 0;
		}
		else
		{
			numbits = 0;

			if(!( scfsi & 0x8 ))
			{
				for( i = 0; i < 6; i++ )
					*scf++ = getbits_fast( fr, num0 );

				numbits += num0 * 6;
			}
			else scf += 6;

			if(!( scfsi & 0x4 ))
			{
				for( i = 0; i < 5; i++ )
					*scf++ = getbits_fast( fr, num0 );

				numbits += num0 * 5;
			}
			else scf += 5;

			if(!( scfsi & 0x2 ))
			{
				for( i = 0; i < 5; i++ )
					*scf++ = getbits_fast( fr, num1 );

				numbits += num1 * 5;
			}
			else scf += 5;

			if(!( scfsi & 0x1 ))
			{
				for( i = 0; i < 5; i++ )
					*scf++ = getbits_fast( fr, num1 );

				numbits += num1 * 5;
			}
			else scf += 5;

			// no l[21] in original sources
			*scf++ = 0;
		}
	}

	return numbits;
}

static int III_get_scale_factors_2( mpg123_handle_t *fr, int *scf, gr_info_t *gr_info, int i_stereo )
{
	const byte	*pnt;
	int		i, j, n = 0;
	int		numbits = 0;
	uint		slen;

	const byte stab[3][6][4] =
	{
	{
	{ 6, 5, 5,5 } , { 6, 5, 7,3 } , { 11,10,0,0},
	{ 7, 7, 7,0 } , { 6, 6, 6,3 } , {  8, 8,5,0}
	},
	{
	{ 9, 9, 9,9 } , { 9, 9,12,6 } , { 18,18,0,0},
	{12,12,12,0 } , {12, 9, 9,6 } , { 15,12,9,0}
	},
	{
	{ 6, 9, 9,9 } , { 6, 9,12,6 } , { 15,18,0,0},
	{ 6,15,12,0 } , { 6,12, 9,6 } , {  6,18,9,0}
	}
	};

	// i_stereo AND second channel -> do_layer3() checks this
	if( i_stereo ) slen = i_slen2[gr_info->scalefac_compress>>1];
	else slen = n_slen2[gr_info->scalefac_compress];

	gr_info->preflag = (slen >> 15) & 0x1;
	n = 0;

	if( gr_info->block_type == 2 )
	{
		if( gr_info->mixed_block_flag )
			n++;
		n++;
	}

	pnt = stab[n][(slen>>12)&0x7];

	for( i = 0; i < 4; i++ )
	{
		int	num = slen & 0x7;

		slen >>= 3;
		if( num )
		{
			for( j = 0; j < (int)(pnt[i]); j++ )
				*scf++ = getbits_fast( fr, num );
			numbits += pnt[i] * num;
		}
		else
		{
			for( j = 0; j < (int)(pnt[i]); j++ )
				*scf++ = 0;
		}
	}

	n = (n << 1) + 1;

	for( i = 0; i < n; i++ )
		*scf++ = 0;

	return numbits;
}

/* 24 is enough because tab13 has max. a 19 bit huffvector */
/* The old code played games with shifting signed integers around in not quite */
/* legal ways. Also, it used long where just 32 bits are required. This could */
/* be good or bad on 64 bit architectures ... anyway, making clear that */
/* 32 bits suffice is a benefit. */
#if 0
/* To reconstruct old code, use this: */
#define MASK_STYPE long
#define MASK_UTYPE unsigned long
#define MASK_TYPE MASK_STYPE
#define MSB_MASK (mask < 0)
#else
/* This should be more proper: */
#define MASK_STYPE int32_t
#define MASK_UTYPE uint32_t
#define MASK_TYPE  MASK_UTYPE
#define MSB_MASK ((MASK_UTYPE)mask & (MASK_UTYPE)1<<(sizeof(MASK_TYPE)*8-1))
#endif

// 24 is enough because tab13 has max. a 19 bit huffvector
#define BITSHIFT	((sizeof(MASK_TYPE) - 1) * 8)

#define REFRESH_MASK \
	while( num < BITSHIFT ) { \
		mask |= ((MASK_UTYPE)getbyte( fr )) << (BITSHIFT - num); \
		num += 8; \
		part2remain -= 8; }

static int III_dequantize_sample( mpg123_handle_t *fr, float xr[SBLIMIT][SSLIMIT], int *scf, gr_info_t *gr_info, int sfreq, int part2bits )
{
	int	shift = 1 + gr_info->scalefac_scale;
	int	part2remain = gr_info->part2_3_length - part2bits;
	int	region1 = gr_info->region1start;
	int	region2 = gr_info->region2start;
	int	bv = gr_info->big_values;
	int	num = getbitoffset( fr );
	float	*xrpnt = (float *)xr;
	int	l[3], l3;
	MASK_TYPE mask;
	int	*me;

	// we must split this, because for num == 0 the shift is undefined if you do it in one step.
	mask  = ((MASK_UTYPE)getbits( fr, num )) << BITSHIFT;
	mask <<= 8 - num;
	part2remain -= num;

	l3 = ((576>>1)-bv)>>1;

	// we may lose the 'odd' bit here !! check this later again
	if( bv <= region1 )
	{
		l[0] = bv;
		l[1] = 0;
		l[2] = 0;
	}
	else
	{
		l[0] = region1;

		if( bv <= region2 )
		{
			l[1] = bv - l[0];
			l[2] = 0;
		}
		else
		{
			l[1] = region2 - l[0];
			l[2] = bv - region2;
		}
	}

	if( gr_info->block_type == 2 )
	{
		int		i, max[4];
		int		step = 0;
		int		lwin = 3;
		register float	v = 0.0f;
		int		cb = 0;
		register int	*m, mc;
		int		rmax;

		// decoding with short or mixed mode BandIndex table
		if( gr_info->mixed_block_flag )
		{
			max[3] = -1;
			max[0] = max[1] = max[2] = 2;
			m = map[sfreq][0];
			me = mapend[sfreq][0];
		}
		else
		{
			max[0] = max[1] = max[2] = max[3] = -1;
			// max[3] not floatly needed in this case
			m = map[sfreq][1];
			me = mapend[sfreq][1];
		}

		mc = 0;

		for( i = 0; i < 2; i++ )
		{
			const struct newhuff	*h = ht + gr_info->table_select[i];
			int			lp = l[i];

			for( ; lp; lp--, mc-- )
			{
				register MASK_STYPE x, y;

				if( (!mc) )
				{
					mc = *m++;
					xrpnt = ((float *)xr) + (*m++);
					lwin = *m++;
					cb = *m++;

					if( lwin == 3 )
					{
						v = gr_info->pow2gain[(*scf++) << shift];
						step = 1;
					}
					else
					{
						v = gr_info->full_gain[lwin][(*scf++) << shift];
						step = 3;
					}
				}
				{
					const short *val = h->table;
					REFRESH_MASK;

					while(( y = *val++ ) < 0 )
					{
						if( MSB_MASK )
							val -= y;

						num--;
						mask <<= 1;
					}
					x = y >> 4;
					y &= 0xf;
				}

				if( x == 15 && h->linbits )
				{
					max[lwin] = cb;
					REFRESH_MASK;

					x += ((MASK_UTYPE)mask) >> (BITSHIFT + 8 - h->linbits);
					num -= h->linbits + 1;
					mask <<= h->linbits;

					if( MSB_MASK ) *xrpnt = REAL_MUL_SCALE_LAYER3( -ispow[x], v );
					else *xrpnt = REAL_MUL_SCALE_LAYER3( ispow[x], v );

					mask <<= 1;
				}
				else if( x )
				{
					max[lwin] = cb;

					if( MSB_MASK ) *xrpnt = REAL_MUL_SCALE_LAYER3( -ispow[x], v );
					else *xrpnt = REAL_MUL_SCALE_LAYER3( ispow[x], v );

					num--;
					mask <<= 1;
				}
				else *xrpnt = DOUBLE_TO_REAL(0.0);

				xrpnt += step;

				if( y == 15 && h->linbits )
				{
					max[lwin] = cb;
					REFRESH_MASK;

					y += ((MASK_UTYPE) mask) >> (BITSHIFT + 8 - h->linbits);
					num -= h->linbits + 1;
					mask <<= h->linbits;

					if( MSB_MASK ) *xrpnt = REAL_MUL_SCALE_LAYER3( -ispow[y], v );
					else *xrpnt = REAL_MUL_SCALE_LAYER3( ispow[y], v );

					mask <<= 1;
				}
				else if( y )
				{
					max[lwin] = cb;

					if( MSB_MASK ) *xrpnt = REAL_MUL_SCALE_LAYER3( -ispow[y], v );
					else *xrpnt = REAL_MUL_SCALE_LAYER3( ispow[y], v );

					num--;
					mask <<= 1;
				}
				else *xrpnt = DOUBLE_TO_REAL(0.0);

				xrpnt += step;
			}
		}

		for( ; l3 && (part2remain + num > 0); l3-- )
		{
			const struct newhuff	*h;
			const short		*val;
			register short		a;

			// this is only a humble hack to prevent a special segfault.
			// more insight into the float workings is still needed.
			// especially why there are (valid?) files that make xrpnt exceed the array with 4 bytes without segfaulting
			// more seems to be floatly bad, though.

			if(!( xrpnt < &xr[SBLIMIT][0] + 5 ))
				return 2;

			h = htc + gr_info->count1table_select;
			val = h->table;

			REFRESH_MASK;

			while(( a = *val++ ) < 0 )
			{
				if( MSB_MASK )
					val -= a;

				num--;
				mask <<= 1;
			}

			if( part2remain + num <= 0 )
			{
				num -= part2remain + num;
				break;
			}

			for( i = 0; i < 4; i++ )
			{
				if(!( i & 1 ))
				{
					if( !mc )
					{
						mc = *m++;
						xrpnt = ((float *)xr) + (*m++);
						lwin = *m++;
						cb = *m++;

						if( lwin == 3 )
						{
							v = gr_info->pow2gain[(*scf++) << shift];
							step = 1;
						}
						else
						{
							v = gr_info->full_gain[lwin][(*scf++) << shift];
							step = 3;
						}
					}
					mc--;
				}

				if(( a & ( 0x8 >> i )))
				{
					max[lwin] = cb;

					if( part2remain + num <= 0 )
						break;

					if( MSB_MASK ) *xrpnt = -REAL_SCALE_LAYER3( v );
					else *xrpnt =  REAL_SCALE_LAYER3( v );

					num--;
					mask <<= 1;
				}
				else *xrpnt = DOUBLE_TO_REAL( 0.0 );

				xrpnt += step;
			}
		}

		if( lwin < 3 )
		{
			// short band?
			while( 1 )
			{
				for( ; mc > 0; mc-- )
				{
					*xrpnt = DOUBLE_TO_REAL( 0.0 );
					xrpnt += 3; // short band -> step = 3
					*xrpnt = DOUBLE_TO_REAL( 0.0 );
					xrpnt += 3;
				}

				if( m >= me ) break;

				mc = *m++;
				xrpnt = ((float *)xr) + *m++;
				if( *m++ == 0 ) break; // optimize: field will be set to zero at the end of the function

				m++; // cb
			}
		}

		gr_info->maxband[0] = max[0]+1;
		gr_info->maxband[1] = max[1]+1;
		gr_info->maxband[2] = max[2]+1;
		gr_info->maxbandl   = max[3]+1;

		rmax = max[0] > max[1] ? max[0] : max[1];
		rmax = (rmax > max[2] ? rmax : max[2]) + 1;
		gr_info->maxb = rmax ? fr->shortLimit[sfreq][rmax] : fr->longLimit[sfreq][max[3]+1];
	}
	else
	{
		// decoding with 'long' BandIndex table (block_type != 2)
		const byte	*pretab = pretab_choice[gr_info->preflag];
		int		*m = map[sfreq][2];
		int		i,max = -1;
		int		cb = 0;
		register float	v = 0.0;
		int		mc = 0;

		// long hash table values
		for( i = 0; i < 3; i++ )
		{
			const struct newhuff	*h = ht + gr_info->table_select[i];
			int			lp = l[i];

			for( ; lp; lp--, mc-- )
			{
				MASK_STYPE	x, y;

				if( !mc )
				{
					mc = *m++;
					cb = *m++;
					v = gr_info->pow2gain[(*(scf++) + (*pretab++)) << shift];
				}
				{
					const short *val = h->table;
					REFRESH_MASK;

					while(( y = *val++ ) < 0 )
					{
						if( MSB_MASK )
							val -= y;

						num--;
						mask <<= 1;
					}

					x = y >> 4;
					y &= 0xf;
				}

				if( x == 15 && h->linbits )
				{
					max = cb;
					REFRESH_MASK;

					x += ((MASK_UTYPE)mask) >> (BITSHIFT + 8 - h->linbits);
					num -= h->linbits+1;
					mask <<= h->linbits;

					if( MSB_MASK ) *xrpnt++ = REAL_MUL_SCALE_LAYER3(-ispow[x], v );
					else *xrpnt++ = REAL_MUL_SCALE_LAYER3( ispow[x], v );

					mask <<= 1;
				}
				else if( x )
				{
					max = cb;

					if( MSB_MASK ) *xrpnt++ = REAL_MUL_SCALE_LAYER3( -ispow[x], v );
					else *xrpnt++ = REAL_MUL_SCALE_LAYER3( ispow[x], v );
					num--;

					mask <<= 1;
				}
				else *xrpnt++ = DOUBLE_TO_REAL( 0.0 );

				if( y == 15 && h->linbits )
				{
					max = cb;
					REFRESH_MASK;
					y += ((MASK_UTYPE)mask) >> (BITSHIFT + 8 - h->linbits);
					num -= h->linbits+1;
					mask <<= h->linbits;

					if( MSB_MASK ) *xrpnt++ = REAL_MUL_SCALE_LAYER3( -ispow[y], v );
					else *xrpnt++ = REAL_MUL_SCALE_LAYER3( ispow[y], v );

					mask <<= 1;
				}
				else if( y )
				{
					max = cb;
					if( MSB_MASK ) *xrpnt++ = REAL_MUL_SCALE_LAYER3( -ispow[y], v );
					else *xrpnt++ = REAL_MUL_SCALE_LAYER3( ispow[y], v );

					num--;
					mask <<= 1;
				}
				else *xrpnt++ = DOUBLE_TO_REAL( 0.0 );
			}
		}

		// short (count1table) values
		for( ; l3 && (part2remain + num > 0); l3-- )
		{
			const struct newhuff	*h = htc+gr_info->count1table_select;
			const short		*val = h->table;
			register short		a;

			REFRESH_MASK;
			while(( a = *val++ ) < 0 )
			{
				if( MSB_MASK )
					val -= a;

				num--;
				mask <<= 1;
			}

			if( part2remain + num <= 0 )
			{
				num -= part2remain + num;
				break;
			}

			for( i = 0; i < 4; i++ )
			{
				if(!( i & 1 ))
				{
					if( !mc )
					{
						mc = *m++;
						cb = *m++;

						v = gr_info->pow2gain[((*scf++) + (*pretab++)) << shift];
					}
					mc--;
				}

				if(( a & (0x8 >> i)))
				{
					max = cb;
					if( part2remain + num <= 0 )
						break;

					if( MSB_MASK ) *xrpnt++ = -REAL_SCALE_LAYER3( v );
					else *xrpnt++ = REAL_SCALE_LAYER3( v );

					num--;
					mask <<= 1;
				}
				else *xrpnt++ = DOUBLE_TO_REAL( 0.0 );
			}
		}

		gr_info->maxbandl = max+1;
		gr_info->maxb = fr->longLimit[sfreq][gr_info->maxbandl];
	}

	part2remain += num;
	backbits( fr, num );
	num = 0;

	while( xrpnt < &xr[SBLIMIT][0] )
		*xrpnt++ = DOUBLE_TO_REAL( 0.0 );

	while( part2remain > 16 )
	{
		skipbits( fr, 16 ); // dismiss stuffing Bits
		part2remain -= 16;
	}

	if( part2remain > 0 )
	{
		skipbits( fr, part2remain );
	}
	else if( part2remain < 0 )
	{
		// error
		return 1;
	}

	return 0;
}

// calculate float channel values for Joint-I-Stereo-mode
static void III_i_stereo( float xr_buf[2][SBLIMIT][SSLIMIT], int *scalefac, gr_info_t *gr_info, int sfreq, int ms_stereo, int lsf )
{
	float (*xr)[SBLIMIT*SSLIMIT] = (float(*)[SBLIMIT*SSLIMIT])xr_buf;
	const bandInfoStruct *bi = &bandInfo[sfreq];
	const float *tab1, *tab2;
	int tab;

	// TODO: optimize as static
	const float *tabs[3][2][2] =
	{
	{ { tan1_1,tan2_1 }       , { tan1_2,tan2_2 } },
	{ { pow1_1[0],pow2_1[0] } , { pow1_2[0],pow2_2[0] } },
	{ { pow1_1[1],pow2_1[1] } , { pow1_2[1],pow2_2[1] } }
	};

	tab = lsf + (gr_info->scalefac_compress & lsf);
	tab1 = tabs[tab][ms_stereo][0];
	tab2 = tabs[tab][ms_stereo][1];

	if( gr_info->block_type == 2 )
	{
		int	lwin, do_l = 0;

		if( gr_info->mixed_block_flag )
			do_l = 1;

		for( lwin = 0; lwin < 3; lwin++ )
		{
			int	is_p, sb, idx;
			int	sfb = gr_info->maxband[lwin];  // sfb is minimal 3 for mixed mode

			if( sfb > 3 ) do_l = 0;

			// process each window
			// get first band with zero values
			for( ; sfb < 12; sfb++ )
			{
				is_p = scalefac[sfb * 3 + lwin - gr_info->mixed_block_flag]; // scale: 0-15

				if( is_p != 7 )
				{
					float	t1, t2;

					sb = bi->shortDiff[sfb];
					idx = bi->shortIdx[sfb] + lwin;
					t1 = tab1[is_p];
					t2 = tab2[is_p];

					for( ; sb > 0; sb--, idx += 3 )
					{
						float v = xr[0][idx];
						xr[0][idx] = REAL_MUL_15( v, t1 );
						xr[1][idx] = REAL_MUL_15( v, t2 );
					}
				}
			}

			// in the original: copy 10 to 11 , here: copy 11 to 12
			// maybe still wrong??? (copy 12 to 13?)
			is_p = scalefac[11 * 3 + lwin - gr_info->mixed_block_flag]; // scale: 0-15
			sb = bi->shortDiff[12];
			idx  = bi->shortIdx[12] + lwin;

			if( is_p != 7 )
			{
				float	t1, t2;

				t1 = tab1[is_p];
				t2 = tab2[is_p];

				for( ; sb > 0; sb--, idx += 3 )
				{
					float v = xr[0][idx];
					xr[0][idx] = REAL_MUL_15( v, t1 );
					xr[1][idx] = REAL_MUL_15( v, t2 );
				}
			}
		}

		// also check l-part, if ALL bands in the three windows are 'empty' and mode = mixed_mode
		if( do_l )
		{
			int	idx, sfb = gr_info->maxbandl;

			if( sfb > 21 ) return; // similarity fix related to CVE-2006-1655

			idx = bi->longIdx[sfb];

			for( ; sfb < 8; sfb++ )
			{
				int	sb = bi->longDiff[sfb];
				int	is_p = scalefac[sfb]; // scale: 0-15

				if( is_p != 7 )
				{
					float	t1, t2;

					t1 = tab1[is_p];
					t2 = tab2[is_p];

					for( ; sb > 0; sb--, idx++ )
					{
						float v = xr[0][idx];
						xr[0][idx] = REAL_MUL_15( v, t1 );
						xr[1][idx] = REAL_MUL_15( v, t2 );
					}
				}
				else idx += sb;
			}
		}
	}
	else
	{
		int	sfb = gr_info->maxbandl;
		int	is_p, idx;

		if( sfb > 21 ) return; // tightened fix for CVE-2006-1655

		idx = bi->longIdx[sfb];

		for( ; sfb < 21; sfb++ )
		{
			int	sb = bi->longDiff[sfb];

			is_p = scalefac[sfb]; // scale: 0-15

			if( is_p != 7 )
			{
				float	t1, t2;

				t1 = tab1[is_p];
				t2 = tab2[is_p];

				for( ; sb > 0; sb--, idx++ )
				{
					 float v = xr[0][idx];
					 xr[0][idx] = REAL_MUL_15( v, t1 );
					 xr[1][idx] = REAL_MUL_15( v, t2 );
				}
			}
			else idx += sb;
		}

		is_p = scalefac[20];

		if( is_p != 7 )
		{
			float	t1, t2;
			int	sb;

			t1 = tab1[is_p],
			t2 = tab2[is_p];

			// copy l-band 20 to l-band 21
			for( sb = bi->longDiff[21]; sb > 0; sb--, idx++ )
			{
				float v = xr[0][idx];
				xr[0][idx] = REAL_MUL_15( v, t1 );
				xr[1][idx] = REAL_MUL_15( v, t2 );
			}
		}
	}
}

static void III_antialias( float xr[SBLIMIT][SSLIMIT], gr_info_t *gr_info )
{
	int	sblim, sb;
	float	*xr1;

	if( gr_info->block_type == 2 )
	{
		if( !gr_info->mixed_block_flag )
			return;
		sblim = 1;
	}
	else
	{
		sblim = gr_info->maxb-1;
	}

	// 31 alias-reduction operations between each pair of sub-bands
	// with 8 butterflies between each pair
	xr1 = (float *)xr[1];

	for( sb = sblim; sb; sb--, xr1 += 10 )
	{
		float	*cs = aa_cs;
		float	*ca = aa_ca;
		float	*xr2 = xr1;
		int	ss;

		for( ss = 7; ss >= 0; ss-- )
		{
			// upper and lower butterfly inputs
			register float bu = *--xr2;
			register float bd = *xr1;

			*xr2 = REAL_MUL( bu, *cs ) - REAL_MUL( bd, *ca );
			*xr1++ = REAL_MUL( bd, *cs++ ) + REAL_MUL( bu, *ca++ );
		}
	}
}

static void III_hybrid( float fsIn[SBLIMIT][SSLIMIT], float tsOut[SSLIMIT][SBLIMIT], int ch, gr_info_t *gr_info, mpg123_handle_t *fr )
{
	float	(*block)[2][SBLIMIT*SSLIMIT] = fr->hybrid_block;
	int	*blc = fr->hybrid_blc;
	float	*tspnt = (float *)tsOut;
	float	*rawout1, *rawout2;
	int	bt = 0, b, i;
	size_t	sb = 0;

	b = blc[ch];
	rawout1 = block[b][ch];
	b=-b + 1;
	rawout2 = block[b][ch];
	blc[ch] = b;

	if( gr_info->mixed_block_flag )
	{
		sb = 2;
		dct36( fsIn[0], rawout1, rawout2, win[0], tspnt );
		dct36( fsIn[1], rawout1+18, rawout2+18, win1[0], tspnt + 1 );
		rawout1 += 36; rawout2 += 36; tspnt += 2;
	}

	bt = gr_info->block_type;

	if( bt == 2 )
	{
		for( ; sb < gr_info->maxb; sb += 2, tspnt += 2, rawout1 += 36, rawout2 += 36 )
		{
			dct12( fsIn[sb], rawout1, rawout2, win[2], tspnt );
			dct12( fsIn[sb+1], rawout1 + 18, rawout2 + 18, win1[2], tspnt + 1 );
		}
	}
	else
	{
		for( ; sb < gr_info->maxb; sb += 2, tspnt += 2, rawout1 += 36, rawout2 += 36 )
		{
			dct36( fsIn[sb], rawout1, rawout2, win[bt], tspnt );
			dct36( fsIn[sb+1], rawout1 + 18, rawout2 + 18, win1[bt], tspnt + 1 );
		}
	}

	for( ; sb < SBLIMIT; sb++, tspnt++ )
	{
		for( i = 0; i < SSLIMIT; i++ )
		{
			tspnt[i*SBLIMIT] = *rawout1++;
			*rawout2++ = DOUBLE_TO_REAL( 0.0 );
		}
	}
}

// and at the end... the main layer3 handler
int do_layer3( mpg123_handle_t *fr )
{
	int		gr, ch, ss, clip = 0;
	int		stereo = fr->stereo;
	int		single = fr->single;
	int		ms_stereo, i_stereo;
	int		sfreq = fr->sampling_frequency;
	int		scalefacs[2][39]; // max 39 for short[13][3] mode, mixed: 38, long: 22
	int		stereo1, granules;
	III_sideinfo	sideinfo;

	if( stereo == 1 )
	{
		// stream is mono
		stereo1 = 1;
		single = SINGLE_LEFT;
	}
	else if( single != SINGLE_STEREO )
	{
		// stream is stereo, but force to mono
		stereo1 = 1;
	}
	else
	{
		stereo1 = 2;
	}

	if( fr->mode == MPG_MD_JOINT_STEREO )
	{
		ms_stereo = (fr->mode_ext & 0x2) >> 1;
		i_stereo  = fr->mode_ext & 0x1;
	}
	else
	{
		ms_stereo = i_stereo = 0;
	}

	granules = fr->lsf ? 1 : 2;

	// quick hack to keep the music playing
	// after having seen this nasty test file...
	if( III_get_side_info( fr, &sideinfo, stereo, ms_stereo, sfreq, single ))
		return clip;

	set_pointer( fr, sideinfo.main_data_begin );

	for( gr = 0; gr < granules; gr++ )
	{
		float	(*hybridIn)[SBLIMIT][SSLIMIT] = fr->layer3.hybrid_in;	//  hybridIn[2][SBLIMIT][SSLIMIT]
		float	(*hybridOut)[SSLIMIT][SBLIMIT] = fr->layer3.hybrid_out;	//  hybridOut[2][SSLIMIT][SBLIMIT]
		gr_info_t	*gr_info = &(sideinfo.ch[0].gr[gr]);
		long	part2bits;

		if( fr->lsf ) part2bits = III_get_scale_factors_2( fr, scalefacs[0], gr_info, 0 );
		else part2bits = III_get_scale_factors_1( fr, scalefacs[0], gr_info );

		if( III_dequantize_sample( fr, hybridIn[0], scalefacs[0], gr_info, sfreq, part2bits ))
			return clip;

		if( stereo == 2 )
		{
			register float	*in0, *in1;
			register int	i;

			gr_info = &(sideinfo.ch[1].gr[gr]);

			if( fr->lsf ) part2bits = III_get_scale_factors_2( fr, scalefacs[1], gr_info, i_stereo );
			else part2bits = III_get_scale_factors_1( fr, scalefacs[1], gr_info );

			if( III_dequantize_sample( fr, hybridIn[1], scalefacs[1], gr_info, sfreq, part2bits ))
				return clip;

			if( ms_stereo )
			{
				uint	maxb = sideinfo.ch[0].gr[gr].maxb;
				int	i;

				if( sideinfo.ch[1].gr[gr].maxb > maxb )
					maxb = sideinfo.ch[1].gr[gr].maxb;

				for( i = 0; i < SSLIMIT * (int)maxb; i++ )
				{
					float tmp0 = ((float *)hybridIn[0])[i];
					float tmp1 = ((float *)hybridIn[1])[i];
					((float *)hybridIn[0])[i] = tmp0 + tmp1;
					((float *)hybridIn[1])[i] = tmp0 - tmp1;
				}
			}

			if( i_stereo )
				III_i_stereo( hybridIn, scalefacs[1], gr_info, sfreq, ms_stereo, fr->lsf );

			if( ms_stereo || i_stereo || ( single == SINGLE_MIX ))
			{
				if( gr_info->maxb > sideinfo.ch[0].gr[gr].maxb )
					sideinfo.ch[0].gr[gr].maxb = gr_info->maxb;
				else gr_info->maxb = sideinfo.ch[0].gr[gr].maxb;
			}

			switch( single )
			{
			case SINGLE_MIX:
				in0 = (float *)hybridIn[0];
				in1 = (float *)hybridIn[1];

				for( i = 0; i < SSLIMIT * (int)gr_info->maxb; i++, in0++ )
					*in0 = (*in0 + *in1++); // *0.5 done by pow-scale
				break;
			case SINGLE_RIGHT:
				in0 = (float *)hybridIn[0];
				in1 = (float *)hybridIn[1];

				for( i = 0; i < SSLIMIT * (int)gr_info->maxb; i++ )
					*in0++ = *in1++;
				break;
			}
		}

		for( ch = 0; ch < stereo1; ch++ )
		{
			gr_info = &(sideinfo.ch[ch].gr[gr]);
			III_antialias( hybridIn[ch], gr_info );
			III_hybrid( hybridIn[ch], hybridOut[ch], ch,gr_info, fr );
		}

		for( ss = 0; ss < SSLIMIT; ss++ )
		{
			if( single != SINGLE_STEREO )
				clip += (fr->synth_mono)(hybridOut[0][ss], fr );
			else clip += (fr->synth_stereo)(hybridOut[0][ss], hybridOut[1][ss], fr );

		}
	}

	return clip;
}