src/sound.cpp in beeps-0.1.12 vs src/sound.cpp in beeps-0.1.13
- old
+ new
@@ -1,21 +1,166 @@
#include "beeps/sound.h"
#include <limits.h>
#include "Stk.h"
-#include "beeps/openal.h"
-#include "beeps/signals.h"
#include "beeps/processor.h"
#include "beeps/exception.h"
#include "openal.h"
+#include "signals.h"
+#if 0
+#define LOG(...) doutln(__VA_ARGS__)
+#else
+#define LOG(...)
+#endif
+
+
namespace Beeps
{
+ static ALuint get_buffer_id (const Sound& sound);
+
+
+ struct SoundSource
+ {
+
+ typedef SoundSource This;
+
+ typedef std::shared_ptr<This> Ptr;
+
+ ALint id;
+
+ static Ptr create ()
+ {
+ ALuint id_;
+ alGenSources(1, &id_);
+ if (!OpenAL_no_error()) return Ptr();
+
+ return Ptr(new This(id_));
+ }
+
+ ~SoundSource ()
+ {
+ if (!*this) return;
+
+ ALuint id_ = id;
+ alDeleteSources(1, &id_);
+ OpenAL_check_error(__FILE__, __LINE__);
+ }
+
+ void play (const Sound& sound)
+ {
+ assert(sound);
+
+ if (!*this)
+ invalid_state_error(__FILE__, __LINE__);
+
+ alSourcei(id, AL_BUFFER, get_buffer_id(sound));
+ alSourcePlay(id);
+ OpenAL_check_error(__FILE__, __LINE__);
+ }
+
+ void stop ()
+ {
+ if (!*this)
+ invalid_state_error(__FILE__, __LINE__);
+
+ alSourceStop(id);
+ OpenAL_check_error(__FILE__, __LINE__);
+ }
+
+ bool is_playing () const
+ {
+ if (!*this) return false;
+
+ ALint state = 0;
+ alGetSourcei(id, AL_SOURCE_STATE, &state);
+ OpenAL_check_error(__FILE__, __LINE__);
+
+ return state == AL_PLAYING;
+ }
+
+ operator bool () const
+ {
+ return id >= 0;
+ }
+
+ bool operator ! () const
+ {
+ return !operator bool();
+ }
+
+ private:
+
+ SoundSource (ALint id = -1)
+ : id(id)
+ {
+ }
+
+ };// SoundSource
+
+
+ typedef std::vector<SoundSource::Ptr> SoundSourceList;
+
+
+ namespace global
+ {
+
+ static SoundSourceList sources;
+
+ }// global
+
+
+ void
+ Sound_cleanup_sources ()
+ {
+ global::sources.clear();
+ }
+
+ static SoundSource*
+ get_next_source ()
+ {
+ SoundSource::Ptr source;
+
+ auto end = global::sources.end();
+ for (auto it = global::sources.begin(); it != end; ++it)
+ {
+ const SoundSource::Ptr& p = *it;
+ if (p && *p && !p->is_playing())
+ {
+ source = p;
+ global::sources.erase(it);
+ LOG("reuse source");
+ break;
+ }
+ }
+
+ if (!source)
+ {
+ source = SoundSource::create();
+ LOG("new source");
+ }
+
+ if (!source)
+ {
+ source = *global::sources.begin();
+ if (source) source->stop();
+ global::sources.erase(global::sources.begin());
+ LOG("stop and reuse oldest source");
+ }
+
+ if (!source)
+ return NULL;
+
+ global::sources.push_back(source);
+ return source.get();
+ }
+
+
struct Sound::Data
{
ALint id;
@@ -33,22 +178,22 @@
{
if (is_valid()) return;
ALuint id_ = 0;
alGenBuffers(1, &id_);
- check_error(__FILE__, __LINE__);
+ OpenAL_check_error(__FILE__, __LINE__);
id = id_;
}
void clear ()
{
if (id >= 0)
{
ALuint id_ = id;
alDeleteBuffers(1, &id_);
- check_error(__FILE__, __LINE__);
+ OpenAL_check_error(__FILE__, __LINE__);
}
id = -1;
}
@@ -58,10 +203,17 @@
}
};// Sound::Data
+ ALuint
+ get_buffer_id (const Sound& sound)
+ {
+ return sound.self->id;
+ }
+
+
Sound::Sound ()
{
}
Sound::Sound (Processor* processor, float seconds)
@@ -72,11 +224,11 @@
self->create();
Signals signals(seconds, 1);
processor->process(&signals);
- stk::StkFrames* frames = signals.frames();
+ stk::StkFrames* frames = Signals_get_frames(&signals);
if (!frames)
return;
ALsizei size = frames->frames();
if (size <= 0)
@@ -88,21 +240,35 @@
buffer.push_back((*frames)[i] * SHRT_MAX);
alBufferData(
self->id, AL_FORMAT_MONO16, &buffer[0], sizeof(short) * size,
frames->dataRate());
- check_error(__FILE__, __LINE__);
+ OpenAL_check_error(__FILE__, __LINE__);
}
Sound::~Sound ()
{
}
void
Sound::play ()
{
- play_sound(*this);
+ if (!*this)
+ invalid_state_error(__FILE__, __LINE__);
+
+ SoundSource* source = get_next_source();
+ if (!source || !*source)
+ invalid_state_error(__FILE__, __LINE__);
+
+ source->play(*this);
+
+#if 0
+ std::string ox = "";
+ for (size_t i = 0; i < global::sources.size(); ++i)
+ ox += global::sources[i]->is_playing() ? 'o' : 'x';
+ LOG("playing with %d sources. (%s)", global::sources.size(), ox.c_str());
+#endif
}
Sound::operator bool () const
{
return self->is_valid();
@@ -110,16 +276,9 @@
bool
Sound::operator ! () const
{
return !operator bool();
- }
-
-
- ALuint
- get_sound_buffer_id (const Sound& sound)
- {
- return sound.self->id;
}
}// Beeps