00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "audio/ogg_sound_file.hpp"
00018
00019 #include <assert.h>
00020
00021 OggSoundFile::OggSoundFile(PHYSFS_file* file, double loop_begin, double loop_at) :
00022 file(),
00023 vorbis_file(),
00024 loop_begin(),
00025 loop_at(),
00026 normal_buffer_loop()
00027 {
00028 this->file = file;
00029
00030 ov_callbacks callbacks = { cb_read, cb_seek, cb_close, cb_tell };
00031 ov_open_callbacks(file, &vorbis_file, 0, 0, callbacks);
00032
00033 vorbis_info* vi = ov_info(&vorbis_file, -1);
00034
00035 channels = vi->channels;
00036 rate = vi->rate;
00037 bits_per_sample = 16;
00038 size = static_cast<size_t> (ov_pcm_total(&vorbis_file, -1) * 2);
00039
00040 double samples_begin = loop_begin * rate;
00041 double sample_loop = loop_at * rate;
00042
00043 this->loop_begin = (ogg_int64_t) samples_begin;
00044 if(loop_begin < 0) {
00045 this->loop_at = (ogg_int64_t) -1;
00046 } else {
00047 this->loop_at = (ogg_int64_t) sample_loop;
00048 }
00049 }
00050
00051 OggSoundFile::~OggSoundFile()
00052 {
00053 ov_clear(&vorbis_file);
00054 }
00055
00056 size_t
00057 OggSoundFile::read(void* _buffer, size_t buffer_size)
00058 {
00059 char* buffer = reinterpret_cast<char*> (_buffer);
00060 int section = 0;
00061 size_t totalBytesRead = 0;
00062
00063 while(buffer_size>0) {
00064 #ifdef WORDS_BIGENDIAN
00065 int bigendian = 1;
00066 #else
00067 int bigendian = 0;
00068 #endif
00069
00070 size_t bytes_to_read = buffer_size;
00071 if(loop_at > 0) {
00072 size_t bytes_per_sample = 2;
00073 ogg_int64_t time = ov_pcm_tell(&vorbis_file);
00074 ogg_int64_t samples_left_till_loop = loop_at - time;
00075 ogg_int64_t bytes_left_till_loop
00076 = samples_left_till_loop * bytes_per_sample;
00077 if(bytes_left_till_loop <= 4)
00078 break;
00079
00080 if(bytes_left_till_loop < (ogg_int64_t) bytes_to_read) {
00081 bytes_to_read = (size_t) bytes_left_till_loop;
00082 }
00083 }
00084
00085 long bytesRead
00086 = ov_read(&vorbis_file, buffer, bytes_to_read, bigendian,
00087 2, 1, §ion);
00088 if(bytesRead == 0) {
00089 break;
00090 }
00091 buffer_size -= bytesRead;
00092 buffer += bytesRead;
00093 totalBytesRead += bytesRead;
00094 }
00095
00096 return totalBytesRead;
00097 }
00098
00099 void
00100 OggSoundFile::reset()
00101 {
00102 ov_pcm_seek(&vorbis_file, loop_begin);
00103 }
00104
00105 size_t
00106 OggSoundFile::cb_read(void* ptr, size_t size, size_t nmemb, void* source)
00107 {
00108 PHYSFS_file* file = reinterpret_cast<PHYSFS_file*> (source);
00109
00110 PHYSFS_sint64 res
00111 = PHYSFS_read(file, ptr, static_cast<PHYSFS_uint32> (size),
00112 static_cast<PHYSFS_uint32> (nmemb));
00113 if(res <= 0)
00114 return 0;
00115
00116 return static_cast<size_t> (res);
00117 }
00118
00119 int
00120 OggSoundFile::cb_seek(void* source, ogg_int64_t offset, int whence)
00121 {
00122 PHYSFS_file* file = reinterpret_cast<PHYSFS_file*> (source);
00123
00124 switch(whence) {
00125 case SEEK_SET:
00126 if(PHYSFS_seek(file, static_cast<PHYSFS_uint64> (offset)) == 0)
00127 return -1;
00128 break;
00129 case SEEK_CUR:
00130 if(PHYSFS_seek(file, PHYSFS_tell(file) + offset) == 0)
00131 return -1;
00132 break;
00133 case SEEK_END:
00134 if(PHYSFS_seek(file, PHYSFS_fileLength(file) + offset) == 0)
00135 return -1;
00136 break;
00137 default:
00138 assert(false);
00139 return -1;
00140 }
00141 return 0;
00142 }
00143
00144 int
00145 OggSoundFile::cb_close(void* source)
00146 {
00147 PHYSFS_file* file = reinterpret_cast<PHYSFS_file*> (source);
00148 PHYSFS_close(file);
00149 return 0;
00150 }
00151
00152 long
00153 OggSoundFile::cb_tell(void* source)
00154 {
00155 PHYSFS_file* file = reinterpret_cast<PHYSFS_file*> (source);
00156 return static_cast<long> (PHYSFS_tell(file));
00157 }
00158
00159