1 #include <vorbis/vorbisfile.h>
2 #include <msp/strings/format.h>
3 #include "oggdecoder.h"
9 size_t read(void *ptr, size_t size, size_t nmemb, void *src)
11 Msp::IO::Base *in = reinterpret_cast<Msp::IO::Base *>(src);
12 unsigned len = in->read(reinterpret_cast<char *>(ptr), size*nmemb);
16 int seek(void *src, ogg_int64_t offset, int whence)
18 Msp::IO::SeekType type;
20 type = Msp::IO::S_BEG;
21 else if(whence==SEEK_CUR)
22 type = Msp::IO::S_CUR;
23 else if(whence==SEEK_END)
24 type = Msp::IO::S_END;
28 Msp::IO::Seekable *in = reinterpret_cast<Msp::IO::Seekable *>(src);
29 return in->seek(offset, type);
34 return reinterpret_cast<Msp::IO::Seekable *>(src)->tell();
37 ov_callbacks io_callbacks =
51 ogg_error::ogg_error(const std::string &func, int code):
52 runtime_error(format("%s: %s", func, get_message(code)))
55 string ogg_error::get_message(int code)
59 case OV_FALSE: return "No data available";
60 case OV_HOLE: return "Missing or corrupt data";
61 case OV_EREAD: return "Read error";
62 case OV_EFAULT: return "Internal inconsistency";
63 case OV_EIMPL: return "Not implemented";
64 case OV_EINVAL: return "Invalid argument";
65 case OV_ENOTVORBIS: return "Not Vorbis data";
66 case OV_EBADHEADER: return "Corrupt Vorbis header";
67 case OV_EVERSION: return "Unsupported version";
68 case OV_EBADLINK: return "Bad link";
69 case OV_ENOSEEK: return "Stream is not seekable";
70 default: return format("Unknown error (%d)", code);
75 struct OggDecoder::Private
77 OggVorbis_File ovfile;
80 OggDecoder::OggDecoder(IO::Seekable &io):
83 int ret = ov_open_callbacks(&io, &priv->ovfile, 0, 0, io_callbacks);
85 throw ogg_error("ov_open_callbacks", ret);
87 vorbis_info *info = ov_info(&priv->ovfile, -1);
90 size = ov_pcm_total(&priv->ovfile, 0)*info->channels*2;
92 switch(info->channels)
94 case 1: format = MONO16; break;
95 case 2: format = STEREO16; break;
96 default: throw unsupported_sound(Msp::format("%d channels", info->channels));
100 OggDecoder::~OggDecoder()
102 if(priv->ovfile.datasource)
103 ov_clear(&priv->ovfile);
107 void OggDecoder::rewind()
109 ov_pcm_seek(&priv->ovfile, 0);
112 unsigned OggDecoder::read(char *buf, unsigned len)
115 int res = ov_read(&priv->ovfile, buf, len, 0, 2, 1, §ion);
117 throw ogg_error("ov_read", res);