/* ----------------------------------------------------------------------------- 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 stream(AudioIO::Get().OpenStream(path)); if (stream.IsNull()) return NULL; #define PCM_OUTPUT_GROW_STEP 16384 // PCM output grows 16k at a time. Array 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 sample(new SampleWav); if (sample.IsNull()) return NULL; sample->Set(data, sample_count, stream->format); return sample.Detach(); } //------------------------------------------------------------------------------