00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
00040 OggVorbis_File oggStream;
00041 if (!openStream(fileName, oggStream)) return;
00042
00043
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
00050 if (size < dataBufferSize)
00051 {
00052 int error = 0;
00053
00054
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
00068 buffer_ = 0;
00069 }
00070
00071
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
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
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, §ion);
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
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