00001 #include <string.h>
00002 #include "input_ogg.h"
00003 #include "types.h"
00004 #include "utility.h"
00005
00006
00007 namespace audiere {
00008
00009 typedef ogg_int64_t int64_t;
00010
00011
00012 OGGInputStream::OGGInputStream() {
00013 m_file = 0;
00014
00015 m_channel_count = 0;
00016 m_sample_rate = 0;
00017 m_sample_format = SF_S16;
00018 }
00019
00020
00021 OGGInputStream::~OGGInputStream() {
00022
00023 if (m_file) {
00024 ov_clear(&m_vorbis_file);
00025 }
00026 }
00027
00028
00029 bool
00030 OGGInputStream::initialize(File* file) {
00031 m_file = file;
00032
00033
00034 ov_callbacks callbacks;
00035 callbacks.read_func = FileRead;
00036 callbacks.seek_func = FileSeek;
00037 callbacks.close_func = FileClose;
00038 callbacks.tell_func = FileTell;
00039
00040
00041 int result = ov_open_callbacks(file, &m_vorbis_file, 0, 0, callbacks);
00042 if (result) {
00043 m_file = 0;
00044 return false;
00045 }
00046
00047
00048 vorbis_info* vi = ov_info(&m_vorbis_file, -1);
00049 if (!vi) {
00050 ov_clear(&m_vorbis_file);
00051 m_file = 0;
00052 return false;
00053 }
00054
00055 m_channel_count = vi->channels;
00056 m_sample_rate = vi->rate;
00057 m_sample_format = SF_S16;
00058
00059 return true;
00060 }
00061
00062
00063 void
00064 OGGInputStream::getFormat(
00065 int& channel_count,
00066 int& sample_rate,
00067 SampleFormat& sample_format)
00068 {
00069 channel_count = m_channel_count;
00070 sample_rate = m_sample_rate;
00071 sample_format = m_sample_format;
00072 }
00073
00074
00075 int
00076 OGGInputStream::read(int frame_count, void* buffer) {
00077 int sample_size = m_channel_count * GetSampleSize(m_sample_format);
00078
00079 u8* out = (u8*)buffer;
00080
00081 int samples_left = frame_count;
00082 int total_read = 0;
00083 while (samples_left > 0) {
00084
00085
00086
00087 vorbis_info* vi = ov_info(&m_vorbis_file, -1);
00088 if (vi && (m_sample_rate != vi->rate || m_channel_count != vi->channels)) {
00089 break;
00090 }
00091
00092 #ifdef WORDS_BIGENDIAN
00093 #define ENDIANNESS 1
00094 #else
00095 #define ENDIANNESS 0
00096 #endif
00097
00098 int bitstream;
00099 long result = ov_read(
00100 &m_vorbis_file,
00101 (char*)out,
00102 samples_left * sample_size,
00103 ENDIANNESS,
00104 2,
00105 1,
00106 &bitstream);
00107
00108 if (result < 0) {
00109
00110 continue;
00111 } else if (result == 0) {
00112 break;
00113 }
00114
00115 u32 samples_read = (u32)(result / sample_size);
00116
00117 out += samples_read * sample_size;
00118 samples_left -= samples_read;
00119 total_read += samples_read;
00120 }
00121
00122 return total_read;
00123 }
00124
00125
00126 void
00127 OGGInputStream::reset() {
00128 ov_pcm_seek(&m_vorbis_file, 0);
00129 }
00130
00131
00132 bool
00133 OGGInputStream::isSeekable() {
00134 return (ov_seekable(&m_vorbis_file) != 0);
00135 }
00136
00137
00138 int
00139 OGGInputStream::getLength() {
00140 if (isSeekable()) {
00141 return ov_pcm_total(&m_vorbis_file, -1);
00142 } else {
00143 return 0;
00144 }
00145 }
00146
00147
00148 void
00149 OGGInputStream::setPosition(int position) {
00150 if (isSeekable()) {
00151 ov_pcm_seek(&m_vorbis_file, position);
00152 }
00153 }
00154
00155
00156 int
00157 OGGInputStream::getPosition() {
00158 if (isSeekable()) {
00159 return ov_pcm_tell(&m_vorbis_file);
00160 } else {
00161 return 0;
00162 }
00163 }
00164
00165
00166 size_t
00167 OGGInputStream::FileRead(void* buffer, size_t size, size_t n, void* opaque) {
00168 File* file = reinterpret_cast<File*>(opaque);
00169 return file->read(buffer, size * n) / size;
00170 }
00171
00172
00173 int
00174 OGGInputStream::FileSeek(void* opaque, ogg_int64_t offset, int whence) {
00175 File* file = reinterpret_cast<File*>(opaque);
00176 File::SeekMode type;
00177 switch (whence) {
00178 case SEEK_SET: type = File::BEGIN; break;
00179 case SEEK_CUR: type = File::CURRENT; break;
00180 case SEEK_END: type = File::END; break;
00181 default: return -1;
00182 }
00183 return (file->seek((int)offset, type) ? 0 : -1);
00184 }
00185
00186
00187 int
00188 OGGInputStream::FileClose(void* ) {
00189
00190
00191 return 0;
00192 }
00193
00194
00195 long
00196 OGGInputStream::FileTell(void* opaque) {
00197 File* file = reinterpret_cast<File*>(opaque);
00198 return file->tell();
00199 }
00200
00201 }