/* -----------------------------------------------------------------------------
	GSFramework
	Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */


		#include "audio/sample_stream_factory.h"
		#include "audio/sample_wav.h"
		#include "audio/audio_io.h"
		#include "audio/stream_interface.h"
		#include "log/log.h"

		using namespace GS;


//------------------------------------------------------------------------------
ISample				*SampleStreamFactory::Load(const char *path)
{
	// Open stream...
	AutoPtr <IAudioStream> stream(AudioIO::Get().OpenStream(path));
	if	(stream.IsNull())
		return NULL;

	#define PCM_OUTPUT_GROW_STEP 16384	// PCM output grows 16k at a time.

	Array <char> data, temp(stream->GetPCMBufferSize());
	size_t pcm_size = 0;

	// ...decode and dump PCM content to buffer.
	forever
	{
		size_t avail = stream->GetPCM(temp.c_ptr());
		if	(!avail)
		{
			if	(stream->IsEOF())
				break;
			continue;
		}

		size_t r_size = pcm_size + avail;
		if	(r_size > data.GetSize())
		{
			size_t size = (r_size / PCM_OUTPUT_GROW_STEP + 1) * PCM_OUTPUT_GROW_STEP;

			if	(!data.Reallocate(size))	// no way to know the PCM output size, this is bad for memory fragmentation...
			{
				__LOG_W__ << "Failed to append pcm chunk to sample, output will be truncated.\n";
				break;
			}
		}

		Memory::Copy(&data[(int)pcm_size], temp.c_ptr(), avail);
		pcm_size += avail;
	}

	if	(pcm_size == 0)
		return NULL;

	// Commit to sample object.
	__LOG__ << "OGG '" << path << "' -> PCM data size: " << pcm_size << " bytes.\n";
	uint sample_count = pcm_size / (stream->format.channels * stream->format.resolution / 8);

	//
	AutoPtr <SampleWav> sample(new SampleWav);
	if	(sample.IsNull())
		return NULL;

	sample->Set(data, sample_count, stream->format);
	return sample.Detach();
}
//------------------------------------------------------------------------------
