Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

input_ogg.cpp

Go to the documentation of this file.
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     // were we initialized successfully?
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     // custom ogg vorbis callbacks
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     // open ogg vorbis stream
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     // calculate stream type
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; // see constructor
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       // check to see if the stream format has changed
00086       // if so, treat it as an EndOfStream
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,  // 16-bit
00105         1,  // signed
00106         &bitstream);
00107 
00108       if (result < 0) {
00109         // if error, ignore it
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* /*opaque*/) {
00189     // we don't have to do anything
00190     // (read: don't trust ogg vorbis with handling file closes)
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 }

Generated on Sat Oct 12 01:43:03 2002 for audiere by doxygen1.2.17