X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fsound.cpp;h=fe2de5eb5c4b85faa6c05c25e64a0d30d44f775d;hb=17948408eafd48ea529acd0a70cc45fc5973cb10;hp=b2744b3abedeb9682a8c08e6ffbead563280f2dd;hpb=58dc1e7c15f928d0f861a20c46f2be4112bf5baf;p=libs%2Fal.git diff --git a/source/sound.cpp b/source/sound.cpp index b2744b3..fe2de5e 100644 --- a/source/sound.cpp +++ b/source/sound.cpp @@ -1,78 +1,148 @@ -/* $Id$ - -This file is part of libmspal -Copyright © 2008 Mikko Rasa, Mikkosoft Productions -Distributed under the LGPL -*/ - #include -#include +#include #include "sound.h" using namespace std; -namespace Msp { -namespace AL { +namespace { -Sound::Sound(): - data(0), - eof_flag(false) +struct MemorySource +{ + const void *data; + unsigned length; + unsigned pos; + + MemorySource(const void *d, unsigned l): data(d), length(l), pos(0) { } +}; + +size_t memory_read(void *ptr, size_t size, size_t nmemb, void *src) +{ + MemorySource &memsrc = *reinterpret_cast(src); + unsigned len = min(size*nmemb, memsrc.length-memsrc.pos); + memcpy(ptr, reinterpret_cast(memsrc.data)+memsrc.pos, len); + memsrc.pos += len; + + return len/size; +} + +int memory_seek(void *src, ogg_int64_t offset, int whence) +{ + MemorySource &memsrc = *reinterpret_cast(src); + if(whence==SEEK_SET) + memsrc.pos = offset; + else if(whence==SEEK_CUR) + memsrc.pos += offset; + else if(whence==SEEK_END) + memsrc.pos = memsrc.length-offset; + memsrc.pos = min(memsrc.pos, memsrc.length); + + return memsrc.pos; +} + +int memory_close(void *src) { - ovfile.datasource=0; + delete reinterpret_cast(src); + return 0; } -Sound::Sound(const std::string &fn): +long memory_tell(void *src) +{ + MemorySource &memsrc = *reinterpret_cast(src); + return memsrc.pos; +} + +ov_callbacks memory_callbacks= +{ + &memory_read, + &memory_seek, + &memory_close, + &memory_tell +}; + +} // namespace + +namespace Msp { +namespace AL { + +Sound::Sound(): data(0), eof_flag(false) { - ovfile.datasource=0; - open(fn); + ovfile.datasource = 0; } Sound::~Sound() { - delete data; + delete[] data; if(ovfile.datasource) ov_clear(&ovfile); } -void Sound::open(const string &fn) +void Sound::open_file(const string &fn) { if(ovfile.datasource) - throw InvalidState("Sound has already been opened"); + throw logic_error("Sound has already been opened"); if(ov_fopen(const_cast(fn.c_str()), &ovfile)<0) - throw Exception("Could not open ogg vorbis file "+fn); + throw runtime_error("Could not open ogg vorbis file "+fn); + + open_common(); +} + +void Sound::open_memory(const void *d, unsigned len) +{ + if(ovfile.datasource) + throw logic_error("Sound has already been opened"); + MemorySource *src = new MemorySource(d, len); + if(ov_open_callbacks(src, &ovfile, 0, 0, memory_callbacks)<0) + { + delete src; + throw runtime_error("Could not open ogg vorbis memory block"); + } + + open_common(); +} + +void Sound::open_common() +{ delete data; - data=0; + data = 0; - vorbis_info *info=ov_info(&ovfile, -1); - freq=info->rate; + vorbis_info *info = ov_info(&ovfile, -1); + freq = info->rate; switch(info->channels) { - case 1: format=MONO16; break; - case 2: format=STEREO16; break; - default: throw Exception("Unsupported number of channels"); + case 1: format = MONO16; break; + case 2: format = STEREO16; break; + default: throw runtime_error("Unsupported number of channels"); } } void Sound::load_data() { if(data) - throw InvalidState("Data has already been loaded"); + throw logic_error("Data has already been loaded"); + + size = ov_pcm_total(&ovfile, 0)*4; + char *dptr = new char[size]; + unsigned pos = 0; + while(unsigned len = read(dptr+pos, size-pos)) + pos += len; + data = dptr; + size = pos; + read_pos = 0; +} - size=ov_pcm_total(&ovfile, 0)*4; - char *dptr=new char[size]; - unsigned pos=0; - while(unsigned len=read(dptr+pos, size-pos)) - pos+=len; - data=dptr; - size=pos; +void Sound::load_file(const std::string &fn) +{ + open_file(fn); + load_data(); + close(); } -void Sound::load(const string &fn) +void Sound::load_memory(const void *d, unsigned len) { - open(fn); + open_memory(d, len); load_data(); close(); } @@ -86,7 +156,7 @@ void Sound::close() void Sound::rewind() { if(data) - read_pos=0; + read_pos = 0; else ov_pcm_seek(&ovfile, 0); } @@ -95,29 +165,29 @@ unsigned Sound::read(char *buf, unsigned len) { if(data) { - len=min(len, size-read_pos); + len = min(len, size-read_pos); memcpy(buf, data+read_pos, len); - read_pos+=len; + read_pos += len; return len; } else if(ovfile.datasource) { - int section=0; - int res=ov_read(&ovfile, buf, len, 0, 2, 1, §ion); + int section = 0; + int res = ov_read(&ovfile, buf, len, 0, 2, 1, §ion); if(res<0) - throw Exception("Error reading ogg vorbis file"); + throw runtime_error("Error reading ogg vorbis file"); else if(res==0) - eof_flag=true; + eof_flag = true; return res; } else - throw InvalidState("No data available"); + throw logic_error("No data available"); } const char *Sound::get_data() const { if(!data) - throw InvalidState("Data has not been loaded"); + throw logic_error("Data has not been loaded"); return data; }