/** (c) Nullsoft, Inc.         C O N F I D E N T I A L
 ** Filename: 
 ** Project:
 ** Description:
 ** Author: Ben Allison benski@nullsoft.com
 ** Created:
 **/
#include "main.h"
#include "ResamplingReader.h"

ResamplingReader::ResamplingReader(Resampler *_resampler, CommonReader *_reader, size_t inputFrameSize)
		: resampler(_resampler), reader(_reader),
		bufferValid(0),
		readState(READING)
{
	bufferAlloc = inputFrameSize * 1024; // enough room for 1024 samples
	buffer = (__int8 *)calloc(bufferAlloc, sizeof(__int8));
}

ResamplingReader::~ResamplingReader()
{
	free(buffer);
	delete resampler;
	delete reader;
}

size_t ResamplingReader::ReadAudio(void *outputBuffer, size_t sizeBytes)
{
	size_t origSize = sizeBytes;
	__int8 *origBuffer = (__int8 *)outputBuffer;
	size_t bytesResampled = 0;
read_again:
	// First, read from the file decoder
	switch (readState)
	{
	case READING:
		{
			size_t bytesToRead = bufferAlloc - bufferValid;
			if (bytesToRead)
			{
				int decode_killswitch=0, decode_error;
				size_t bytesRead = reader->ReadAudio(buffer + (bufferAlloc - bytesToRead), bytesToRead, &decode_killswitch, &decode_error);
				bufferValid += bytesRead;
				if (bytesRead == 0)
				{
					readState = ENDOFFILE;
				}
			}
		}
		break;
	case ENDOFFILE:
		resampler->Flush();
		readState = FLUSHING;

	}

	// now, resample
	size_t inputBytes = bufferValid;
	size_t bytesDone;

	bytesDone = resampler->Convert(buffer, &inputBytes, outputBuffer, sizeBytes);
	bytesResampled += bytesDone;

	// if we didn't use all of our input buffer, then we'll copy what's left to the beginning
	if (inputBytes)
		memmove(buffer, buffer + (bufferValid - inputBytes), inputBytes);

	// mark the number of bytes of data still valid in the input buffer
	bufferValid = inputBytes;

	if (!bytesDone && readState == FLUSHING)
		readState = DONE;

	if (bytesResampled != origSize && readState != DONE) // if we didn't provide enough data to fill the output buffer
	{
		sizeBytes = origSize - bytesResampled;
		outputBuffer = origBuffer + bytesResampled;
		goto read_again;
	}



	return bytesResampled;

}
#define CBCLASS ResamplingReader
START_DISPATCH;
CB(IFC_AUDIOSTREAM_READAUDIO, ReadAudio)
END_DISPATCH;