X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;ds=sidebyside;f=source%2Fsound.cpp;h=8b6af20fcde8fe2c0ea22951a8d138c3dece0289;hb=97dae493948466867b9f661f45e451711dd6b41b;hp=b2744b3abedeb9682a8c08e6ffbead563280f2dd;hpb=58dc1e7c15f928d0f861a20c46f2be4112bf5baf;p=libs%2Fal.git diff --git a/source/sound.cpp b/source/sound.cpp index b2744b3..8b6af20 100644 --- a/source/sound.cpp +++ b/source/sound.cpp @@ -11,49 +11,102 @@ Distributed under the LGPL using namespace std; -namespace Msp { -namespace AL { +namespace { -Sound::Sound(): - data(0), - eof_flag(false) +struct MemorySource { - ovfile.datasource=0; + 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; +} + +void memory_close(void *src) +{ + delete reinterpret_cast(src); +} + +long memory_tell(void *src) +{ + MemorySource &memsrc=*reinterpret_cast(src); + return memsrc.pos; } -Sound::Sound(const std::string &fn): +ov_callbacks memory_callbacks= +{ + &memory_read, + &memory_seek, + 0, + &memory_tell +}; + +} // namespace + +namespace Msp { +namespace AL { + +Sound::Sound(): data(0), eof_flag(false) { ovfile.datasource=0; - open(fn); } 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"); if(ov_fopen(const_cast(fn.c_str()), &ovfile)<0) throw Exception("Could not open ogg vorbis file "+fn); - delete data; - data=0; + open_common(); +} - vorbis_info *info=ov_info(&ovfile, -1); - freq=info->rate; - switch(info->channels) +void Sound::open_memory(const void *d, unsigned len) +{ + if(ovfile.datasource) + throw InvalidState("Sound has already been opened"); + + MemorySource *src=new MemorySource(d, len); + if(ov_open_callbacks(src, &ovfile, 0, 0, memory_callbacks)<0) { - case 1: format=MONO16; break; - case 2: format=STEREO16; break; - default: throw Exception("Unsupported number of channels"); + delete src; + throw Exception("Could not open ogg vorbis memory block"); } + + open_common(); } void Sound::load_data() @@ -68,11 +121,19 @@ void Sound::load_data() pos+=len; data=dptr; size=pos; + read_pos=0; +} + +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(); } @@ -121,5 +182,20 @@ const char *Sound::get_data() const return data; } +void Sound::open_common() +{ + delete data; + data=0; + + 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"); + } +} + } // namespace AL } // namespace Msp