issues addressed

warnings fixed
added type checking to Lua functions
stopping queueable source clears buffered data
getting queueable source to auto-play if it underruns and then gets re-filled
will probably require re-designing pool usage strategy

--HG--
branch : minor
This commit is contained in:
rcoaxil
2016-10-13 18:18:08 +03:00
parent b757a0534e
commit 00c02adcd0
4 changed files with 65 additions and 45 deletions
+39 -27
View File
@@ -362,7 +362,7 @@ bool Source::update()
offsetSamples += (curOffsetSamples - newOffsetSamples);
offsetSeconds += (curOffsetSecs - newOffsetSecs);
for (unsigned int i = 0; i < processed; i++)
for (unsigned int i = 0; i < (unsigned int)processed; i++)
unusedBufferPush(buffers[i]);
while (unusedBufferPeek() != AL_NONE)
@@ -384,7 +384,7 @@ bool Source::update()
alGetSourcei(source, AL_BUFFERS_PROCESSED, &processed);
alSourceUnqueueBuffers(source, processed, buffers);
for (unsigned int i = 0; i < processed; i++)
for (unsigned int i = 0; i < (unsigned int)processed; i++)
{
ALint size;
alGetBufferi(buffers[i], AL_SIZE, &size);
@@ -393,6 +393,8 @@ bool Source::update()
}
return !isFinished();
}
case TYPE_MAX_ENUM:
break;
}
return false;
@@ -505,6 +507,8 @@ void Source::seekAtomic(float offset, void *unit)
offsetSeconds = offsetSamples / sampleRate;
}
break;
case TYPE_MAX_ENUM:
break;
}
}
@@ -742,13 +746,12 @@ bool Source::queueAtomic(void *data, ALsizei length)
}
else
{
//remaining buffers are stored beyond the tail of unused stack
if (unusedBufferTop >= (int)MAX_BUFFERS - 1)
ALuint buffer = unusedBufferPeekNext();
if (buffer == AL_NONE)
return false;
ALuint buffer = unusedBuffers[unusedBufferTop + 1];
//stack acts as queue while stopped
alBufferData(buffer, getFormat(channels, bitDepth), data, length, sampleRate);
//new buffer must go last, so it goes to the base of the stack
unusedBufferQueue(buffer);
}
bufferedBytes += length;
@@ -765,7 +768,10 @@ int Source::getFreeBufferCount() const
return unusedBufferTop + 1;
case TYPE_QUEUE:
return valid ? unusedBufferTop + 1 : (int)MAX_BUFFERS - unusedBufferTop - 1;
case TYPE_MAX_ENUM:
return 0;
}
return 0;
}
void Source::prepareAtomic()
@@ -807,7 +813,10 @@ void Source::prepareAtomic()
if (offsetSamples >= 0)
alSourcef(source, AL_SAMPLE_OFFSET, offsetSamples);
break;
}
case TYPE_MAX_ENUM:
break;
}
}
@@ -823,40 +832,38 @@ void Source::teardownAtomic()
ALint queued;
ALuint buffer;
decoder->seek(0);
// drain buffers
//since we only unqueue 1 buffer, it's OK to use singular variable pointer instead of array
alGetSourcei(source, AL_BUFFERS_QUEUED, &queued);
for (unsigned int i = 0; i < queued; i++)
{
//since we only unqueue 1 buffer, it's OK to use singular variable pointer instead of array
for (unsigned int i = 0; i < (unsigned int)queued; i++)
alSourceUnqueueBuffers(source, 1, &buffer);
unusedBufferPush(buffer);
}
// generate unused buffers list
for (unsigned int i = 0; i < MAX_BUFFERS; i++)
unusedBuffers[i] = streamBuffers[i];
unusedBufferTop = MAX_BUFFERS - 1;
break;
}
case TYPE_QUEUE:
{
ALint queued;
ALuint buffers[MAX_BUFFERS];
ALuint buffer;
int unused = 0;
//store all unused buffers, also clear stack
while (unusedBufferPeek() != AL_NONE)
buffers[unused++] = *unusedBufferPop();
alGetSourcei(source, AL_BUFFERS_QUEUED, &queued);
//stack needs to be filled in reverse order
for (unsigned int i = queued; i > 0; i--)
{
for (unsigned int i = (unsigned int)queued; i > 0; i--)
alSourceUnqueueBuffers(source, 1, &buffer);
unusedBufferPush(buffer);
}
// put unused buffers at the end of stack
for (unsigned int i = 0; i < unused; i++)
unusedBuffers[unusedBufferTop + 1 + i] = buffers[i];
// generate unused buffers list
for (unsigned int i = 0; i < MAX_BUFFERS; i++)
unusedBuffers[i] = streamBuffers[i];
unusedBufferTop = -1;
break;
}
case TYPE_MAX_ENUM:
break;
}
alSourcei(source, AL_BUFFER, AL_NONE);
@@ -1043,6 +1050,11 @@ ALuint Source::unusedBufferPeek()
return (unusedBufferTop < 0) ? AL_NONE : unusedBuffers[unusedBufferTop];
}
ALuint Source::unusedBufferPeekNext()
{
return (unusedBufferTop >= (int)MAX_BUFFERS - 1) ? AL_NONE : unusedBuffers[unusedBufferTop + 1];
}
ALuint *Source::unusedBufferPop()
{
return &unusedBuffers[unusedBufferTop--];
+3 -3
View File
@@ -165,6 +165,7 @@ private:
int streamAtomic(ALuint buffer, love::sound::Decoder *d);
ALuint unusedBufferPeek();
ALuint unusedBufferPeekNext();
ALuint *unusedBufferPop();
void unusedBufferPush(ALuint buffer);
void unusedBufferQueue(ALuint buffer);
@@ -177,9 +178,6 @@ private:
ALuint streamBuffers[MAX_BUFFERS];
ALuint unusedBuffers[MAX_BUFFERS];
int unusedBufferTop;
ALsizei bufferedBytes;
StrongRef<StaticDataBuffer> staticBuffer;
float pitch;
@@ -212,6 +210,8 @@ private:
StrongRef<love::sound::Decoder> decoder;
unsigned int toLoop;
int unusedBufferTop;
ALsizei bufferedBytes;
}; // Source
} // openal
+4 -5
View File
@@ -82,10 +82,9 @@ 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));
});
luax_catchexcept(L, [&]() {
t = instance()->newSource((int)luaL_checknumber(L, 1), (int)luaL_checknumber(L, 2), (int)luaL_checknumber(L, 3));
});
if (t != nullptr)
{
@@ -94,7 +93,7 @@ int w_newQueueableSource(lua_State *L)
return 1;
}
else
return luaL_error(L, "Wrong type of arguments to function call.");
return 0; //all argument type errors are checked in above constructor
}
static std::vector<Source*> readSourceList(lua_State *L, int n)
+19 -10
View File
@@ -346,10 +346,18 @@ int w_Source_queue(lua_State *L)
{
love::sound::SoundData *s = luax_totype<love::sound::SoundData>(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;
int offset = 0;
int length = s->getSize();
if (length > s->getSize() - offset || offset < 0 || length < 0)
if (lua_gettop(L) == 4)
{
offset = luaL_checknumber(L, 3);
length = luaL_checknumber(L, 4);
}
else if (lua_gettop(L) == 3)
length = luaL_checknumber(L, 3);
if (length > (int)s->getSize() - offset || offset < 0 || length < 0)
return luaL_error(L, "Data region out of bounds.");
luax_catchexcept(L, [&]() {
@@ -359,16 +367,17 @@ int w_Source_queue(lua_State *L)
}
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)
int offset = luaL_checknumber(L, 3);
int length = luaL_checknumber(L, 4);
int sampleRate = luaL_checknumber(L, 5);
int bitDepth = luaL_checknumber(L, 6);
int channels = luaL_checknumber(L, 7);
if (length < 0 || offset < 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));
success = t->queue((void*)((uintptr_t)lua_touserdata(L, 2) + (uintptr_t)offset), length, sampleRate, bitDepth, channels);
});
}
else