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

input_ogg.cpp

Go to the documentation of this file.
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 //  m_eof  = false;
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   // were we initialized successfully?
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   // custom ogg vorbis callbacks
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   // open ogg vorbis stream
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   // calculate stream type
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   // if we're at the end of the file, we have no more samples
00100 //  if (m_eof) {
00101 //    return 0;
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 /*&& !m_eof*/) {
00109 
00110     // check to see if the stream format has changed
00111     // if so, treat it as an EndOfStream
00112     vorbis_info* vi = ov_info(&m_vorbis_file, -1);
00113     if (vi && (m_sample_rate != vi->rate || m_channel_count != vi->channels)) {
00114 //      m_eof = true;
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,  // little endian
00124       2,  // 16-bit
00125       1,  // signed
00126       &bitstream);
00127 
00128     if (result < 0) {
00129       // if error, ignore it
00130       continue;
00131     } else if (result == 0) {
00132 //      m_eof = true;
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* /*opaque*/)
00183 {
00184   // we don't have to do anything
00185   // (read: don't trust ogg vorbis with handling file closes)
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 

Generated at Mon Jun 10 02:55:12 2002 for audiere by doxygen1.2.8.1 written by Dimitri van Heesch, © 1997-2001