32 #include "util/log/logger.h"
33 #include "util/base/exception.h"
35 #include "sounddecoder_ogg.h"
38 static Logger _log(LM_AUDIO);
43 static size_t read(
void *ptr,
size_t size,
size_t nmemb,
void *datasource) {
44 RawData* rdp =
reinterpret_cast<RawData*
>(datasource);
45 size_t restlen = rdp->getDataLength()-rdp->getCurrentIndex();
46 size_t len = (restlen<=size*nmemb)?restlen:size*nmemb;
48 rdp->readInto(reinterpret_cast<uint8_t *>(ptr), len);
53 static int32_t seek(
void *datasource, ogg_int64_t offset, int32_t whence) {
54 RawData* rdp =
reinterpret_cast<RawData*
>(datasource);
57 (*rdp).setIndex(static_cast<uint32_t>(offset));
60 (*rdp).moveIndex(static_cast<uint32_t>(offset));
63 (*rdp).setIndex( (*rdp).getDataLength() -1 +
static_cast<uint32_t
>(offset));
69 static int32_t close(
void *datasource) {
return 0; }
71 static long tell(
void *datasource) {
72 RawData* rdp =
reinterpret_cast<RawData*
>(datasource);
73 return (*rdp).getCurrentIndex();
77 SoundDecoderOgg::SoundDecoderOgg(RawData* rdp) : m_file(rdp) {
80 OGG_cb::read, OGG_cb::seek, OGG_cb::close, OGG_cb::tell
83 if (0 > ov_open_callbacks(m_file.get(), &m_ovf, 0, 0, ocb)) {
84 throw InvalidFormat(
"Error opening OggVorbis file");
88 vorbis_info *vi = ov_info(&m_ovf, -1);
90 throw InvalidFormat(
"Error fetching OggVorbis info");
93 if (!ov_seekable(&m_ovf)) {
94 throw InvalidFormat(
"OggVorbis file has to be seekable");
97 m_isstereo = vi->channels == 2;
98 m_samplerate = vi->rate;
100 m_declength = (m_isstereo ? 2 : 1) * 2 * ov_pcm_total(&m_ovf, -1);
105 bool SoundDecoderOgg::decode(uint64_t length) {
111 m_data =
new char[length];
116 ret = ov_read(&m_ovf, m_data + m_datasize,
117 length-m_datasize, 0, 2, 1, &stream);
122 }
while (length-m_datasize > 0 && ret > 0);
124 return m_datasize == 0;
127 bool SoundDecoderOgg::setCursor(uint64_t pos) {
129 if (ov_pcm_seek(&m_ovf, pos / ((m_isstereo ? 2 : 1) * 2)) == 0) {
credit to phoku for his NodeDisplay example which the visitor code is adapted from ( he coded the qua...