From b757a0534e18145cc9d110f60295ab2fc5d893c1 Mon Sep 17 00:00:00 2001 From: rcoaxil Date: Thu, 13 Oct 2016 04:40:41 +0300 Subject: [PATCH] pull request feedback addressed newQueueableSource added isQueueable removed, getFreeBufferCount added queueData renamed to queue; added 3 argument variant with (data, offset, length) lightuserdata variant now requires offset (pointer, offset, length, samplerate, bitdepth, channels) setLooping now throws exception if called on queueable source --HG-- branch : minor --- src/modules/audio/Source.h | 4 +- src/modules/audio/null/Source.cpp | 6 +-- src/modules/audio/null/Source.h | 4 +- src/modules/audio/openal/Pool.cpp | 4 +- src/modules/audio/openal/Pool.h | 2 +- src/modules/audio/openal/Source.cpp | 65 +++++++++++++++------------- src/modules/audio/openal/Source.h | 6 +-- src/modules/audio/wrap_Audio.cpp | 67 ++++++++++++++++++----------- src/modules/audio/wrap_Source.cpp | 58 ++++++++++++++++--------- 9 files changed, 128 insertions(+), 88 deletions(-) diff --git a/src/modules/audio/Source.h b/src/modules/audio/Source.h index 3eecbb592..e169fe819 100644 --- a/src/modules/audio/Source.h +++ b/src/modules/audio/Source.h @@ -102,8 +102,8 @@ public: virtual int getChannels() const = 0; - virtual bool isQueueable() const = 0; - virtual bool queueData(void *data, int length, int dataSampleRate, int dataBitDepth, int dataChannels) = 0; + virtual int getFreeBufferCount() const = 0; + virtual bool queue(void *data, int length, int dataSampleRate, int dataBitDepth, int dataChannels) = 0; virtual Type getType() const; diff --git a/src/modules/audio/null/Source.cpp b/src/modules/audio/null/Source.cpp index e6a6fe7ee..101f38079 100644 --- a/src/modules/audio/null/Source.cpp +++ b/src/modules/audio/null/Source.cpp @@ -217,12 +217,12 @@ int Source::getChannels() const return 2; } -bool Source::isQueueable() const +int Source::getFreeBufferCount() const { - return false; + return 0; } -bool Source::queueData(void *data, int length, int dataSampleRate, int dataBitDepth, int dataChannels) +bool Source::queue(void *data, int length, int dataSampleRate, int dataBitDepth, int dataChannels) { return false; } diff --git a/src/modules/audio/null/Source.h b/src/modules/audio/null/Source.h index bd57804e4..780c39453 100644 --- a/src/modules/audio/null/Source.h +++ b/src/modules/audio/null/Source.h @@ -76,8 +76,8 @@ public: virtual float getMaxDistance() const; virtual int getChannels() const; - virtual bool isQueueable() const; - virtual bool queueData(void *data, int length, int dataSampleRate, int dataBitDepth, int dataChannels); + virtual int getFreeBufferCount() const; + virtual bool queue(void *data, int length, int dataSampleRate, int dataBitDepth, int dataChannels); private: diff --git a/src/modules/audio/openal/Pool.cpp b/src/modules/audio/openal/Pool.cpp index 7427bd23e..e52243dbd 100644 --- a/src/modules/audio/openal/Pool.cpp +++ b/src/modules/audio/openal/Pool.cpp @@ -283,10 +283,10 @@ double Pool::getDuration(Source *source, void *unit) return source->getDurationAtomic(unit); } -bool Pool::queueData(Source *source, void *data, ALsizei length) +bool Pool::queue(Source *source, void *data, ALsizei length) { thread::Lock lock(mutex); - return source->queueDataAtomic(data, length); + return source->queueAtomic(data, length); } ALuint Pool::findi(const Source *source) const diff --git a/src/modules/audio/openal/Pool.h b/src/modules/audio/openal/Pool.h index 3a32566aa..9588aefd5 100644 --- a/src/modules/audio/openal/Pool.h +++ b/src/modules/audio/openal/Pool.h @@ -91,7 +91,7 @@ public: void seek(Source *source, float offset, void *unit); float tell(Source *source, void *unit); double getDuration(Source *source, void *unit); - bool queueData(Source *source, void *data, ALsizei length); + bool queue(Source *source, void *data, ALsizei length); bool play(const std::vector &sources); void stop(const std::vector &sources); diff --git a/src/modules/audio/openal/Source.cpp b/src/modules/audio/openal/Source.cpp index b842e1c57..10a8db7e6 100644 --- a/src/modules/audio/openal/Source.cpp +++ b/src/modules/audio/openal/Source.cpp @@ -80,18 +80,7 @@ class QueueTypeMismatchException : public love::Exception public: QueueTypeMismatchException() - : Exception("Only \"queue\" type sound Sources can be queued with sound data.") - { - } - -}; - -class QueueNegativeLengthException : public love::Exception -{ -public: - - QueueNegativeLengthException() - : Exception("Data length cannot be negative.") + : Exception("Only queueable Sources can be queued with sound data.") { } @@ -102,12 +91,24 @@ class QueueMalformedLengthException : public love::Exception public: QueueMalformedLengthException(int bytes) - : Exception("Data lenght must be a multiple of sample size (%d bytes).", bytes) + : Exception("Data length must be a multiple of sample size (%d bytes).", bytes) { } }; +class QueueLoopingException : public love::Exception +{ +public: + + QueueLoopingException() + : Exception("Queueable Sources can not be looped.") + { + } + +}; + + StaticDataBuffer::StaticDataBuffer(ALenum format, const ALvoid *data, ALsizei size, ALsizei freq) : size(size) { @@ -317,10 +318,10 @@ bool Source::isPlaying() const } bool Source::isFinished() const -{ +{ if (!valid) return false; - + if (type == TYPE_STREAM && (isLooping() || !decoder->isFinished())) return false; @@ -342,7 +343,7 @@ bool Source::update() alSourcei(source, AL_LOOPING, isLooping() ? AL_TRUE : AL_FALSE); return !isFinished(); case TYPE_STREAM: - if (isLooping() || !isFinished()) + if (!isFinished()) { ALint processed; ALuint buffers[MAX_BUFFERS]; @@ -696,6 +697,9 @@ bool Source::isRelative() const void Source::setLooping(bool enable) { + if (type == TYPE_QUEUE) + throw QueueLoopingException(); + if (valid && type == TYPE_STATIC) alSourcei(source, AL_LOOPING, enable ? AL_TRUE : AL_FALSE); @@ -707,25 +711,24 @@ bool Source::isLooping() const return looping; } -bool Source::queueData(void *data, int length, int dataSampleRate, int dataBitDepth, int dataChannels) +bool Source::queue(void *data, int length, int dataSampleRate, int dataBitDepth, int dataChannels) { if (type != TYPE_QUEUE) throw QueueTypeMismatchException(); - if (length < 0) - throw QueueNegativeLengthException(); - if (dataSampleRate != sampleRate || dataBitDepth != bitDepth || dataChannels != channels ) throw QueueFormatMismatchException(); if (length % (bitDepth / 8 * channels) != 0) throw QueueMalformedLengthException(bitDepth / 8 * channels); - if (length > 0) - return pool->queueData(this, data, (ALsizei)length); + if (length == 0) + return true; + + return pool->queue(this, data, (ALsizei)length); } -bool Source::queueDataAtomic(void *data, ALsizei length) +bool Source::queueAtomic(void *data, ALsizei length) { if (valid) { @@ -752,11 +755,17 @@ bool Source::queueDataAtomic(void *data, ALsizei length) return true; } -bool Source::isQueueable() const +int Source::getFreeBufferCount() const { - if (type != TYPE_QUEUE || (valid && unusedBufferTop < 0) || (!valid && unusedBufferTop >= (int)MAX_BUFFERS - 1)) - return false; - return true; + switch (type) //why not :^) + { + case TYPE_STATIC: + return 0; + case TYPE_STREAM: + return unusedBufferTop + 1; + case TYPE_QUEUE: + return valid ? unusedBufferTop + 1 : (int)MAX_BUFFERS - unusedBufferTop - 1; + } } void Source::prepareAtomic() @@ -799,7 +808,6 @@ void Source::prepareAtomic() if (offsetSamples >= 0) alSourcef(source, AL_SAMPLE_OFFSET, offsetSamples); } - } } @@ -839,7 +847,6 @@ void Source::teardownAtomic() //stack needs to be filled in reverse order for (unsigned int i = queued; i > 0; i--) { - //since we only unqueue 1 buffer, it's OK to use singular variable pointer instead of array alSourceUnqueueBuffers(source, 1, &buffer); unusedBufferPush(buffer); } diff --git a/src/modules/audio/openal/Source.h b/src/modules/audio/openal/Source.h index 32158c0be..4b06a5414 100644 --- a/src/modules/audio/openal/Source.h +++ b/src/modules/audio/openal/Source.h @@ -131,9 +131,9 @@ public: virtual float getMaxDistance() const; virtual int getChannels() const; - virtual bool isQueueable() const; - virtual bool queueData(void *data, int length, int dataSampleRate, int dataBitDepth, int dataChannels); - virtual bool queueDataAtomic(void *data, ALsizei length); + virtual int getFreeBufferCount() const; + virtual bool queue(void *data, int length, int dataSampleRate, int dataBitDepth, int dataChannels); + virtual bool queueAtomic(void *data, ALsizei length); void prepareAtomic(); void teardownAtomic(); diff --git a/src/modules/audio/wrap_Audio.cpp b/src/modules/audio/wrap_Audio.cpp index 68e6dcaef..f7e7bedda 100644 --- a/src/modules/audio/wrap_Audio.cpp +++ b/src/modules/audio/wrap_Audio.cpp @@ -44,41 +44,57 @@ int w_getSourceCount(lua_State *L) int w_newSource(lua_State *L) { - Source *t = 0; - - if (lua_isnumber(L, 1) && lua_isnumber(L, 2) && lua_isnumber(L, 3)) - luax_catchexcept(L, [&]() { - t = instance()->newSource((int)lua_tonumber(L, 1), (int)lua_tonumber(L, 2), (int)lua_tonumber(L, 3)); - }); - else - { - Source::Type stype = Source::TYPE_STREAM; + Source::Type stype = Source::TYPE_STREAM; - const char *stypestr = lua_isnoneornil(L, 2) ? 0 : lua_tostring(L, 2); + if (!luax_istype(L, 1, SOUND_SOUND_DATA_ID) && !luax_istype(L, 1, SOUND_DECODER_ID)) + { + const char *stypestr = luaL_checkstring(L, 2); if (stypestr && !Source::getConstant(stypestr, stype)) return luaL_error(L, "Invalid source type: %s", stypestr); - - if (lua_isstring(L, 1) || luax_istype(L, 1, FILESYSTEM_FILE_ID) || luax_istype(L, 1, FILESYSTEM_FILE_DATA_ID)) - luax_convobj(L, 1, "sound", "newDecoder"); - - if (stype == Source::TYPE_STATIC && luax_istype(L, 1, SOUND_DECODER_ID)) - luax_convobj(L, 1, "sound", "newSoundData"); - - luax_catchexcept(L, [&]() { - if (luax_istype(L, 1, SOUND_SOUND_DATA_ID)) - t = instance()->newSource(luax_totype(L, 1, SOUND_SOUND_DATA_ID)); - else if (luax_istype(L, 1, SOUND_DECODER_ID)) - t = instance()->newSource(luax_totype(L, 1, SOUND_DECODER_ID)); - }); } - if (t) + + if (lua_isstring(L, 1) || luax_istype(L, 1, FILESYSTEM_FILE_ID) || luax_istype(L, 1, FILESYSTEM_FILE_DATA_ID)) + luax_convobj(L, 1, "sound", "newDecoder"); + + if (stype == Source::TYPE_STATIC && luax_istype(L, 1, SOUND_DECODER_ID)) + luax_convobj(L, 1, "sound", "newSoundData"); + + Source *t = nullptr; + + luax_catchexcept(L, [&]() { + if (luax_istype(L, 1, SOUND_SOUND_DATA_ID)) + t = instance()->newSource(luax_totype(L, 1, SOUND_SOUND_DATA_ID)); + else if (luax_istype(L, 1, SOUND_DECODER_ID)) + t = instance()->newSource(luax_totype(L, 1, SOUND_DECODER_ID)); + }); + + if (t != nullptr) { luax_pushtype(L, AUDIO_SOURCE_ID, t); t->release(); return 1; } else - return luax_typerror(L, 1, "Decoder, SoundData or format description"); + return luax_typerror(L, 1, "Decoder or SoundData"); +} + +int w_newQueueableSource(lua_State *L) +{ + Source *t = nullptr; + + if (lua_isnumber(L, 1) && lua_isnumber(L, 2) && lua_isnumber(L, 3)) + luax_catchexcept(L, [&]() { + t = instance()->newSource((int)lua_tonumber(L, 1), (int)lua_tonumber(L, 2), (int)lua_tonumber(L, 3)); + }); + + if (t != nullptr) + { + luax_pushtype(L, AUDIO_SOURCE_ID, t); + t->release(); + return 1; + } + else + return luaL_error(L, "Wrong type of arguments to function call."); } static std::vector readSourceList(lua_State *L, int n) @@ -310,6 +326,7 @@ static const luaL_Reg functions[] = { { "getSourceCount", w_getSourceCount }, { "newSource", w_newSource }, + { "newQueueableSource", w_newQueueableSource }, { "play", w_play }, { "stop", w_stop }, { "pause", w_pause }, diff --git a/src/modules/audio/wrap_Source.cpp b/src/modules/audio/wrap_Source.cpp index bf4b4f705..605197f9d 100644 --- a/src/modules/audio/wrap_Source.cpp +++ b/src/modules/audio/wrap_Source.cpp @@ -330,34 +330,50 @@ int w_Source_getChannels(lua_State *L) return 1; } -int w_Source_isQueueable(lua_State *L) +int w_Source_getFreeBufferCount(lua_State *L) { Source *t = luax_checksource(L, 1); - luax_pushboolean(L, t->isQueueable()); + lua_pushinteger(L, t->getFreeBufferCount()); return 1; } -int w_Source_queueData(lua_State *L) +int w_Source_queue(lua_State *L) { Source *t = luax_checksource(L, 1); bool success; - luax_catchexcept(L, [&]() { - if (luax_istype(L, 2, SOUND_SOUND_DATA_ID)) - { - love::sound::SoundData *s = luax_totype(L, 2, SOUND_SOUND_DATA_ID); - success = t->queueData(s->getData(), lua_isnumber(L, 3) ? (int)lua_tonumber(L, 3) : s->getSize(), s->getSampleRate(), s->getBitDepth(), s->getChannels()); - } - else if (lua_islightuserdata(L, 2)) - { - if (lua_isnumber(L, 4) && lua_isnumber(L, 5) && lua_isnumber(L, 6)) - success = t->queueData(lua_touserdata(L, 2), (int)lua_tonumber(L, 3), (int)lua_tonumber(L, 4), (int)lua_tonumber(L, 5), (int)lua_tonumber(L, 6)); - else - return luaL_error(L, "No format specified."); - } - else - return luaL_error(L, "Invalid data type."); - }); + if (luax_istype(L, 2, SOUND_SOUND_DATA_ID)) + { + love::sound::SoundData *s = luax_totype(L, 2, SOUND_SOUND_DATA_ID); + + int length = lua_isnumber(L, 4) ? lua_tonumber(L, 4) : ( lua_isnumber(L, 3) ? lua_tonumber(L, 3) : s->getSize() ); + int offset = lua_isnumber(L, 4) ? lua_tonumber(L, 3) : 0; + + if (length > s->getSize() - offset || offset < 0 || length < 0) + return luaL_error(L, "Data region out of bounds."); + + luax_catchexcept(L, [&]() { + success = t->queue((void*)((uintptr_t)s->getData() + (uintptr_t)offset), + length, s->getSampleRate(), s->getBitDepth(), s->getChannels()); + }); + } + else if (lua_islightuserdata(L, 2)) + { + if (!(lua_isnumber(L, 3) && lua_isnumber(L, 4))) + return luaL_error(L, "No region specified."); + if (!(lua_isnumber(L, 5) && lua_isnumber(L, 6) && lua_isnumber(L, 7))) + return luaL_error(L, "No format specified."); + if (lua_tonumber(L, 3) < 0 || lua_tonumber(L, 4) < 0) + return luaL_error(L, "Data region out of bounds."); + + luax_catchexcept(L, [&]() { + success = t->queue((void*)((uintptr_t)lua_touserdata(L, 2) + (uintptr_t)lua_tonumber(L, 3)), + lua_tonumber(L, 4), (int)lua_tonumber(L, 5), (int)lua_tonumber(L, 6), (int)lua_tonumber(L, 7)); + }); + } + else + return luax_typerror(L, 1, "Sound Data or lightuserdata"); + luax_pushboolean(L, success); return 1; } @@ -415,8 +431,8 @@ static const luaL_Reg w_Source_functions[] = { "getChannels", w_Source_getChannels }, - { "isQueueable", w_Source_isQueueable }, - { "queueData", w_Source_queueData }, + { "getFreeBufferCount", w_Source_getFreeBufferCount }, + { "queue", w_Source_queue }, { "getType", w_Source_getType },