ResumeChannel fails under OpenAL

Archives Forums/BlitzMax Bug Reports/ResumeChannel fails under OpenAL

GfK(Posted 2010) [#1]
I'm just adding a pause function for my game and discovered that ResumeChannel (or possibly PauseChannel) does not work correctly under OpenAL.

Load a sound of your choice in the code below, and press P to pause/unpause. It works fine while the sound is still playing. Now wait for the sound to end, and press P to pause/unpause. When I unpause now, the sound starts playing again but it should not, as its ended.

This code works as expected under the default driver (whatever that is these days)

I'm using Windows 7.

Graphics 400,300
EnableOpenALAudio()
SetAudioDriver("OpenAL Generic Software")

Local snd:TSound = LoadSound("newitem.ogg")

Local channel:TChannel = New TChannel

channel = PlaySound(snd)

Local paused:Byte	


While Not KeyDown(key_escape)
	If KeyHit(key_p)
		paused = 1 - paused
		If paused = True
			PauseChannel(channel)
		Else
			ResumeChannel(channel)
		EndIf
	EndIf
	
	Cls
	DrawText "Paused: " + paused,50,50
	Flip
	
Wend


[edit]

Tested with the following:
OpenAL Generic Software - Fails
OpenAL - Fails
OpenAL Default - Fails
FreeAudio - Works
FreeAudio Multimedia - Works
FreeAudio DirectSound - Works
DirectSound - Works


Dabhand(Posted 2010) [#2]
I 'think' I've seen this before, and as such, its a bug in OpenAL itself, rather then BlitzMax.

Dabz


GfK(Posted 2010) [#3]
Dunno. Just tested in XP too - fails the same as above.


Yan(Posted 2010) [#4]
OpenALAudio.BMX>TOpenALChannel...
Method SetPaused( paused )
  If _seq<>_source._seq Return

  If paused
    alSourcePause _source._id
  Else
    If _source.Paused() Then alSourcePlay _source._id
  EndIf
End Method



GfK(Posted 2010) [#5]
Awesome! Thanks Ian!

Can this be put in an official release, please? :D


marksibly(Posted 2010) [#6]
Hi,

Yep, in for 1.38!


GfK(Posted 2010) [#7]
Wait a minute.... I think this has caused a new problem. (Sorry Mark - tested with the original code I reported the bug with - which did appear to be fixed)

Using the code below, I only get sound for the first few (3) times I press X. After that - nothing.

Graphics 800,600
EnableOpenALAudio()
SetAudioDriver("OpenAL Generic Software")

Local snd:TSound = LoadSound("chain.ogg")

While Not KeyDown(key_escape)
	If KeyHit(key_x)
		PlaySound snd
	EndIf
	Delay 1
Wend



Yan(Posted 2010) [#8]
Hmm...You can only play a new sound whilst the initial sound is still playing.:o/


I know next to nothing about OpenAL's inner workings but it appears that you can only pause a source when it's state is either AL_INITIAL or AL_PLAYING. Once the assigned buffer has played through, the state is set to AL_STOPPED. This means that subsequent calls to TOpenALChannel.Cue(), via TOpenALSound.Play(), don't pause the source.

The source has to be rewound, thus forcing an AL_INITIAL state, *only* when TOpenALChannel.Cue() is called via TOpenSound.Play(). Unfortunately I can't yet see a 'nice' way to implement this.


In the mean time, here's a bodge...

In OpenALAudio.BMX

TOpenALChannel
Method Rewind()
  If _seq<>_source._seq Return

  alSourceRewind _source._id
End Method

Method SetPaused( paused )
  If _seq<>_source._seq Return

  If paused
    alSourcePause _source._id
  Else
    If _source.Paused() Then alSourcePlay _source._id
  EndIf
End Method

TOpenALSound
Method Play:TOpenALChannel( alloced_channel:TChannel=Null )
  Local t:TOpenALChannel=Cue( alloced_channel )
  t.Rewind()
  t.SetPaused False
  Return t
End Method


I don't really have any BMX code that uses the sound system to any great extent, so can't easily test this fully myself.


GfK(Posted 2010) [#9]
It seems to be working fine here with that code. Here's the modified, horrible test code I'm using if you wanna give it a try (obviously this only pauses one channel so if you've jabbed the X key a few times, then press P, some sounds will still run).
Graphics 400, 300
EnableOpenALAudio()
SetAudioDriver("openal generic software")
Local snd:TSound = LoadSound("select.ogg")

Local channel:TChannel = New TChannel

channel = PlaySound(snd)

Local paused:Byte	


While Not KeyDown(key_escape)
	If KeyHit(key_x)
		channel = PlaySound(snd)
	EndIf
	If KeyHit(key_p)
		paused = 1 - paused
		If paused = True
			PauseChannel(channel)
		Else
			ResumeChannel(channel)
		EndIf
	EndIf
	
	Cls
	DrawText "Paused: " + paused,50,50
	Flip
	
Wend



marksibly(Posted 2010) [#10]
Hi,

Slightly simpler fix in TOpenALChannel - use with Yan's first SetPaused() fix above:

	Method Cue( sound:TOpenALSound )	
		If _seq<>_source._seq Return

		_source._sound=sound
		alSourceRewind _source._id
		alSourcei _source._id,AL_LOOPING,sound._loop
		alSourcei _source._id,AL_BUFFER,sound._buffer
	End Method



GfK(Posted 2010) [#11]
Cor... took me ages to even spot the difference with that!

Trying now... completely buggered it up so just reinstalling!

[edit] Got it sorted in the end. Having trouble even copying/pasting today.

With Yan's SetPaused() and your Cue(), all seems good now. Thanks for your help!


Yan(Posted 2010) [#12]
LOL...That was my first solution too. Unfortunately, I'd somehow got it into my head that CueSound() shouldn't *always* restart the sample, but of course it should...Doh!


GfK(Posted 2010) [#13]
Just a lil update - been using this in my game for the past two days without any apparent errors whatsoever (you said it was a bodge - but whatever's bodgy about it, it works really well)


Yan(Posted 2010) [#14]
The use of alSourceRewind is quite correct.

It was my implementation, due to a misunderstanding of how CueSound() is supposed to work (brain spasm), that I considered to be a bodge. See my previous post.

Now, can we just forget the whole thing. ;o)
Wanders off, whistling at the ceiling