Sign in to follow this  
Deliverance

Sound Streaming & Multithreading

Recommended Posts

To be as specific as i can, suppose i manage a bunch of sound streams and i play and update them using openal. Every sound stream is updated in it's own thread. Let's assume the following pseudocode where alFunctionX is just a function specific to openal. This code runs in the main thread(the main program's thread):
Thread A
1. Init();
2. while (isRunning)
3. {
4.     Update();

5.       DisplayOrSomething();

6.       if (bDeinitializeOpenAl)      // did someone said to deinitialize openal?
7.           DeInitializeOpenAl();
8. }


This code runs for every sound stream(in a separate thread for every stream)

Thread Sound_i, with i>=1
void ThreadUpdateStreamFunction()
{
0.    alFunctionX();
1.    ....
2.    alFunctionX();
3.    ....
4.    ....     //   some number of lines with possibily other calls but not 
5.    ....       //          involving openal
6.    alFunctionX();
}



Now say that openal is deinitialized at ine 7 in Thread A, and some Thread Sound_x is running and arrives at line 5. There is no call to openal specific functions there. But it continues running andarrives at line 6 interacting with the deinitialized openal. My question is: how should i signal to every thread that openal has deinitialized? Say i use a global boolean variable isOpelAlAlive, booleans read/write is atomic as far as i read so no problems that two threads will try to access in the same time. Now the solution i came up is to verify before every call to openal that it's still alive, quit if it's not and proceed if it is. Is this the way to do it? The code would look like this:
Thread Sound_i, with i>=1
void ThreadUpdateStreamFunction()
{
0.'   if (isOpenAlAlive)
0.        alFunctionX();
1.    ....
2'.   if (isOpenAlAlive)
2.    alFunctionX();
3.    ....
4.    ....     //   some number of lines with possibily other calls but not 
5.    ....       //          involving openal
6'.   if (isOpenAlAlive)
6.    alFunctionX();
}



One thing that i noticed is that in every thread Sound_i i need to put a sleep before doing any calculations because otherwise the application is running really slow. Why is that? Creating a hello world with this line of code
while (1);



runs more smoothly than when putting that line of code in a thread. Am i missing something? I must admit i'm quite a beginner when it comes to multithreading :D [Edited by - Deliverance on March 12, 2009 8:42:11 AM]

Share this post


Link to post
Share on other sites
Quote:
Original post by Deliverance
Say i use a global boolean variable isOpelAlAlive, booleans read/write is atomic as far as i read so no problems that two threads will try to access in the same time.

Reading a boolean may well be atomic, under certain conditions. But even if it is, you can't guarantee the boolean hasn't changed by the time you execute your next statement, eg. alFunctionX could run when isOpenAlAlive is now false.

Share this post


Link to post
Share on other sites
I have only a cursory understanding of OpenAL, but when you say that you have a thread *per stream,* are you referring to a setup where each possible sound/voice has a separate thread dedicated to it? If so, that's a bad idea, and would certainly explain why you're slowing down-- it's the rough equivalent to running a number of full programs equal to the number of sources you have going. Obviously, this is going to bog things down.

If you're looking to get the most out of parallelism, start with the idea of creating N-1 threads. (where N is the number of cores present in the machine running your program) Thus, you now have one thread per core (Don't forget-- your main thread is a thread too! :) )

You then need to use these for everything in your app-- you more or less do things the way you would normally; look into something called a 'thread pool' to elegantly handle multiple threads working to achieve an arbitrary number of tasks.

Also, I *strongly, strongly, STRONGLY* suggest you build a good understanding of synchronization if you don't have one already. If you're looking for a starting point, read up on mutexes/critical sections, interlocked/atomic operations and this:
http://www.flounder.com/no_synchronization.htm
(though it is certainly better to err on the side of caution when starting out, i.e. lock more than you should :) )

Best of luck in your multithreaded endeavors.

Share this post


Link to post
Share on other sites
What you probably really want is a single thread to manage all your sounds, not a random collection of threads, one for each stream.
If you keep with the massive number of threads, you atleast need to make the main sound thread aware of all other sound threads, so you can wait on their completion before calling DeInitializeOpenAL().
really, it should be more along the lines of:
while (isSoundRunning)
{
///
}
WaitOnMultipleObjects( otherSoundThreads, INFINITY );
DeInitializeOpenAl();

Share this post


Link to post
Share on other sites
Quote:
Original post by Kylotan
Quote:
Original post by Deliverance
Say i use a global boolean variable isOpelAlAlive, booleans read/write is atomic as far as i read so no problems that two threads will try to access in the same time.

Reading a boolean may well be atomic, under certain conditions. But even if it is, you can't guarantee the boolean hasn't changed by the time you execute your next statement, eg. alFunctionX could run when isOpenAlAlive is now false.


You are correct. Locking the variable would solve this issue i guess.

Quote:

I have only a cursory understanding of OpenAL, but when you say that you have a thread *per stream,* are you referring to a setup where each possible sound/voice has a separate thread dedicated to it? If so, that's a bad idea, and would certainly explain why you're slowing down-- it's the rough equivalent to running a number of full programs equal to the number of sources you have going. Obviously, this is going to bog things down.


Well there are only 8 streams in my application each with one seperate thread. The performance decrease problem only occurs on a low spec hyper threaded processor and only on certain .ogg files(big ones ~ 3 mb). Each thread sleeps for 0.1 seconds before doing computations only a fraction of a second(let's say like 5-20 ms). Every time 40 kb of compressed sound are read from disk(or from the buffer) and are decoded, in less than 0.1 second but representing more than 0.1 seconds of sound.

Quote:

You then need to use these for everything in your app-- you more or less do things the way you would normally; look into something called a 'thread pool' to elegantly handle multiple threads working to achieve an arbitrary number of tasks.


Yeah, this is a good idea. c# has this facility out of the box but i guess it'll be an interesting exercise to do it in C++.

Quote:

Best of luck in your multithreaded endeavors.


Thanks! :D.

Quote:

What you probably really want is a single thread to manage all your sounds, not a random collection of threads, one for each stream.
If you keep with the massive number of threads, you atleast need to make the main sound thread aware of all other sound threads, so you can wait on their completion before calling DeInitializeOpenAL().
really, it should be more along the lines of:
while (isSoundRunning)
{
///
}
WaitOnMultipleObjects( otherSoundThreads, INFINITY );
DeInitializeOpenAl();


Yes,it's a fast way to do solve my issue, thanks.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this