AudioFormat_OGG.cpp
Go to the documentation of this file.00001 //*** AudioFormat_OGG.cpp *** 00002 00003 #include "AudioFormat_OGG.h" 00004 #include "Debug.h" 00005 #include "Asset.h" 00006 #include "StandardLibrary.h" 00007 00008 00009 #include "ogg/codec.h" 00010 #include "ogg/vorbisfile.h" 00011 00012 //*** File wrappers *** 00013 size_t AudioFormat_OGG_read_func(void *ptr, size_t size, size_t nmemb, void *datasource); 00014 int AudioFormat_OGG_seek_func(void *datasource, ogg_int64_t offset, int whence); 00015 int AudioFormat_OGG_close_func(void *datasource); 00016 long AudioFormat_OGG_tell_func(void *datasource); 00017 00018 00019 //*** Register *** 00020 00021 void AudioFormat_OGG::Register() 00022 { 00023 AudioFormat::RegisterAudioFormat(TestAsset,Create); 00024 } 00025 00026 00027 //*** Create *** 00028 00029 AudioFormat* AudioFormat_OGG::Create(const Asset& asset) 00030 { 00031 return new AudioFormat_OGG(asset); 00032 } 00033 00034 00035 //*** TestAsset *** 00036 00037 bool AudioFormat_OGG::TestAsset(const Asset& asset) 00038 { 00039 if (asset.Open()) 00040 { 00041 char buffer[5]; 00042 asset.Read(buffer,5); 00043 asset.Close(); 00044 if (StrCmp(buffer,"OggS")==0) 00045 { 00046 return true; 00047 } 00048 } 00049 return false; 00050 } 00051 00052 00053 //*** Constructor *** 00054 00055 AudioFormat_OGG::AudioFormat_OGG(const Asset& asset) 00056 { 00057 // Create a copy of the asset (we need it to stream data from) 00058 asset_=new Asset(asset); 00059 00060 // Open file (will be closed by OGG when it is done with it) 00061 bool res=asset_->Open(); 00062 00063 // Report missing file 00064 #ifdef _DEBUG 00065 if (!res) 00066 { 00067 const char* filename=asset.GetFilename().GetString(); 00068 if (filename) 00069 { 00070 char errorMessage[1024]; 00071 SNPrintF(errorMessage,1024,"File not found: %s",filename); 00072 Assert(false,errorMessage); 00073 } 00074 else 00075 { 00076 Assert(false,"An asset could not be accessed."); 00077 } 00078 } 00079 #endif 00080 00081 if (!res) 00082 { 00083 delete asset_; 00084 asset_=0; 00085 return; 00086 } 00087 00088 // Set up OGG callbacks, to make it use our own file wrapper instead of fread etc. 00089 ov_callbacks callbacks; 00090 callbacks.read_func=AudioFormat_OGG_read_func; 00091 callbacks.seek_func=AudioFormat_OGG_seek_func; 00092 callbacks.close_func=AudioFormat_OGG_close_func; 00093 callbacks.tell_func=AudioFormat_OGG_tell_func; 00094 00095 // Initialize OGG decoding of file 00096 oggFile_=new OggVorbis_File; 00097 int result=ov_open_callbacks(asset_, oggFile_, 0,0, callbacks); 00098 Assert(result==0,"Couldn't open stream"); 00099 if (result!=0) 00100 { 00101 delete asset_; 00102 asset_=0; 00103 delete oggFile_; 00104 oggFile_=0; 00105 } 00106 } 00107 00108 00109 //*** Destructor *** 00110 00111 AudioFormat_OGG::~AudioFormat_OGG() 00112 { 00113 ov_clear(oggFile_); 00114 delete oggFile_; 00115 delete asset_; 00116 } 00117 00118 00119 //*** GetChannels *** 00120 00121 int AudioFormat_OGG::GetChannels() 00122 { 00123 vorbis_info* vi=ov_info(oggFile_,-1); 00124 return vi->channels; 00125 } 00126 00127 00128 //*** GetFrequency *** 00129 00130 int AudioFormat_OGG::GetFrequency() 00131 { 00132 vorbis_info* vi=ov_info(oggFile_,-1); 00133 return vi->rate; 00134 } 00135 00136 00137 //*** GetBitsPerSample *** 00138 00139 int AudioFormat_OGG::GetBitsPerSample() 00140 { 00141 return 16; 00142 } 00143 00144 00145 00146 //*** GetSize *** 00147 00148 int AudioFormat_OGG::GetSize() 00149 { 00150 Assert(oggFile_,"File not open"); 00151 if (!oggFile_) 00152 { 00153 return 0; 00154 } 00155 00156 unsigned int size=(unsigned int)ov_pcm_total(oggFile_,-1); 00157 Assert(size!=OV_EINVAL,"Couldn't get total length"); 00158 return size*GetChannels()*(GetBitsPerSample()/8); 00159 } 00160 00161 00162 //*** GetPosition *** 00163 00164 int AudioFormat_OGG::GetPosition() 00165 { 00166 return (int)(ov_pcm_tell(oggFile_)*GetChannels()*(GetBitsPerSample()/8)); 00167 } 00168 00169 00170 //*** SetPosition *** 00171 00172 void AudioFormat_OGG::SetPosition(int position) 00173 { 00174 ov_pcm_seek(oggFile_,position/(GetChannels()*(GetBitsPerSample()/8))); 00175 } 00176 00177 00178 //*** CopySoundChunk *** 00179 00180 int AudioFormat_OGG::CopySoundChunk(void* buffer, int bytes) 00181 { 00182 int bytesToRead=bytes; 00183 unsigned int ret=0; 00184 while (bytesToRead>0) 00185 { 00186 int readSize=bytesToRead; 00187 int read=0; 00188 while (read<readSize) 00189 { 00190 ret=ov_read(oggFile_,static_cast<char*>(buffer)+read,readSize-read,0,2,1,0); 00191 read+=ret; 00192 if (ret==0) 00193 { 00194 return bytes-(bytesToRead-read); 00195 } 00196 } 00197 bytesToRead-=readSize; 00198 buffer=static_cast<unsigned char*>(buffer)+readSize; 00199 } 00200 Assert(bytesToRead==0,"I'm sort of assuming bytesToRead will always equal 0 here..."); 00201 return bytes; 00202 } 00203 00204 00205 //*** File wrappers *** 00206 00207 size_t AudioFormat_OGG_read_func(void* ptr, size_t size, size_t nmemb, void* datasource) 00208 { 00209 Asset* asset=static_cast<Asset*>(datasource); 00210 return asset->Read(static_cast<unsigned char*>(ptr),(int)(size*nmemb)); 00211 } 00212 00213 int AudioFormat_OGG_seek_func(void* datasource, ogg_int64_t offset, int whence) 00214 { 00215 Asset* asset=static_cast<Asset*>(datasource); 00216 Asset::SeekOrigin origin=Asset::SEEK_FROM_START; 00217 switch (whence) 00218 { 00219 case SEEK_SET: 00220 { 00221 origin=Asset::SEEK_FROM_START; 00222 }break; 00223 case SEEK_CUR: 00224 { 00225 origin=Asset::SEEK_FROM_CURRENT; 00226 }break; 00227 case SEEK_END: 00228 { 00229 origin=Asset::SEEK_FROM_END; 00230 }break; 00231 } 00232 00233 return asset->Seek((int)offset,origin); 00234 } 00235 00236 int AudioFormat_OGG_close_func(void* datasource) 00237 { 00238 Asset* asset=static_cast<Asset*>(datasource); 00239 asset->Close(); 00240 return 0; 00241 } 00242 00243 long AudioFormat_OGG_tell_func(void* datasource) 00244 { 00245 Asset* asset=static_cast<Asset*>(datasource); 00246 return asset->Tell(); 00247 }
Reproduction/republishing of any material on this site without permission is strictly prohibited.
