*******************************************************************************/
-#include <iostream>
#include <string>
#include <SDL/SDL.h>
#include <SDL/SDL_sound.h>
#include <AL/al.h>
+#include "Log.hh"
#include "Mippleton.hh"
#include "Sound.hh"
+#define BUFFER_SIZE (8 * 4096)
namespace Mf {
struct Buffer : public Mippleton<Buffer>
{
Buffer(const std::string& name) :
- Mippleton<Buffer>(name),
- object(0)
- {}
+ Mippleton<Buffer>(name)
+ {
+ sound = 0;
+ objects[0] = 0;
+ objects[1] = 0;
+ }
~Buffer()
{
- alDeleteBuffers(1, &object);
+ alDeleteBuffers(2, objects);
+
+ if (sound) Sound_FreeSample(sound);
}
+
+
void loadFromFile(const std::string& filePath, bool stream)
{
- if (object != 0) return;
+ if (objects[0] != 0) return;
- Sound_Sample* sound = Sound_NewSampleFromFile(filePath.c_str(),
- NULL, 8096);
+ sound = Sound_NewSampleFromFile(filePath.c_str(),
+ NULL, BUFFER_SIZE);
if (!sound)
{
- std::cerr << "could not load sound from file" << std::endl;
- exit(1);
+ logWarning("error while loading sound %s: %s", getName().c_str(), Sound_GetError());
+ throw Exception(Exception::FILE_NOT_FOUND);
}
+ if (!stream)
+ {
unsigned decoded = Sound_DecodeAll(sound);
if (decoded == 0)
{
- std::cout << "decoded no bytes" << std::endl;
- exit(1);
+ logWarning("decoded no bytes from %s", getName().c_str());
+ //throw Exception(Exception::FILE_NOT_FOUND);
+ return;
}
- std::cerr << "buffer size: " << sound->buffer_size << std::endl;
- std::cerr << "channels: " << (int)sound->actual.channels << std::endl;
- std::cerr << "format: " << sound->actual.format << std::endl;
- std::cerr << "frequency: " << sound->actual.rate << std::endl;
- alGenBuffers(1, &object);
- alBufferData(object, getAudioFormat(sound->actual), sound->buffer,
+ alGenBuffers(2, objects);
+ alBufferData(objects[0], getAudioFormat(sound->actual), sound->buffer,
sound->buffer_size, sound->actual.rate);
+ 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);
Sound_FreeSample(sound);
+ sound = 0;
+ }
+ else
+ {
+ 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);
+ alGenBuffers(2, objects);
+ }
}
- ALuint object;
+ bool stream(ALuint buffer)
+ {
+ int bytes = Sound_Decode(sound);
+
+ if (bytes < BUFFER_SIZE) return false;
+
+ alBufferData(buffer, getAudioFormat(sound->actual), sound->buffer,
+ sound->buffer_size, sound->actual.rate);
+ return false;
+ }
+
+ Sound_Sample* sound;
+ ALuint objects[2];
//ALfloat location[] = {0.0f, 0.0f, 0.0f};
//ALfloat location2[] = {0.0f, 0.0f, 0.0f};
};
Impl(const std::string& name, bool stream = false) :
- buffer_(Buffer::retain(name), Buffer::release)
+ buffer_(Buffer::getInstance(name))
{
if (!stream) buffer_->loadFromFile(Sound::getPath(name), stream);
else buffer_->loadFromFile(SoundStream::getPath(name), stream);
ALfloat location[] = {0.0f, 0.0f, 0.0f};
alGenSources(1, &source_);
- alSourcei(source_, AL_BUFFER, buffer_->object);
+
alSourcef(source_, AL_PITCH, 1.0f);
alSourcef(source_, AL_GAIN, 1.0f);
alSourcefv(source_, AL_POSITION, location);
alSourcefv(source_, AL_VELOCITY, location);
alSourcei(source_, AL_LOOPING, AL_FALSE);
+
+ if (!stream)
+ {
+ alSourcei(source_, AL_BUFFER, buffer_->objects[0]);
+ }
+ else
+ {
+ buffer_->stream(buffer_->objects[0]);
+ buffer_->stream(buffer_->objects[1]);
+
+ alSourceQueueBuffers(source_, 2, buffer_->objects);
+ }
}
~Impl()
void update()
{
+ int finished = 0;
+
+ alGetSourcei(source_, AL_BUFFERS_PROCESSED, &finished);
+
+ while (finished-- > 0)
+ {
+ ALuint buffer;
+
+ alSourceUnqueueBuffers(source_, 1, &buffer);
+ buffer_->stream(buffer);
+ alSourceQueueBuffers(source_, 1, &buffer);
+ }
}
boost::shared_ptr<Buffer> buffer_;
ALuint source_;
+ bool playing;
};
void Sound::play()
{
- alSourceRewind(impl_->source_);
+ if (!impl_->buffer_->sound) return;
+
+ //alSourceRewind(impl_->source_);
alSourcePlay(impl_->source_);
+ impl_->playing = true;
+}
+
+void Sound::pause()
+{
+ alSourcePause(impl_->source_);
+ impl_->playing = false;
+}
+
+void Sound::togglePlayPause()
+{
+ if (impl_->playing) pause();
+ else play();
+}
+
+void Sound::setGain(Scalar gain)
+{
+ alSourcef(impl_->source_, AL_GAIN, gain);
}