72 lines
1.9 KiB
C++
72 lines
1.9 KiB
C++
/* -----------------------------------------------------------------------------
|
|
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();
|
|
}
|
|
//------------------------------------------------------------------------------
|