How to block a function

Apr 4, 2012 at 6:17pm
I have a std::queue of sounds to play (in OpenAL) and I need to know how to block my threaded function so that I don't end up playing all of the sounds in the queue at the same time.

I want to block at line 38 until the sound is done playing. Any pointers? (Pun intended).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <queue>
#inlcude <boost/thread>
#include <al/al.h>
#include <al/alc.h>
#include "cSoundObject.h"

void PopulateSndBuf(std::queue<cSoundObject> &SNDBUF);
void play_sounds   (std::queue<cSoundObject> &SNDBUF);

int main()
{
	std::queue<cSoundObject> SNDBUF;
	
	while(true)
	{
		PopulateSndBuf(SNDBUF); // Might add something to the sound buffer.
		
		static bool playing = false;
		if (!SNDBUF.empty() && !playing) // Only call this function if SNDBUF is not empty and not playing
		{
			playing = true;
			boost::thread sndthrd(play_sounds,boost::ref(SNDBUF));
		}
		
		if (SNDBUF.empty())	playing = false;
			
		Sleep(16); // Runs according to a real-time scheduler, not really this
	}
}

void play_sounds(std::queue<cSoundIF> &SNDBUF)
{
	while(!SNDBUF.empty())
	{
		ALuint source = SNDBUF.front()->ALsource());
		alSourcePlay(source); // Starts playing the sound
		
		// WAIT UNTIL SOUND IS DONE PLAYING
		
		SNDBUF.pop();		
	}
}
Last edited on Apr 4, 2012 at 6:32pm
Apr 4, 2012 at 7:04pm
Why would you create al those threads in the first place if you don't want them to run at the same time?

Why not create one thread to play sounds from a queue (which I think is what you want)?
Apr 4, 2012 at 7:05pm
I know the length of the WAVE files so I could just do something like:

1
2
3
4
5
double timer = 0.;
while(timer < SNDBUF.front().length())
{
    timer += dTime; // dTime would increment based on a timer.
}


But this has two problems:
1) It'll eat up all available processor time.
2) A signal from OpenAL would have less chance of deviating from what we are actually hearing.
Apr 4, 2012 at 7:12pm
I didn't see your post there for a moment kbw.

I thought I was creating only one thread by using bool playing to prevent creating a new one until the sound buffer was empty. Are you saying there is a simpler way of doing this?

Regardless, I think my base question still stands..
Last edited on Apr 4, 2012 at 7:17pm
Apr 4, 2012 at 7:18pm
I don't think that's what you're doing.

You probably should create the thread at the start of the program, then just add items to the queue while play_sounds just plays the next item from the queue.

You will need to synchronise access to the queue.
Apr 4, 2012 at 7:23pm
That would leave me with this. Wouldn't this make the thread take all remaining processing time? Also, I am still not sure how to tell if the sound is complete so that I should pop the last one and play the next.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <queue>
#inlcude <boost/thread>
#include <al/al.h>
#include <al/alc.h>
#include "cSoundObject.h"

void PopulateSndBuf(std::queue<cSoundObject> &SNDBUF);
void play_sounds   (std::queue<cSoundObject> &SNDBUF);

int main()
{
	std::queue<cSoundObject> SNDBUF;
	
	boost::thread sndthrd(play_sounds,boost::ref(SNDBUF));
	
	while(true)
	{
		PopulateSndBuf(SNDBUF); // Might add something to the sound buffer.
		Sleep(16); // Runs according to a real-time scheduler, not really this
	}
}

void play_sounds(std::queue<cSoundIF> &SNDBUF)
{
	while(true)
	{
		ALuint state;
		alGetSourcei(source, AL_SOURCE_STATE, &state);

		if(!SNDBUF.empty() && state != AL_PLAYING)
		{
			ALuint source = SNDBUF.front()->ALsource());
			alSourcePlay(source); // Starts playing the sound
			SNDBUF.pop();		// Pops the queue
		}
	}
}


Edit: I figured how to determine if the sound is done, but while loops are not really a process' friend.
Last edited on Apr 4, 2012 at 7:31pm
Apr 4, 2012 at 7:29pm
You don't need that Sleep call. You do need to synchronise use of the queue, a mutex would be suitable.
Apr 4, 2012 at 7:32pm
Thanks. Still learning about threading, I'll look up mutex's.

The main application doesn't actually use a sleep command, this is part of a dll where the "main" function is called by a real-time process at a rate of 60Hz. I'll figure it out.
Last edited on Apr 4, 2012 at 7:33pm
Topic archived. No new replies allowed.