Browse Source

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
rcoaxil 8 years ago
parent
commit
00c02adcd0

+ 39 - 27
src/modules/audio/openal/Source.cpp

@@ -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
src/modules/audio/openal/Source.h

@@ -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
src/modules/audio/wrap_Audio.cpp

@@ -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
src/modules/audio/wrap_Source.cpp

@@ -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