/* this file is a part of amp software, (C) tomislav uzelac 1996,1997
 */

/* layer3.c  layer3 audio decoding

 * Created by: tomislav uzelac  Mar  1 97
 * Last modified by: 
 */
#include "amp.h"
#include "audio.h"
#include "dump.h"
#include "getbits.h"
#include "getdata.h"
#include "huffman.h"
#include "misc2.h"
#include "rtbuf.h"
#include "transform.h"

#define LAYER3
#include "layer3.h"

/* this function decodes one layer3 audio frame, except for the header decoding
 * which is done in main() [audio.c]. returns 0 if everything is ok.
 */
int layer3_frame(struct AUDIO_HEADER *header, int cnt)
{
	static struct SIDE_INFO info;

	int gr, ch, sb, i;
	int mean_frame_size, bitrate, fs, hsize, ssize;

/* we need these later, hsize is the size of header+side_info
 */
	if (header->ID)
		if (header->mode == 3) {
			nch = 1;
			hsize = 21;
		} else {
			nch = 2;
			hsize = 36;
	} else if (header->mode == 3) {
		nch = 1;
		hsize = 13;
	} else {
		nch = 2;
		hsize = 21;
	}

/* crc increases hsize by 2
 */
	if (header->protection_bit == 0)
		hsize += 2;


/* read layer3 specific side_info
 */
	getinfo(header, &info);


/* MPEG2 only has one granule
 */
	bitrate = t_bitrate[header->ID][3 - header->layer][header->bitrate_index];
	fs = t_sampling_frequency[header->ID][header->sampling_frequency];
	if (header->ID)
		mean_frame_size = 144000 * bitrate / fs;
	else
		mean_frame_size = 72000 * bitrate / fs;


/* check if mdb is too big for the first few frames. this means that
 * a part of the stream could be missing. We must still fill the buffer
 *
 * don't forget to (re)initialise bclean_bytes to 0, and f_bdirty to FALSE!!!
 */
	if (f_bdirty)
		if (info.main_data_begin > bclean_bytes) {
			fillbfr(mean_frame_size + header->padding_bit - hsize);
			bclean_bytes += mean_frame_size + header->padding_bit - hsize;
			/* warn(" frame %d discarded, incomplete main_data\n",cnt); */
			return 0;
		} else {
			/* re-initialise */
			f_bdirty = FALSE;
			bclean_bytes = 0;
		}
/* now update the data 'pointer' (counting in bits) according to
 * the main_data_begin information
 */
	data = 8 * ((append - info.main_data_begin) & (BUFFER_SIZE - 1));


/* read into the buffer all bytes up to the start of next header
 */
	fillbfr(mean_frame_size + header->padding_bit - hsize);


/* these two should go away
 */
	t_l = &t_b8_l[header->ID][header->sampling_frequency][0];
	t_s = &t_b8_s[header->ID][header->sampling_frequency][0];

/* debug/dump stuff
 */
	if (A_DUMP_BINARY)
		dump((int *) info.part2_3_length);

/* decode the scalefactors and huffman data
 * this part needs to be enhanced for error robustness
 */
	for (gr = 0; gr < ((header->ID) ? 2 : 1); gr++) {
		for (ch = 0; ch < nch; ch++) {
			ssize = decode_scalefactors(&info, header, gr, ch);
			decode_huffman_data(&info, gr, ch, ssize);
		}

		/* requantization, stereo processing, reordering(shortbl)
		 */

		if (A_DOWNMIX && nch == 2)
			requantize_downmix(gr, &info, header);
		else if (header->mode != 1 || (header->mode == 1 && header->mode_extension == 0))
			for (ch = 0; ch < nch; ch++)
				requantize_mono(gr, ch, &info, header);
		else
			requantize_ms(gr, &info, header);

		/* just which window?
		 */

		/* this is a very temporary, very ugly hack. 
		 */
		if (A_DOWNMIX)
			nch = 1;

		for (ch = 0; ch < (A_DOWNMIX ? 1 : nch); ch++) {
			int win_type;	/* same as in the standard, long=0, start=1 ,.... */
			int window_switching_flag = info.window_switching_flag[gr][ch];
			int block_type = info.block_type[gr][ch];
			int mixed_block_flag = info.mixed_block_flag[gr][ch];

			/* antialiasing butterflies
			 */
			if (!(window_switching_flag &&
			      block_type == 2))
				alias_reduction(ch);

			if (window_switching_flag &&
			    block_type == 2 &&
			    mixed_block_flag)
				win_type = 0;
			else if (!window_switching_flag)
				win_type = 0;
			else
				win_type = block_type;

			/* imdct ...
			 */
			for (sb = 0; sb < 2; sb++)
				imdct(win_type, sb, ch);

			if (window_switching_flag &&
			    block_type == 2 &&
			    mixed_block_flag)
				win_type = 2;

			/* no_of_imdcts tells us how many subbands from the top are all zero
			 * it is set by the requantize functions in misc2.c
			 */
			for (sb = 2; sb < no_of_imdcts[ch]; sb++)
				imdct(win_type, sb, ch);

			for (; sb < 32; sb++)
				for (i = 0; i < 18; i++) {
					res[sb][i] = s[ch][sb][i];
					s[ch][sb][i] = 0.0f;
				}

			/* polyphase filterbank
			 */
			/* if (nch == 2) this was a bug, tomislav */
			for (i = 0; i < 18; i++)
				poly(ch, i);
		}

		printout();

		/* this is part2 of a particularily ugly hack. this should vanish as soon as nch isn't
		   a global variable anymore
		 */
		if (A_DOWNMIX && header->mode != 3)
			nch = 2;

	}			/*  for (gr... */

	/* return status: 0 for ok, errors will be added
	 */
	return 0;
}
