OpenAL channel bug. Please help me test.

BlitzMax Forums/BlitzMax Programming/OpenAL channel bug. Please help me test.

Grey Alien(Posted 2007) [#1]
I believe I've got to the route of a problem I encountered a while back with Open AL.

Basically there is a 256 channel limit which is reached EVEN IF you use Stop Channel to free up a channel for reuse.

Get this sample:

http://www.greyaliengames.com/misc/test.wav

and put it in the same folder as the test app:

and if you don't have OpenAL installed, put these in the same folder as the app:

http://www.greyaliengames.com/misc/OpenAL.zip (234k)

Strict

EnableOpenALAudio()
SetAudioDriver("OpenAL Generic Software") 'comment this out for no crash

Const MAX_CHANNELS=16
Global channels:TChannel[MAX_CHANNELS]
Global CurrentChannel=0

Local sound:TSound = LoadSound("test.wav")

Local Counter=0
Local total=0
Const TEST_VALUE = 16 'anything up to and including 15 will result in a sound, anything over will not.

Graphics 400,300,0

While Not KeyHit(KEY_ESCAPE)
	Cls
	Counter:+1
	If Counter=5 Then
		If Total<TEST_VALUE Then
			CreateChannels()		
			KillChannels()
			Counter=0
		ElseIf total=TEST_VALUE
			CreateChannels()		
			Play(Sound)			
		EndIf
		Total:+1
	EndIf
	DrawText Total,10,10
	DrawText CurrentChannel,10,30
	Flip
Wend

Function Play(sample:TSound)
	Local ch:TChannel=channels[CurrentChannel]
	CueSound(sample, ch)
	ResumeChannel(ch)		
	CurrentChannel:+1
	If CurrentChannel=MAX_CHANNELS Then CurrentChannel=0
End Function

Function CreateChannels()
	For Local i=0 To MAX_CHANNELS-1
		channels[i]=AllocChannel()
	Next
End Function

Function KillChannels()
	For Local i=0 To MAX_CHANNELS-1
		StopChannel(Channels[i])
		Channels[i]=Null
	Next
End Function


When you run it, you will NOT hear any sound when the counter hits 17.

The bug exists with all OpenAL drivers:

'OpenAL Default
'OpenAL Generic Software
'OpenAL Generic Hardware
'OpenAL

It does NOT exist with FreeAudio or DirectSound.

What does the code do? It makes a channel array (of 16 channels) and destroys it 16 times then tries to play a sound on the 17th channel array. The astute of you will realise that 16x16=256 and thus it is failing to play on the 257th channel. HOWEVER, I'm using STOPCHANNEL to free the channels and setting the pointer to null for what it's worth and thus the channel should be completely freed up for reuse, but it is not.

Please see if you get the same results on your PC (different OSes welcome). If so, I'll post this in the bug forum.

Thanks in advance!

[edit] of course I'm quite prepared for someone to tell me I'm using this code in an "incorrect" manner, but I don't think I am especially as the behavious is inconsistent between the drivers - for example you can go over 4096 channel creations/freeings with DirectSound and FreeAudio using the above code.


tonyg(Posted 2007) [#2]
This seems to be OK and doesn't use StopChannel and goes beyond 256. Am I missing something?


<edit> on 1.24. In fact your code doesn't seem to fail on that level.


Grey Alien(Posted 2007) [#3]
I forgot to say, if you comment out the KillChannels() line in my code you get the same result.

How strange that your code works and that mine doesn't...

If you change the array size in mine to 1 and you make the TEST_VALUE 256, the sound doesn't play so the bug is still present.

[edit] I just replaced my CueSound and ResumeSound with PlaySound sample,ch and same result i.e. bug.


tonyg(Posted 2007) [#4]
Are you sure there is a limit on channels any more?



Grey Alien(Posted 2007) [#5]
check this out, I tried to make my code more like yours (i.e. not use an array, just a global channel which I never free) and it still results in the bug:

Strict

EnableOpenALAudio()
SetAudioDriver("OpenAL Generic Software") 'comment this out for no crash

Const MAX_CHANNELS=16
Global channels:TChannel[MAX_CHANNELS]
Global CurrentChannel=0

Local sound:TSound = LoadSound("test.wav")

Local Counter=0
Local total=0
Const TEST_VALUE = 256 'anything up to and including 15 will result in a sound, anything over will not.

Global ch:TChannel

Graphics 400,300,0

While Not KeyHit(KEY_ESCAPE)
	Cls
	Counter:+1
	If Counter=1 Then
		If Total<TEST_VALUE Then
			ch=AllocChannel()
'			CreateChannels()		
'			KillChannels()
			Counter=0
		ElseIf total=TEST_VALUE
'			CreateChannels()		
			Play(Sound)			
		EndIf
		Total:+1
	EndIf
	DrawText Total,10,10
	DrawText CurrentChannel,10,30
	Flip
Wend

Function Play(sample:TSound)
'	Local ch:TChannel=channels[CurrentChannel]
	ch=AllocChannel()
	PlaySound sample,ch
'	CueSound(sample, ch)
'	ResumeChannel(ch)		
	CurrentChannel:+1
	If CurrentChannel=MAX_CHANNELS Then CurrentChannel=0
End Function

Function CreateChannels()
	For Local i=0 To MAX_CHANNELS-1
		channels[i]=AllocChannel()
	Next
End Function

Function KillChannels()
	For Local i=0 To MAX_CHANNELS-1
		StopChannel(Channels[i])
		Channels[i]=Null
	Next
End Function



Grey Alien(Posted 2007) [#6]
OK Tony, great test you made because I discovered THIS!

Replace your playsound line with this:

	If counter>250 Then PlaySound sound , mychannel


You'll get 250 no sounds as expected, 5 sounds, then NO SOUNDS until near the end then you'll hear a few more. For more weirdness, boost your exit line to not end until 500 or more is met, then you'll hear a few sounds every 50or so.

This is crazy.

So basically if you make OpenAL channels and DON'T USE THEM, they are NEVER freed up. If you use them, they are freed up fine.

This should be enough for BRL to fix it. yay! Well done TonyG!


tonyg(Posted 2007) [#7]
What is your latest code supposed to do and how does it fail? For me it simply displays 0 to 257 and a 0 on the screen the stops at 257 and displays 1.


Grey Alien(Posted 2007) [#8]
Didn't see your other post until just now. Change your play line to this:

	If x>260 Then PlaySound sound , channel_dump[x]


No sounds are played.


tonyg(Posted 2007) [#9]
Isn't this the same as the DirectSound issue where the sounds are played in seperate channels so quickly that the buffers can't be cleared fast enough?


Grey Alien(Posted 2007) [#10]
What is your latest code supposed to do and how does it fail? For me it simply displays 0 to 257 and a 0 on the screen the stops at 257 and displays 1.
It should play a sound when then 1 appears (i.e. straight after the loop of channelallocations) but it doesn't.


Grey Alien(Posted 2007) [#11]
Isn't this the same as the DirectSound issue where the sounds are played in seperate channels so quickly that the buffers can't be cleared fast enough?

No, change the driver to DirectSound. No bug. These are two separate bugs. I noted this one about 3 months ago but was too busy to investigate more. Now as my project nears completion I have to choose a sound driver and I can't use FreeAudio in non-XP due to lag. DirectSound crashes on all OSes and OpenAL has this issue (plus some people say it doesn't work in Vista, but I haven't tested it on enough varied vista PCs).

Did you see my post above where I figured out why it's doing it?


So basically if you make OpenAL channels and DON'T USE THEM, they are NEVER freed up. If you use them, they are freed up fine.

This should be enough for BRL to fix it. yay! Well done TonyG!



Grey Alien(Posted 2007) [#12]
I'm gonna post this in the bug forum now that we have a smaller test app (yours).


tonyg(Posted 2007) [#13]
Here's my last bit of code which suggest there isn't a problem... I think :
<edit> change the waster array to 1000 and you don't hear any sound. Really not sure what is going on really.


Grey Alien(Posted 2007) [#14]
change it to 256 and fill it up and there are no sounds.


tonyg(Posted 2007) [#15]
Isn't that right though if there is a 256limit?


Grey Alien(Posted 2007) [#16]
yes for your latest code. BUT how come if you FREE those unused channels you still hit the 256 limit. If you play a sound on the channel BEFORE freeing it then the channel is properly freed thus it seems as though there is no limit. That's the bug, I'm 99% sure.

Regarding freeing a channel, I just recalled that nulling the pointer isn't good enough, you ARE supposed to use StopChannel first. However, as per my very first example, this doesn't work either. Good job you got me reminded of this as I've updated the code in the bug forum to use stopchannel properly like so:

Strict

EnableOpenALAudio()
SetAudioDriver("OpenAL Generic Software") 'change to FreeAudio or DirectSound for no crash

Local sound:TSound = LoadSound("test.wav")
Graphics 400,300,0
Local counter:Int = 0
Local mychannel:TChannel
While Not KeyHit(KEY_ESCAPE)
	Cls
	mychannel=AllocChannel()
	If counter>250 Then
		PlaySound sound , mychannel
	Else
		StopChannel(mychannel)
		mychannel = Null 'this line is not required
	EndIf

	DrawText counter , 0 , 0
	DrawText GCMemAlloced(),0,100
	counter:+ 1
	Flip
	If counter > 500 End
Wend



Armitage 1982(Posted 2012) [#17]
Sorry to bump a very old topic but I got the same problems only when using OpenAL on 2 different computers. I'm currently using PulseAudio to fix this but some Linux would like support for OpenAL.

I was wondering if you find a fix or a work around for this?


Armitage 1982(Posted 2012) [#18]
I saw you created a bug thread about this ( http://www.blitzbasic.com/Community/posts.php?topic=96082 ).

So you are using Global channel in your framework.
Like declaring X global channels and check which one is available before cue it to your sound and finally play it ? Doesn't it limit the maximum available object with sounds to 255 ?

The problem is that I'm doing some spacial detection code to pan / volume sound around multiple players. So it's easier to link a channel to a specific sound and that sound to the object. This working great with others Audio drivers...


This bug exist since more than 5 years now, isn't it possible to fix this :(

Last edited 2012


Grey Alien(Posted 2012) [#19]
Yes without global channels you are severely limited unfortunately. Global channels worked out fine and isn't too much code, it's just not ideal.


Armitage 1982(Posted 2012) [#20]
But how did you managed to control volume/pan/rate on a specific sound with global channels?

You created a new channel type to know if the channel is already cue with a sound or you cue your sound at runtime just before playing the sample ?

The first idea is cumbersome the next one is maybe a bit slower nah ?


Grey Alien(Posted 2012) [#21]
I create like a bank of 16 and iterate through them every time a new sound plays and the volume/pan/pitch when the sound plays. If I want to adjust volume over time then I create a handle to that channel and "lock" it so it can't be reused by other sounds until I'm finished with it.


Armitage 1982(Posted 2012) [#22]
That's what I thought.

I tried to do something like this but for the moment result are not great.

Do you still use the Stop Channel function at least for the musics ?
I though stopping a channel would destroy-it or something like that...


But seriously, OpenAL is not made to work this way. Am I wrong ?


Armitage 1982(Posted 2012) [#23]
Rather than using StopChannel playing a quick empty sound will have the same effect. It's ugly but again...


Armitage 1982(Posted 2012) [#24]
My coordinates method to pan/volume channel is corrupted if I'm using Global Channel. Plus I get all kind of little squirk sounds here and there.

It's working if I'm not changing too many channel pan/volume at the same time but unfortunately I have way too many objects emitting sounds with a moving player as listener that this solution does not work.

I think I'm doom until someone fix the OpenAL Channel behavior, which will probably never happen this year :(
Isn't it supposed to be a support for such basic stuff?

EDIT
Support exist!
BlitzMax update 1.48 fix that OpenAL Channel Bug
:D

Last edited 2012