SoundBufferOV.cpp

Go to the documentation of this file.
00001 ////////////////////////////////////////////////////////////////////////////////
00002 //    Scorched3D (c) 2000-2009
00003 //
00004 //    This file is part of Scorched3D.
00005 //
00006 //    Scorched3D is free software; you can redistribute it and/or modify
00007 //    it under the terms of the GNU General Public License as published by
00008 //    the Free Software Foundation; either version 2 of the License, or
00009 //    (at your option) any later version.
00010 //
00011 //    Scorched3D is distributed in the hope that it will be useful,
00012 //    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 //    GNU General Public License for more details.
00015 //
00016 //    You should have received a copy of the GNU General Public License
00017 //    along with Scorched3D; if not, write to the Free Software
00018 //    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 ////////////////////////////////////////////////////////////////////////////////
00020 
00021 #include <sound/SoundBufferOV.h>
00022 #include <sound/SoundBufferStaticSourceInstance.h>
00023 #include <sound/SoundBufferDynamicOVSourceInstance.h>
00024 #include <sound/Sound.h>
00025 #ifdef __DARWIN__
00026 #include <OpenAL/al.h>
00027 #include <OpenAL/alut.h>
00028 #else
00029 #include <AL/al.h>
00030 #include <AL/alut.h>
00031 #endif
00032 
00033 #ifdef HAVE_OGG
00034 
00035 SoundBufferOV::SoundBufferOV(const char *fileName) : 
00036         SoundBuffer(fileName),
00037         buffer_(0)
00038 {
00039         // Opean stream
00040         OggVorbis_File oggStream;
00041         if (!openStream(fileName, oggStream)) return;
00042 
00043         // Read file
00044         ov_raw_seek(&oggStream, 0);
00045         int dataBufferSize = OGG_BUFFER_SIZE * 2;
00046         static char dataBuffer[OGG_BUFFER_SIZE * 2];
00047         int size = readData(oggStream, dataBuffer, dataBufferSize);
00048 
00049         // Check if can fit in one go
00050         if (size < dataBufferSize)
00051         {
00052                 int error = 0;
00053 
00054                 // Create a buffer
00055                 alGetError();
00056                 alGenBuffers(1, &buffer_);
00057                 if ((error = alGetError()) != AL_NO_ERROR)
00058                 {
00059                         return;
00060                 }
00061 
00062                 vorbis_info *vorbisInfo = ov_info(&oggStream, -1);
00063                 addDataToBuffer(vorbisInfo, buffer_, dataBuffer, size);
00064         }
00065         else
00066         {
00067                 // Dynamic
00068                 buffer_ = 0;
00069         }
00070 
00071         // Cleanup ogg
00072         ov_clear(&oggStream);
00073 }
00074 
00075 bool SoundBufferOV::openStream(const char *fileName, OggVorbis_File &oggStream)
00076 {
00077         int error = 0;
00078         ov_callbacks callbacks = {
00079                 read_func,
00080                 seek_func,
00081                 close_func,
00082                 tell_func 
00083         };
00084 
00085         // Open file
00086         FILE *oggFile = fopen(fileName, "rb");
00087         if (!oggFile)
00088         {
00089                 S3D::dialogMessage("OGG Vorbis",
00090                         S3D::formatStringBuffer("Could not open ogg file \"%s\"",
00091                         fileName));
00092                 return false;
00093         }
00094 
00095         // Open stream
00096         int result = ov_open_callbacks((void *) oggFile, &oggStream, 0, 0, callbacks);
00097         if(result < 0)
00098         {        
00099                 fclose(oggFile);
00100                 S3D::dialogMessage("OGG Vorbis",
00101                         S3D::formatStringBuffer("Could not open ogg stream \"%s\" : %s",
00102                         fileName, errorString(result)));
00103                 return false; 
00104         }
00105 
00106         return true;
00107 }
00108 
00109 int SoundBufferOV::readData(OggVorbis_File &oggStream, char *buffer, int bufferSize)
00110 {    
00111         int size = 0;    
00112         int section;    
00113         while(size < bufferSize)
00114         {        
00115                 int result = ov_read(&oggStream, buffer + size, 
00116                         bufferSize - size, ((SDL_BYTEORDER == SDL_LIL_ENDIAN)?0:1), 2, 1, &section);            
00117                 if (result > 0) size += result;        
00118                 else if (result < 0) return -1;
00119                 else break;    
00120         }
00121         return size;
00122 }
00123 
00124 bool SoundBufferOV::addDataToBuffer(vorbis_info *vorbisInfo, int buffer, char *dataBuffer, int size)
00125 {
00126         ALenum format;
00127     if(vorbisInfo->channels == 1) format = AL_FORMAT_MONO16;
00128         else format = AL_FORMAT_STEREO16;
00129 
00130         // Load OV into buffer
00131         int error = 0;
00132         alGetError();
00133         alBufferData(buffer, format, dataBuffer, size, vorbisInfo->rate);  
00134         if ((error = alGetError()) != AL_NO_ERROR)
00135         {
00136                 return false;
00137         }
00138 
00139         return true;
00140 }
00141 
00142 const char *SoundBufferOV::errorString(int code)
00143 {    
00144         switch(code)    
00145         {        
00146         case OV_EREAD:            
00147                 return ("Read from media.");        
00148         case OV_ENOTVORBIS:            
00149                 return ("Not Vorbis data.");        
00150         case OV_EVERSION:            
00151                 return ("Vorbis version mismatch.");        
00152         case OV_EBADHEADER:            
00153                 return ("Invalid Vorbis header.");        
00154         case OV_EFAULT:            
00155                 return ("Internal logic fault (bug or heap/stack corruption.");        
00156         default:            
00157                 return ("Unknown Ogg error.");    
00158         }
00159 }
00160 
00161 size_t SoundBufferOV::read_func(void *ptr, size_t size, size_t nmemb, void *datasource)
00162 {
00163         return fread(ptr, size, nmemb, (FILE *) datasource);
00164 }
00165 
00166 int SoundBufferOV::seek_func(void *datasource, ogg_int64_t offset, int whence)
00167 {
00168         return fseek((FILE*) datasource, (long) offset, whence);
00169 }
00170 
00171 int SoundBufferOV::close_func(void *datasource)
00172 {
00173         return fclose((FILE *) datasource);
00174 }
00175 
00176 long SoundBufferOV::tell_func(void *datasource)
00177 {
00178         return ftell((FILE *) datasource);
00179 }
00180 
00181 SoundBufferOV::~SoundBufferOV()
00182 {
00183         if (buffer_) alDeleteBuffers (1, &buffer_);
00184         buffer_ = 0;
00185 }
00186 
00187 SoundBufferSourceInstance *SoundBufferOV::createSourceInstance(unsigned int source)
00188 {
00189         if (buffer_ == 0)
00190         {
00191                 return new SoundBufferDynamicOVSourceInstance(source, fileName_.c_str());
00192         }
00193         else
00194         {
00195                 return new SoundBufferStaticSourceInstance(source, buffer_);
00196         }
00197 }
00198 
00199 #endif // HAVE_OGG

Generated on Mon Feb 16 15:14:47 2009 for Scorched3D by  doxygen 1.5.3