X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;ds=sidebyside;f=source%2Foggdecoder.cpp;fp=source%2Foggdecoder.cpp;h=a00b78ed7341bbfb42e1229d006490f15a6514b1;hb=10cdb043b613d60c5de8f1cce0f7a5512b0d0074;hp=0000000000000000000000000000000000000000;hpb=ef9906f379e066cb9c754853a3cc771e8e881356;p=libs%2Fal.git diff --git a/source/oggdecoder.cpp b/source/oggdecoder.cpp new file mode 100644 index 0000000..a00b78e --- /dev/null +++ b/source/oggdecoder.cpp @@ -0,0 +1,99 @@ +#include +#include +#include "oggdecoder.h" + +using namespace std; + +namespace { + +size_t read(void *ptr, size_t size, size_t nmemb, void *src) +{ + Msp::IO::Base *in = reinterpret_cast(src); + unsigned len = in->read(reinterpret_cast(ptr), size*nmemb); + return len/size; +} + +int seek(void *src, ogg_int64_t offset, int whence) +{ + Msp::IO::SeekType type; + if(whence==SEEK_SET) + type = Msp::IO::S_BEG; + else if(whence==SEEK_CUR) + type = Msp::IO::S_CUR; + else if(whence==SEEK_END) + type = Msp::IO::S_END; + else + return -1; + + Msp::IO::Seekable *in = reinterpret_cast(src); + return in->seek(offset, type); +} + +long tell(void *src) +{ + return reinterpret_cast(src)->tell(); +} + +ov_callbacks io_callbacks = +{ + &read, + &seek, + 0, + &tell +}; + +} // namespace + + +namespace Msp { +namespace AL { + +struct OggDecoder::Private +{ + OggVorbis_File ovfile; +}; + +OggDecoder::OggDecoder(IO::Seekable &io): + priv(new Private) +{ + if(ov_open_callbacks(&io, &priv->ovfile, 0, 0, io_callbacks)<0) + throw runtime_error("Could not open ogg vorbis resource"); + + vorbis_info *info = ov_info(&priv->ovfile, -1); + freq = info->rate; + + size = ov_pcm_total(&priv->ovfile, 0)*info->channels*2; + + switch(info->channels) + { + case 1: format = MONO16; break; + case 2: format = STEREO16; break; + default: throw runtime_error("Unsupported number of channels"); + } +} + +OggDecoder::~OggDecoder() +{ + if(priv->ovfile.datasource) + ov_clear(&priv->ovfile); + delete priv; +} + +void OggDecoder::rewind() +{ + ov_pcm_seek(&priv->ovfile, 0); +} + +unsigned OggDecoder::read(char *buf, unsigned len) +{ + int section = 0; + int res = ov_read(&priv->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; +} + +} // namespace AL +} // namespace Msp