/* 
 *	Copyright (C) Aaron Holtzman - May 1999
 *
 *  This file is part of ac3dec, a free Dolby AC-3 stream decoder.
 *	
 *  ac3dec 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 2, or (at your option)
 *  any later version.
 *   
 *  ac3dec 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.
 *   
 *  You should have received a copy of the GNU General Public License
 *  along with GNU Make; see the file COPYING.  If not, write to
 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
 *
 */

//	let's make the ac3 lib independent from the GUI
//#include "../global.h"

#include "ac3.h"
#include "bitstream.h"
#include <stdlib.h>

//unsigned char * AC3Dec_Buffer;		// 48KB/frame for 64~448 Kbps
//uint_32 error_flag;


void bit_allocate(uint_16 fscod, bsi_t *bsi, audblk_t *audblk);
/*
static audblk_t audblk;
static bsi_t bsi;
static syncinfo_t syncinfo;

// the floating point samples for one audblk
static stream_samples_t samples;

// the integer samples for the entire frame (with enough space for 2 ch out)
// if this size change, be sure to change the size when muting
static sint_16 s16_samples[2 * 6 * 256];
static short *ptrAC3Dec_Buffer = 0;

// storage for the syncframe
#define BUFFER_MAX_SIZE 4096
static uint_8 buffer[BUFFER_MAX_SIZE];
static sint_32 buffer_size;
*/

uint_32 AC3Decoder::decode_buffer_syncframe(syncinfo_t *syncinfo, uint_8 **start, uint_8 *end)
{
	uint_8 *cur = *start;
	uint_16 syncword = syncinfo->syncword;
	uint_32 ret = 0;

	// find an ac3 sync frame
resync:
	while(syncword != 0x0b77)
	{
		if(cur >= end)
			goto done;
		syncword = (unsigned short)((syncword << 8) + *cur++);
	}

	// need the next 3 bytes to decide how big the frame is
	while(buffer_size < 3)
	{
		if(cur >= end)
			goto done;

		buffer[buffer_size++] = *cur++;
	}
	
	parse_syncinfo(syncinfo, buffer);

	if (syncinfo->frame_size==0)		// CRITICAL CONDITION
		goto done;

	while (buffer_size < (syncinfo->frame_size<<1) - 2)
	{
		if(cur >= end)
			goto done;

		buffer[buffer_size++] = *cur++;
	}

	// check the crc over the entire frame
	if (crc_process_frame(buffer, (syncinfo->frame_size<<1) - 2))
	{
		syncword = 0xffff;
		buffer_size = 0;
		goto resync;
	}

	// if we got to this point, we found a valid ac3 frame to decode
	bitstream_init(buffer);
	// get rid of the syncinfo struct as we already parsed it
	bitstream_get(24);

	// reset the syncword for next time
	syncword = 0xffff;
	buffer_size = 0;
	ret = 1;

done:
	syncinfo->syncword = syncword;
	*start = cur;
	return ret;
}

uint_32 AC3Decoder::decode_data(uint_8 *data_start, uint_32 length, uint_32 start, short p_SoundMax,ac3_context * p_Context)
{
	uint_8 *data_end = data_start + length;
	uint_32 i, j = start;

	AC3Dec_Buffer = p_Context->AC3Dec_Buffer;
	ptrAC3Dec_Buffer = (short*)AC3Dec_Buffer;

	while (decode_buffer_syncframe(&syncinfo, &data_start, data_end))
	{
		if (error_flag)
		{
			ZeroMemory(s16_samples, sizeof(sint_16) * 256 * 2 * 6);
			error_flag = 0;
			continue;
		}

		parse_bsi(&bsi);

		for (i=0; i<6; i++)
		{
			ZeroMemory(samples, sizeof(double) * 256 * (bsi.nfchans + bsi.lfeon));

			parse_audblk(&bsi, &audblk);

			exponent_unpack(&bsi, &audblk); 
			if (error_flag)
				goto error;

			bit_allocate(syncinfo.fscod, &bsi, &audblk);

			coeff_unpack(&bsi, &audblk, samples);
			if (error_flag)
				goto error;

			if (bsi.acmod == 0x2)
				rematrix(&audblk, samples);

			imdct(&bsi, &audblk, samples);

			downmix(&audblk, &bsi, samples, &s16_samples[i * 512],p_Context);

			sanity_check(&bsi, &audblk);
			if (error_flag)
				goto error;
		}

		memcpy(&AC3Dec_Buffer[start], s16_samples, 6144);
		start += 6144;
error:
		;
	}

	if (/*p_Context->Decision_Flag || */(!p_Context->SRC_Flag && p_Context->Normalization_Flag))
		for (i=(j>>1); i<(start>>1); i++)
			if (p_SoundMax < abs(ptrAC3Dec_Buffer[i]))
				p_SoundMax = (short)abs(ptrAC3Dec_Buffer[i]);
	return start;
}

void AC3Decoder::Init(int p_DRC_Flag)
{
	error_flag = buffer_size = 0;

	ZeroMemory(&syncinfo, sizeof(syncinfo));
	ZeroMemory(&bsi, sizeof(bsi));
	ZeroMemory(&audblk, sizeof(audblk));

	drc_init(p_DRC_Flag);
	imdct_init();
	exponent_init();
	mantissa_init();

	srand(0);
}
