3

I cant ensure this by checking if the sound has stopped in my program because the sounds are handled in different thread, isnt that right?

So the problem comes when i want to be 100% sure that once a sound has stopped from playing, another sound would start instantly after it with no possibility for any delay.

The second sound will be looping sound type, so i cant just glue the two sounds together.

How can i do this?

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
Rookie
  • 119
  • 4

1 Answers1

2

I am not aware of any function in OpenAL that would let you do such a thing direcly, e.g. by blocking or notifying you, so gapless playback in a way as you said would be possible. Any solution like "sleep for the duration of the first sound, then start the second" is bound to fail, because sleep is not reliable. Checking repeatedly whether the source has stopped playing will not work either, because at the time you see that the source is done, there is already an audible gap.

However, you can get this to work indirectly by using alSourceQueueBuffers once with the first sound, and once with the second (looping) sound.

Start playing the source.

Then regularly call alGetSourcei(source, AL_BUFFERS_PROCESSED, &num_done). You don't need to call it all the time, just more often than the duration of your loop sound.

If this tells you that a buffer is done, unqueue it. That's the first sound done, and the second one is playing right now. Now, quickly queue the buffer holding the second sound again, and keep queueing/unqueueing as long as you want the sound to loop.

Damon
  • 67,688
  • 20
  • 135
  • 185
  • i tried searching the documents, but i cannot find a reference how to unqueue a buffer, any help? – Rookie May 04 '11 at 18:59
  • `alSourceUnqueueBuffers`, [chapter 4.3.5](http://connect.creativelabs.com/openal/Documentation/OpenAL%201.1%20Specification.htm#_Toc199835885) – Damon May 04 '11 at 19:09
  • oh well, windows search apparently just sucks, sorry. – Rookie May 05 '11 at 11:15
  • i dont quite understand this method anyways, why i need to call alSourceQueueBuffers() twice in the same source? atm i just do alSourceQueueBuffers() once with an array that has two buffer ID's in it. also, isnt there a chance i play the sound incorrectly if my game lags? because you are relying to "quickly" do something. are you relying this looping on that i will make sure the sound loops? instead of using AL_LOOPING ? – Rookie May 05 '11 at 13:49
  • When you play a source from a buffer, it eventually reaches the end, and then there is silence. You wanted to play another sound immediately, i.e. **without** silence in between. The only reliable way to do that is to queue at least two buffers. When the first one is used up (which you can query), OpenAL will seamlessly continue playing the second one. So there is no silence, and you have time to queue another buffer while the second one is playing (and you can repeat that for as long as you want). – Damon May 05 '11 at 16:47
  • i fail to understand this idea, can you make some pseudo code? i really dont get this. with all the logic, there will be a possibility for a gap in the sound. – Rookie May 05 '11 at 18:31
  • I can confirm Damon's answer, I have used this same technique for this exact purpose. You might want to add that the identifiers returned by alSourceUnqueueBuffers are NOT reliable, so if you start to see crashes from alSourceQueueBuffers then either change some parameters (buffer length, number of buffers) or keep track of the identifiers yourself in a queue mirroring what you're doing with alSourceQueueBuffers. – ZoFreX May 05 '11 at 23:09
  • @ZoFreX, did you have to make the second sound looping? i dont see how it could be gapless if i have to programmatically check every now and then when the sound has ended and play it again. the looping sounds are about 0.1 seconds long, or less... – Rookie May 06 '11 at 11:16
  • 0.1 seconds (100ms) are an eternity for a computer. Most applications work on much shorter intervals, such as for example 16ms frames. In that exemplary case, if you check once per frame, that's about 6 checks during the lifetime of a loop sound. With another one queued, that's 13 checks before an audible gap appears. – Damon May 06 '11 at 11:29
  • It is easy to make sure that this cannot happen (other than the user suspending the process or pulling the power cord) by separating tasks that _can_ and _will_ block indefinitely (network, disk) from tasks that must not block (visuals, audio) using separate threads. If blocking for one second is something that can be reasonably expected to happen in your program, then an audible gap is the least of your problems, tbh. – Damon May 06 '11 at 12:10
  • Rookie: I used fixed length buffers and wrote the audio data into them... as long as there is always data going in, there is always sound coming out, without gaps. You don't react in any way to one sound ending and another beginning, in fact you don't even know exactly when it happens - you just give OpenAL buffers and say "please play these at some point in the immediate future". – ZoFreX May 06 '11 at 12:13
  • so the way to minimize the gaps is to repeat many times the buffer data which will be looping? – Rookie May 06 '11 at 12:19