00001 #include <string.h>
00002 #include "input_ogg.hpp"
00003 #include "config.h"
00004 #include "utility.hpp"
00005
00006
00007 struct OGG_INTERNAL
00008 {
00009 OggVorbis_File vf;
00010 adr_u32 location;
00011 bool eof;
00012 };
00013
00014
00015 typedef ogg_int64_t int64_t;
00016
00017
00019
00020 OGGInputStream::OGGInputStream()
00021 {
00022 m_file = 0;
00023
00024
00025 m_channel_count = 0;
00026 m_sample_rate = 0;
00027 m_bits_per_sample = 0;
00028 }
00029
00031
00032 OGGInputStream::~OGGInputStream()
00033 {
00034
00035 if (m_file) {
00036 ov_clear(&m_vorbis_file);
00037
00038 delete m_file;
00039 m_file = 0;
00040 }
00041 }
00042
00044
00045 bool
00046 OGGInputStream::Initialize(IFile* file)
00047 {
00048 m_file = file;
00049
00050
00051 ov_callbacks callbacks;
00052 callbacks.read_func = FileRead;
00053 callbacks.seek_func = FileSeek;
00054 callbacks.close_func = FileClose;
00055 callbacks.tell_func = FileTell;
00056
00057
00058 int result = ov_open_callbacks(file, &m_vorbis_file, 0, 0, callbacks);
00059 if (result) {
00060 m_file = 0;
00061 return false;
00062 }
00063
00064
00065 vorbis_info* vi = ov_info(&m_vorbis_file, -1);
00066 if (!vi) {
00067 ov_clear(&m_vorbis_file);
00068 m_file = 0;
00069 return false;
00070 }
00071
00072 m_channel_count = vi->channels;
00073 m_bits_per_sample = 16;
00074 m_sample_rate = vi->rate;
00075
00076 return true;
00077 }
00078
00080
00081 void
00082 OGGInputStream::GetFormat(
00083 int& channel_count,
00084 int& sample_rate,
00085 int& bits_per_sample)
00086 {
00087 channel_count = m_channel_count;
00088 sample_rate = m_sample_rate;
00089 bits_per_sample = m_bits_per_sample;
00090 }
00091
00093
00094 int
00095 OGGInputStream::Read(int sample_count, void* samples)
00096 {
00097 int sample_size = m_bits_per_sample * m_channel_count / 8;
00098
00099
00100
00101
00102
00103
00104 adr_u8* out = (adr_u8*)samples;
00105
00106 int samples_left = sample_count;
00107 int total_read = 0;
00108 while (samples_left > 0 ) {
00109
00110
00111
00112 vorbis_info* vi = ov_info(&m_vorbis_file, -1);
00113 if (vi && (m_sample_rate != vi->rate || m_channel_count != vi->channels)) {
00114
00115 break;
00116 }
00117
00118 int bitstream;
00119 long result = ov_read(
00120 &m_vorbis_file,
00121 (char*)out,
00122 samples_left * sample_size,
00123 0,
00124 2,
00125 1,
00126 &bitstream);
00127
00128 if (result < 0) {
00129
00130 continue;
00131 } else if (result == 0) {
00132
00133 break;
00134 }
00135
00136 adr_u32 samples_read = (adr_u32)(result / sample_size);
00137
00138 out += samples_read * sample_size;
00139 samples_left -= samples_read;
00140 total_read += samples_read;
00141 }
00142
00143 return total_read;
00144 }
00145
00147
00148 bool
00149 OGGInputStream::Reset()
00150 {
00151 return (0 == ov_pcm_seek(&m_vorbis_file, 0));
00152 }
00153
00155
00156 size_t
00157 OGGInputStream::FileRead(void* buffer, size_t size, size_t n, void* opaque)
00158 {
00159 IFile* file = reinterpret_cast<IFile*>(opaque);
00160 return file->Read(buffer, size * n) / size;
00161 }
00162
00164
00165 int
00166 OGGInputStream::FileSeek(void* opaque, ogg_int64_t offset, int whence)
00167 {
00168 IFile* file = reinterpret_cast<IFile*>(opaque);
00169 ADR_SEEK_TYPE type;
00170 switch (whence) {
00171 case SEEK_SET: type = ADR_BEGIN; break;
00172 case SEEK_CUR: type = ADR_CURRENT; break;
00173 case SEEK_END: type = ADR_END; break;
00174 default: return -1;
00175 }
00176 return (file->Seek((int)offset, type) ? 0 : -1);
00177 }
00178
00180
00181 int
00182 OGGInputStream::FileClose(void* )
00183 {
00184
00185
00186 return 0;
00187 }
00188
00190
00191 long
00192 OGGInputStream::FileTell(void* opaque)
00193 {
00194 IFile* file = reinterpret_cast<IFile*>(opaque);
00195 return file->Tell();
00196 }
00197