commit x64 compilation from lulu cause the other branch dont seems to compile properly at home
This commit is contained in:
52
include/framework/audio/audio_io.cpp
Normal file
52
include/framework/audio/audio_io.cpp
Normal file
@ -0,0 +1,52 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "audio/audio_io.h"
|
||||
#include "filesystem/filesystem.h"
|
||||
#include "platform.h"
|
||||
#include "log/log.h"
|
||||
|
||||
using namespace GS;
|
||||
|
||||
template<> AudioIO *Singleton <AudioIO> ::i = NULL;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void AudioIO::RegisterStreamFactory(IAudioStreamFactory *f)
|
||||
{ stream_factories.Add(f); }
|
||||
void AudioIO::RegisterSampleFactory(ISampleFactory *f)
|
||||
{ sample_factories.Add(f); }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
ISample *AudioIO::LoadSample(const char *path, const char *format)
|
||||
{
|
||||
String fmt(format);
|
||||
if (Platform::Get().io->Exists(path))
|
||||
ListForeachPtr(ISampleFactory *, codec, sample_factories)
|
||||
if (ISample *sample = codec->Load(path))
|
||||
{
|
||||
if (!fmt || (fmt == sample->GetFormat()))
|
||||
return sample;
|
||||
_safe_delete(sample);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
IAudioStream *AudioIO::OpenStream(const char *path, const char *format)
|
||||
{
|
||||
String fmt(format);
|
||||
if (Platform::Get().io->Exists(path))
|
||||
ListForeachPtr(IAudioStreamFactory *, codec, stream_factories)
|
||||
if (IAudioStream *stream = codec->Open(path))
|
||||
{
|
||||
if (!fmt || (fmt == stream->GetFormat()))
|
||||
return stream;
|
||||
_safe_delete(stream);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
71
include/framework/audio/sample_stream_factory.cpp
Normal file
71
include/framework/audio/sample_stream_factory.cpp
Normal file
@ -0,0 +1,71 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
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();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
44
include/framework/audio/sample_wav.cpp
Normal file
44
include/framework/audio/sample_wav.cpp
Normal file
@ -0,0 +1,44 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "audio/sample_wav.h"
|
||||
#include "log/log.h"
|
||||
|
||||
using namespace GS;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool SampleWav::GetSampleFormat(SampleFormat &fmt) const
|
||||
{
|
||||
fmt = format;
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Time SampleWav::GetDuration() const
|
||||
{ return Time::fromMs(sample_count * 1000 / format.frequency); }
|
||||
uint SampleWav::GetPCMDataSize() const
|
||||
{ return format.GetPCMDataSize(sample_count); }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
char *SampleWav::AllocAs(uint count, const SampleFormat &fmt)
|
||||
{
|
||||
format = fmt;
|
||||
if (!pcm_data.Allocate(format.GetPCMDataSize(count)))
|
||||
__ERR__(__LOG_E__ << "Failed to allocate raw PCM sample buffer.\n", NULL)
|
||||
|
||||
sample_count = count;
|
||||
return pcm_data;
|
||||
}
|
||||
void SampleWav::Set(Array <char> &pcm, uint count, const SampleFormat &fmt)
|
||||
{
|
||||
pcm_data = pcm;
|
||||
sample_count = count;
|
||||
format = fmt;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
119
include/framework/audio/sample_wav_factory.cpp
Normal file
119
include/framework/audio/sample_wav_factory.cpp
Normal file
@ -0,0 +1,119 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "audio/sample_wav_factory.h"
|
||||
#include "audio/sample_wav.h"
|
||||
#include "filesystem/filesystem.h"
|
||||
#include "filesystem/io_handle.h"
|
||||
#include "memory/endian.h"
|
||||
#include "platform.h"
|
||||
#include "log/log.h"
|
||||
|
||||
using namespace GS;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
ISample *SampleWavFactory::Load(const char *path)
|
||||
{
|
||||
AutoPtr <IO::Handle> h(Platform::Get().io->Open(path));
|
||||
if (h.IsNull())
|
||||
return NULL;
|
||||
|
||||
// Verify format.
|
||||
char header[4];
|
||||
h->Read(header, 4);
|
||||
if (memcmp(header, "RIFF", 4))
|
||||
return NULL;
|
||||
h->Seek(4);
|
||||
h->Read(header, 4);
|
||||
if (memcmp(header, "WAVE", 4))
|
||||
return NULL;
|
||||
|
||||
// Create sample.
|
||||
AutoPtr <SampleWav> sample(new SampleWav);
|
||||
if (sample.IsNull())
|
||||
return NULL;
|
||||
|
||||
// Parse format.
|
||||
bool has_format = false, has_data = false;
|
||||
|
||||
struct Format
|
||||
{
|
||||
short wFormatTag;
|
||||
unsigned short wChannels;
|
||||
unsigned long dwSamplesPerSec;
|
||||
unsigned long dwAvgBytesPerSec;
|
||||
unsigned short wBlockAlign;
|
||||
unsigned short wBitsPerSample;
|
||||
};
|
||||
Format format;
|
||||
|
||||
Memory::Set(&format, 0, sizeof(Format));
|
||||
|
||||
forever
|
||||
{
|
||||
// Chunk + size.
|
||||
if (h->Read(header, 4) != 4)
|
||||
break;
|
||||
uint chunk_size = h->Read <uint> ();
|
||||
|
||||
// WAV format tag.
|
||||
if (!memcmp(header, "fmt ", 4))
|
||||
{
|
||||
uint cs = chunk_size;
|
||||
if (cs > sizeof(Format))
|
||||
{
|
||||
__LOG_W__ << "Unexpected WAV 'format' chunk size. Found " << cs << ", expected " << (int)sizeof(Format) << ".\n";
|
||||
cs = sizeof(Format);
|
||||
}
|
||||
if (h->Read(&format, cs) != cs)
|
||||
__ERR__(__LOG_E__ << "Mangled WAV 'format' chunk in '" << path << "'.\n", NULL)
|
||||
|
||||
Endian::ToHost(&format.wFormatTag, 2, Endian::Intel);
|
||||
Endian::ToHost(&format.wChannels, 2, Endian::Intel);
|
||||
Endian::ToHost(&format.dwSamplesPerSec, 4, Endian::Intel);
|
||||
Endian::ToHost(&format.dwAvgBytesPerSec, 4, Endian::Intel);
|
||||
Endian::ToHost(&format.wBlockAlign, 2, Endian::Intel);
|
||||
Endian::ToHost(&format.wBitsPerSample, 2, Endian::Intel);
|
||||
|
||||
has_format = true;
|
||||
|
||||
// Finish skipping tag.
|
||||
if (cs != chunk_size)
|
||||
h->Seek(chunk_size - cs);
|
||||
}
|
||||
|
||||
// WAV data tag.
|
||||
else if (!memcmp(header, "data", 4))
|
||||
{
|
||||
if (has_format)
|
||||
{
|
||||
char *pcm = sample->AllocAs(chunk_size / (format.wBitsPerSample / 8) / format.wChannels, SampleFormat(SampleFormat::Format_PCM, format.wChannels, format.dwSamplesPerSec, (uchar)format.wBitsPerSample));
|
||||
if (!pcm)
|
||||
__ERR__(__LOG_E__ << "failed to allocate WAV data chunk for '" << path << "'.\n", NULL)
|
||||
if (h->Read(pcm, chunk_size) != chunk_size)
|
||||
__ERR__(__LOG_E__ << "mangled WAV 'data' chunk in '" << path << "'.\n", NULL)
|
||||
}
|
||||
else
|
||||
__ERR__(__LOG_E__ << "WAV data with no format in '" << path << "'.\n", NULL)
|
||||
|
||||
has_data = true;
|
||||
}
|
||||
else
|
||||
h->Seek(chunk_size);
|
||||
}
|
||||
|
||||
if (!has_format || !has_data)
|
||||
return NULL;
|
||||
|
||||
SampleFormat sample_format;
|
||||
if (!sample->GetSampleFormat(sample_format))
|
||||
return NULL;
|
||||
|
||||
__LOG__ << "Sample format: " << sample_format.frequency / 1000 << "KHz@" << sample_format.resolution << "bit, " << sample_format.channels << " channel(s).\n";
|
||||
return sample.Detach();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
Reference in New Issue
Block a user