00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include "util/log/logger.h"
00033 #include "util/base/exception.h"
00034
00035 #include "sounddecoder_ogg.h"
00036
00037 namespace FIFE {
00038 static Logger _log(LM_AUDIO);
00039
00040
00041
00042 namespace OGG_cb {
00043 static size_t read(void *ptr, size_t size, size_t nmemb, void *datasource) {
00044 RawData* rdp = reinterpret_cast<RawData*>(datasource);
00045 size_t restlen = rdp->getDataLength()-rdp->getCurrentIndex();
00046 size_t len = (restlen<=size*nmemb)?restlen:size*nmemb;
00047 if (len) {
00048 rdp->readInto(reinterpret_cast<uint8_t *>(ptr), len);
00049 }
00050 return len;
00051 }
00052
00053 static int seek(void *datasource, ogg_int64_t offset, int whence) {
00054 RawData* rdp = reinterpret_cast<RawData*>(datasource);
00055 switch (whence) {
00056 case SEEK_SET:
00057 (*rdp).setIndex(offset);
00058 return 0;
00059 case SEEK_CUR:
00060 (*rdp).moveIndex(offset);
00061 return 0;
00062 case SEEK_END:
00063 (*rdp).setIndex( (*rdp).getDataLength() -1 + offset);
00064 return 0;
00065 }
00066 return -1;
00067 }
00068
00069 static int close(void *datasource) { return 0; }
00070
00071 static long tell(void *datasource) {
00072 RawData* rdp = reinterpret_cast<RawData*>(datasource);
00073 return (*rdp).getCurrentIndex();
00074 }
00075 }
00076
00077 SoundDecoderOgg::SoundDecoderOgg(RawData* rdp) : m_file(rdp) {
00078
00079 ov_callbacks ocb = {
00080 OGG_cb::read, OGG_cb::seek, OGG_cb::close, OGG_cb::tell
00081 };
00082
00083 if (0 > ov_open_callbacks(m_file.get(), &m_ovf, 0, 0, ocb)) {
00084 throw InvalidFormat("Error opening OggVorbis file");
00085 }
00086
00087
00088 vorbis_info *vi = ov_info(&m_ovf, -1);
00089 if (!vi) {
00090 throw InvalidFormat("Error fetching OggVorbis info");
00091 }
00092
00093 if (!ov_seekable(&m_ovf)) {
00094 throw InvalidFormat("OggVorbis file has to be seekable");
00095 }
00096
00097 m_isstereo = vi->channels == 2;
00098 m_samplerate = vi->rate;
00099 m_is8bit = false;
00100 m_declength = (m_isstereo ? 2 : 1) * 2 * ov_pcm_total(&m_ovf, -1);
00101 m_datasize = 0;
00102 m_data = NULL;
00103 }
00104
00105 bool SoundDecoderOgg::decode(unsigned long length) {
00106 int stream = 0;
00107 int ret = 0;
00108
00109
00110 releaseBuffer();
00111 m_data = new char[length];
00112
00113
00114 m_datasize = 0;
00115 do {
00116 ret = ov_read(&m_ovf, m_data + m_datasize,
00117 length-m_datasize, 0, 2, 1, &stream);
00118 if (ret > 0) {
00119 m_datasize += ret;
00120 }
00121
00122 } while (length-m_datasize > 0 && ret > 0);
00123
00124 return m_datasize == 0;
00125 }
00126
00127 bool SoundDecoderOgg::setCursor(unsigned long pos) {
00128
00129 if (ov_pcm_seek(&m_ovf, pos / ((m_isstereo ? 2 : 1) * 2)) == 0) {
00130 return true;
00131 }
00132 return false;
00133 }
00134 }