X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fsounddecoder.cpp;h=ed9de800ffef84345faf133260080a9aa9eb6b96;hb=HEAD;hp=d4d176718d9dbc1b82cb402781df8371719f593d;hpb=6cc0f1735a00e8f9eb80ff0c9468fb67205f6d20;p=libs%2Fal.git diff --git a/source/sounddecoder.cpp b/source/sounddecoder.cpp index d4d1767..ed9de80 100644 --- a/source/sounddecoder.cpp +++ b/source/sounddecoder.cpp @@ -1,141 +1,70 @@ -#include -#include +#include +#include +#include +#ifdef WITH_LIBMAD +#include "mad/mp3decoder.h" +#endif +#ifdef WITH_LIBVORBIS +#include "vorbis/oggdecoder.h" +#endif #include "sounddecoder.h" using namespace std; -namespace { - -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) -{ - delete reinterpret_cast(src); - return 0; -} - -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 { +unsupported_sound::unsupported_sound(const string &w): + runtime_error(w) +{ } + + SoundDecoder::SoundDecoder(): + source(0), + freq(0), + size(0), + format(MONO8), eof_flag(false) -{ - ovfile.datasource = 0; -} +{ } SoundDecoder::~SoundDecoder() { - if(ovfile.datasource) - ov_clear(&ovfile); + delete source; } -void SoundDecoder::open_file(const string &fn) +SoundDecoder *SoundDecoder::open_file(const string &fn) { - if(ovfile.datasource) - throw logic_error("Sound has already been opened"); - if(ov_fopen(const_cast(fn.c_str()), &ovfile)<0) - throw runtime_error("Could not open ogg vorbis file "+fn); - - open_common(); -} - -void SoundDecoder::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(); + RefPtr file = new IO::BufferedFile(fn); + SoundDecoder *decoder = open_io(*file); + decoder->source = file.release(); + return decoder; } -void SoundDecoder::open_common() +SoundDecoder *SoundDecoder::open_io(IO::Seekable &io) { - vorbis_info *info = ov_info(&ovfile, -1); - freq = info->rate; - - size = ov_pcm_total(&ovfile, 0)*info->channels*2; - - switch(info->channels) + char sig_buf[8]; + io.read(sig_buf, sizeof(sig_buf)); + io.seek(0, IO::S_BEG); + string signature(sig_buf, sizeof(sig_buf)); + +#ifdef WITH_LIBVORBIS + if(OggDecoder::detect(signature)) + return new OggDecoder(io); +#endif + +#ifdef WITH_LIBMAD + if(Mp3Decoder::detect(signature)) + return new Mp3Decoder(io); +#endif + + string sig_hex; + for(unsigned i=0; i(sig_buf[i])); } -} - -void SoundDecoder::close() -{ - if(ovfile.datasource) - ov_clear(&ovfile); -} - -void SoundDecoder::rewind() -{ - ov_pcm_seek(&ovfile, 0); -} - -unsigned SoundDecoder::read(char *buf, unsigned len) -{ - int section = 0; - int res = ov_read(&ovfile, buf, len, 0, 2, 1, §ion); - if(res<0) - throw runtime_error("Error reading ogg vorbis file"); - else if(res==0) - eof_flag = true; - return res; + throw unsupported_sound(sig_hex); } } // namespace AL