*******************************************************************************/
+#include <cstdio>
#include <string>
#include <queue>
#include <vector>
-#include <SDL/SDL.h>
-#include <SDL/SDL_sound.h>
#include <AL/al.h>
+#include <vorbis/codec.h>
+#include <vorbis/vorbisfile.h>
#include "Log.hh"
#include "Mippleton.hh"
struct Sound::Impl
{
- static ALenum getAudioFormat(const Sound_AudioInfo& audioInfo)
+ static ALenum getAudioFormat(const vorbis_info* audioInfo)
{
- if (audioInfo.format == AUDIO_U8 || audioInfo.format == AUDIO_S8)
- {
- if (audioInfo.channels == 1) return AL_FORMAT_MONO8;
- else return AL_FORMAT_STEREO8;
- }
- else
- {
- if (audioInfo.channels == 1) return AL_FORMAT_MONO16;
- else return AL_FORMAT_STEREO16;
- }
+ if (audioInfo->channels == 1) return AL_FORMAT_MONO16;
+ else return AL_FORMAT_STEREO16;
}
class Buffer;
class Buffer : public Mippleton<Buffer>
{
- Sound_Sample* sound;
+ OggVorbis_File oggStream;
+ ALenum audioFormat;
+ ALsizei audioFreq;
std::vector<ALuint> objects;
public:
Buffer(const std::string& name) :
- Mippleton<Buffer>(name),
- sound(0)
+ Mippleton<Buffer>(name)
{
+ oggStream.datasource = 0;
openFile();
}
objects.pop_back();
}
- if (sound) Sound_FreeSample(sound);
+ if (oggStream.datasource)
+ {
+ ov_clear(&oggStream);
+ }
}
void openFile()
{
- if (sound) Sound_FreeSample(sound);
+ if (oggStream.datasource)
+ {
+ ov_clear(&oggStream);
+ oggStream.datasource = 0;
+ }
- sound = Sound_NewSampleFromFile(Sound::getPath(getName()).c_str(),
- 0, BUFFER_SIZE);
+ std::string filePath = Sound::getPath(getName());
+ int result = ov_fopen((char*)filePath.c_str(), &oggStream);
- if (!sound)
+ if (result < 0)
{
- logWarning("error while loading sound %s: %s",
- getName().c_str(), Sound_GetError());
- throw Exception(Exception::FILE_NOT_FOUND);
+ logWarning("error while loading sound %s",
+ getName().c_str());
+ throw Exception(Exception::BAD_AUDIO_FORMAT);
}
- logDebug("buffer size: %d", sound->buffer_size);
- logDebug(" channels: %d", sound->actual.channels);
- logDebug(" format: %d", sound->actual.format);
- logDebug(" frequency: %d", sound->actual.rate);
+ vorbis_info* vorbisInfo = ov_info(&oggStream, -1);
+ audioFormat = getAudioFormat(vorbisInfo);
+ audioFreq = vorbisInfo->rate;
+
+ logDebug(" channels: %d", vorbisInfo->channels);
+ logDebug(" frequency: %d", vorbisInfo->rate);
}
void loadAll(ALuint source)
{
- if (!sound) openFile();
- if (!sound) return;
+ if (!oggStream.datasource) openFile();
+ if (!oggStream.datasource) return;
+
+ char data[BUFFER_SIZE];
+ int size = 0;
+
+ for (;;)
+ {
+ int section;
+ int result = ov_read(&oggStream, data + size,
+ BUFFER_SIZE - size, 0, 2, 1, §ion);
- unsigned decoded = Sound_DecodeAll(sound);
- if (decoded == 0)
+ if (result > 0)
+ {
+ size += result;
+ }
+ else
+ {
+ if (result < 0) logWarning("vorbis playback error");
+ break;
+ }
+ }
+ if (size == 0)
{
logWarning("decoded no bytes from %s", getName().c_str());
//throw Exception(Exception::FILE_NOT_FOUND);
ALuint obj;
alGenBuffers(1, &obj);
- alBufferData(obj, getAudioFormat(sound->actual), sound->buffer,
- sound->buffer_size, sound->actual.rate);
+ alBufferData(obj, audioFormat, data, size, audioFreq);
objects.push_back(obj);
alSourcei(source, AL_BUFFER, obj);
- // don't need t his anymore
- Sound_FreeSample(sound);
- sound = 0;
+ // don't need this anymore
+ ov_clear(&oggStream);
+ oggStream.datasource = 0;
}
void beginStream(ALuint source, int nBuffers = 4)
{
- if (!sound) openFile();
- if (!sound) return;
+ if (!oggStream.datasource) openFile();
+ if (!oggStream.datasource) return;
ALuint objs[nBuffers];
alGenBuffers(nBuffers, objs);
// that buffer doesn't belong to us
if (it == objects.end()) return STREAM_WRONG;
- unsigned bytes = Sound_Decode(sound);
+ char data[BUFFER_SIZE];
+ int size = 0;
+
+ while (size < BUFFER_SIZE)
+ {
+ int section;
+ int result = ov_read(&oggStream, data + size,
+ BUFFER_SIZE - size, 0, 2, 1, §ion);
+
+ if (result > 0)
+ {
+ size += result;
+ }
+ else
+ {
+ if (result < 0) logWarning("vorbis playback error");
+ break;
+ }
+ }
- if (bytes == 0) return STREAM_EOF;
+ if (size == 0) return STREAM_EOF;
- alBufferData(buffer, getAudioFormat(sound->actual), sound->buffer,
- bytes, sound->actual.rate);
+ alBufferData(buffer, audioFormat, data, size, audioFreq);
return STREAM_OK;
}
inline void rewind()
{
- if (!sound) openFile();
- else Sound_Rewind(sound);
+ if (!oggStream.datasource) openFile();
+ else ov_raw_seek(&oggStream, 0);
}