From e6f2d4f1acd40da05b1900a4c04b675f3edbf58f Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Fri, 20 Dec 2013 00:20:41 -0400 Subject: [PATCH] =?UTF-8?q?Added=20Source:clone()=20and=20love.audio.newSo?= =?UTF-8?q?urce(source):=20creates=20a=20new=20(stopped)=20Source=20which?= =?UTF-8?q?=20has=20all=20of=20the=20settable=20state=20of=20the=20origina?= =?UTF-8?q?l.=20Static=20sources=20don=E2=80=99t=20duplicate=20their=20Ope?= =?UTF-8?q?nAL=20data=20buffer=20when=20cloned=20(resolves=20issue=20#319)?= =?UTF-8?q?.=20Cloned=20streaming=20sources=20also=20clone=20the=20origina?= =?UTF-8?q?l=20Decoder.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/modules/audio/Source.h | 2 +- src/modules/audio/null/Source.cpp | 2 +- src/modules/audio/null/Source.h | 2 +- src/modules/audio/openal/Source.cpp | 95 +++++++++++++++++++++++------ src/modules/audio/openal/Source.h | 28 ++++++++- src/modules/audio/wrap_Audio.cpp | 9 +++ src/modules/audio/wrap_Source.cpp | 11 ++++ src/modules/audio/wrap_Source.h | 1 + 8 files changed, 126 insertions(+), 24 deletions(-) diff --git a/src/modules/audio/Source.h b/src/modules/audio/Source.h index 4e0983e4d..fd0892300 100644 --- a/src/modules/audio/Source.h +++ b/src/modules/audio/Source.h @@ -51,7 +51,7 @@ public: Source(Type type); virtual ~Source(); - virtual Source *copy() = 0; + virtual Source *clone() = 0; virtual void play() = 0; virtual void stop() = 0; diff --git a/src/modules/audio/null/Source.cpp b/src/modules/audio/null/Source.cpp index 1d543a940..ffd93b8ed 100644 --- a/src/modules/audio/null/Source.cpp +++ b/src/modules/audio/null/Source.cpp @@ -36,7 +36,7 @@ Source::~Source() { } -love::audio::Source *Source::copy() +love::audio::Source *Source::clone() { this->retain(); return this; diff --git a/src/modules/audio/null/Source.h b/src/modules/audio/null/Source.h index 969c019ab..1addc45c7 100644 --- a/src/modules/audio/null/Source.h +++ b/src/modules/audio/null/Source.h @@ -38,7 +38,7 @@ public: Source(); virtual ~Source(); - virtual love::audio::Source *copy(); + virtual love::audio::Source *clone(); virtual void play(); virtual void stop(); virtual void pause(); diff --git a/src/modules/audio/openal/Source.cpp b/src/modules/audio/openal/Source.cpp index 465d2516d..04c510b73 100644 --- a/src/modules/audio/openal/Source.cpp +++ b/src/modules/audio/openal/Source.cpp @@ -33,10 +33,22 @@ namespace audio namespace openal { +StaticDataBuffer::StaticDataBuffer(ALenum format, const ALvoid *data, ALsizei size, ALsizei freq) +{ + alGenBuffers(1, &buffer); + alBufferData(buffer, format, data, size, freq); +} + +StaticDataBuffer::~StaticDataBuffer() +{ + alDeleteBuffers(1, &buffer); +} + Source::Source(Pool *pool, love::sound::SoundData *soundData) : love::audio::Source(Source::TYPE_STATIC) , pool(pool) , valid(false) + , staticBuffer(nullptr) , pitch(1.0f) , volume(1.0f) , relative(false) @@ -51,14 +63,13 @@ Source::Source(Pool *pool, love::sound::SoundData *soundData) , offsetSamples(0) , offsetSeconds(0) , channels(soundData->getChannels()) - , decoder(0) + , decoder(nullptr) , toLoop(0) { - alGenBuffers(1, buffers); ALenum fmt = getFormat(soundData->getChannels(), soundData->getBitDepth()); - alBufferData(buffers[0], fmt, soundData->getData(), soundData->getSize(), soundData->getSampleRate()); + staticBuffer = new StaticDataBuffer(fmt, soundData->getData(), soundData->getSize(), soundData->getSampleRate()); - static float z[3] = {0, 0, 0}; + float z[3] = {0, 0, 0}; setFloatv(position, z); setFloatv(velocity, z); @@ -69,6 +80,7 @@ Source::Source(Pool *pool, love::sound::Decoder *decoder) : love::audio::Source(Source::TYPE_STREAM) , pool(pool) , valid(false) + , staticBuffer(nullptr) , pitch(1.0f) , volume(1.0f) , relative(false) @@ -87,27 +99,70 @@ Source::Source(Pool *pool, love::sound::Decoder *decoder) , toLoop(0) { decoder->retain(); - alGenBuffers(MAX_BUFFERS, buffers); + alGenBuffers(MAX_BUFFERS, streamBuffers); - static float z[3] = {0, 0, 0}; + float z[3] = {0, 0, 0}; setFloatv(position, z); setFloatv(velocity, z); setFloatv(direction, z); } +Source::Source(Source *s) + : love::audio::Source(s->type) + , pool(s->pool) + , valid(false) + , staticBuffer(s->staticBuffer) + , pitch(s->pitch) + , volume(s->volume) + , relative(s->relative) + , looping(s->looping) + , paused(false) + , minVolume(s->minVolume) + , maxVolume(s->maxVolume) + , referenceDistance(s->referenceDistance) + , rolloffFactor(s->rolloffFactor) + , maxDistance(s->maxDistance) + , cone(s->cone) + , offsetSamples(0) + , offsetSeconds(0) + , channels(s->channels) + , decoder(nullptr) + , toLoop(0) +{ + if (type == TYPE_STREAM) + { + if (s->decoder) + decoder = s->decoder->clone(); + + alGenBuffers(MAX_BUFFERS, streamBuffers); + } + else + staticBuffer->retain(); + + setFloatv(position, s->position); + setFloatv(velocity, s->velocity); + setFloatv(direction, s->direction); +} + Source::~Source() { if (valid) pool->stop(this); - alDeleteBuffers((type == TYPE_STATIC) ? 1 : MAX_BUFFERS, buffers); + + if (type == TYPE_STREAM) + alDeleteBuffers(MAX_BUFFERS, streamBuffers); + + if (staticBuffer) + staticBuffer->release(); + if (decoder) decoder->release(); } -love::audio::Source *Source::copy() +love::audio::Source *Source::clone() { - return 0; + return new Source(this); } void Source::play() @@ -341,13 +396,15 @@ float Source::tellAtomic(void *unit) const break; case Source::UNIT_SECONDS: default: - alGetSourcef(source, AL_SAMPLE_OFFSET, &offset); - ALint buffer; - alGetSourcei(source, AL_BUFFER, &buffer); - int freq; - alGetBufferi(buffer, AL_FREQUENCY, &freq); - offset /= freq; - if (type == TYPE_STREAM) offset += offsetSeconds; + { + alGetSourcef(source, AL_SAMPLE_OFFSET, &offset); + ALint buffer; + alGetSourcei(source, AL_BUFFER, &buffer); + int freq; + alGetBufferi(buffer, AL_FREQUENCY, &freq); + offset /= freq; + if (type == TYPE_STREAM) offset += offsetSeconds; + } break; } return offset; @@ -459,7 +516,7 @@ void Source::playAtomic() { if (type == TYPE_STATIC) { - alSourcei(source, AL_BUFFER, buffers[0]); + alSourcei(source, AL_BUFFER, staticBuffer->getBuffer()); } else if (type == TYPE_STREAM) { @@ -467,14 +524,14 @@ void Source::playAtomic() for (unsigned int i = 0; i < MAX_BUFFERS; i++) { - streamAtomic(buffers[i], decoder); + streamAtomic(streamBuffers[i], decoder); ++usedBuffers; if (decoder->isFinished()) break; } if (usedBuffers > 0) - alSourceQueueBuffers(source, usedBuffers, buffers); + alSourceQueueBuffers(source, usedBuffers, streamBuffers); } // This Source may now be associated with an OpenAL source that still has diff --git a/src/modules/audio/openal/Source.h b/src/modules/audio/openal/Source.h index d6defea8c..9027e2d2d 100644 --- a/src/modules/audio/openal/Source.h +++ b/src/modules/audio/openal/Source.h @@ -47,14 +47,35 @@ namespace openal class Audio; class Pool; +// Basically just a reference-counted non-streaming OpenAL buffer object. +class StaticDataBuffer : public love::Object +{ +public: + + StaticDataBuffer(ALenum format, const ALvoid *data, ALsizei size, ALsizei freq); + virtual ~StaticDataBuffer(); + + inline ALuint getBuffer() const + { + return buffer; + } + +private: + + ALuint buffer; + +}; // StaticDataBuffer + class Source : public love::audio::Source { public: + Source(Pool *pool, love::sound::SoundData *soundData); Source(Pool *pool, love::sound::Decoder *decoder); + Source(Source *s); virtual ~Source(); - virtual love::audio::Source *copy(); + virtual love::audio::Source *clone(); virtual void play(); virtual void stop(); virtual void pause(); @@ -123,8 +144,11 @@ private: Pool *pool; ALuint source; bool valid; + static const unsigned int MAX_BUFFERS = 32; - ALuint buffers[MAX_BUFFERS]; + ALuint streamBuffers[MAX_BUFFERS]; + + StaticDataBuffer *staticBuffer; float pitch; float volume; diff --git a/src/modules/audio/wrap_Audio.cpp b/src/modules/audio/wrap_Audio.cpp index 08dda50e8..c00102445 100644 --- a/src/modules/audio/wrap_Audio.cpp +++ b/src/modules/audio/wrap_Audio.cpp @@ -41,6 +41,15 @@ int w_getSourceCount(lua_State *L) int w_newSource(lua_State *L) { + if (luax_istype(L, 1, AUDIO_SOURCE_T)) + { + Source *t = luax_checksource(L, 1); + Source *clone = 0; + EXCEPT_GUARD(clone = t->clone();) + luax_pushtype(L, "Source", AUDIO_SOURCE_T, clone); + return 1; + } + if (lua_isstring(L, 1) || luax_istype(L, 1, FILESYSTEM_FILE_T)) luax_convobj(L, 1, "filesystem", "newFileData"); diff --git a/src/modules/audio/wrap_Source.cpp b/src/modules/audio/wrap_Source.cpp index 1ac396375..0c8a0b692 100644 --- a/src/modules/audio/wrap_Source.cpp +++ b/src/modules/audio/wrap_Source.cpp @@ -30,6 +30,15 @@ Source *luax_checksource(lua_State *L, int idx) return luax_checktype(L, idx, "Source", AUDIO_SOURCE_T); } +int w_Source_clone(lua_State *L) +{ + Source *t = luax_checksource(L, 1); + Source *clone = nullptr; + EXCEPT_GUARD(clone = t->clone();) + luax_pushtype(L, "Source", AUDIO_SOURCE_T, clone); + return 1; +} + int w_Source_play(lua_State *L) { Source *t = luax_checksource(L, 1); @@ -333,6 +342,8 @@ int w_Source_getChannels(lua_State *L) static const luaL_Reg functions[] = { + { "clone", w_Source_clone }, + { "play", w_Source_play }, { "stop", w_Source_stop }, { "pause", w_Source_pause }, diff --git a/src/modules/audio/wrap_Source.h b/src/modules/audio/wrap_Source.h index bca5ecaad..1a163dbad 100644 --- a/src/modules/audio/wrap_Source.h +++ b/src/modules/audio/wrap_Source.h @@ -30,6 +30,7 @@ namespace audio { Source *luax_checksource(lua_State *L, int idx); +int w_Source_clone(lua_State *L); int w_Source_play(lua_State *L); int w_Source_stop(lua_State *L); int w_Source_pause(lua_State *L);