Hi, I believe I have found a serious bug with the DirectSound driver but I need to verify it. It breaks my current game with a MAV when DirectSound is the chosen driver. I was investigating using DirectSound in WinME and Vista instead of OpenAL which also has some (different) problems becaue FreeAudio is not viable on those systems due to breakup/lag etc.
I've spent HOURS whittling down the code into a test app as follows:
You need this sample: http://www.greyaliengames.com/misc/test.wav (18k)
Basically if I put that sample in the same folder as the app and run it I get a "Unhandled Memory Exception Error". With Debug enabled it appears to be happening in Stop() called by Cue() called by Cue() called by CueSound(). I noticed that self._buff._succ._succ:TBuf = null and I'm not sure if it should be (but that could be a red herring).
This bug needs weirdly specific circumstances to occur. I basically figured out that if you load in a sound and play it and then free up that sound (but not the channel), then later on you try to use that channel again, DirectSound crashes. Yet FreeAudio and OpenAL do NOT crash. In those other drivers you can quite happily trigger a sound in a channel, kill of the sound and the channel will keep playing and is reuseable. With DirectSound the channel keeps playing, but it's not reuseable later.
However, in my above code, if I comment out one of the Test() function calls, it doesn't crash! If I comment out the GCCollect it doesn't crash, weird. This must just be something to do with then the GC decides to collect the local variable of TestSound in the Test() function.
First I'd like to verify that other people get the same crash, and if they do then I can raise it as an official bug.
My theory is that DirectSound doesn't like it when you free up a sound that is playing yet the other drivers are happy with this.
Why do I want to free up a sound that is playing? Well imagine a screen with a button with a special click sound. The user clicks the button, the sound plays on a GLOBAL channel, and then the screen is freed up and a new screen is showing. The global button click channel may continue playing for a little bit even though the sound has now been freed up. Then later on the global channel is reused - works in FreeAudio and OpenAL but not DirectSound.
Any help appreciated thanks, it would be nice to get to the bottom of this.
I've spent HOURS whittling down the code into a test app as follows:
Strict SetAudioDriver("DirectSound") 'comment this out for no crash Const MAX_CHANNELS=4 Global channels:TChannel[MAX_CHANNELS] Global CurrentChannel=0 For Local i=0 To MAX_CHANNELS-1 channels[i]=AllocChannel() Next Local Counter=0 Local sound:TSound = LoadSound("test.wav") Graphics 400,300,0 test() test() 'if you comment this line out, it doesn't crash on my PC ... go figure! GCCollect() While Not KeyHit(KEY_ESCAPE) Cls Counter:+1 If Counter=5 Then Play(Sound) Counter=0 EndIf DrawText CurrentChannel,10,10 Flip Wend Function test() Local TestSound:TSound = LoadSound("test.wav") Play(TestSound) End Function 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
You need this sample: http://www.greyaliengames.com/misc/test.wav (18k)
Basically if I put that sample in the same folder as the app and run it I get a "Unhandled Memory Exception Error". With Debug enabled it appears to be happening in Stop() called by Cue() called by Cue() called by CueSound(). I noticed that self._buff._succ._succ:TBuf = null and I'm not sure if it should be (but that could be a red herring).
This bug needs weirdly specific circumstances to occur. I basically figured out that if you load in a sound and play it and then free up that sound (but not the channel), then later on you try to use that channel again, DirectSound crashes. Yet FreeAudio and OpenAL do NOT crash. In those other drivers you can quite happily trigger a sound in a channel, kill of the sound and the channel will keep playing and is reuseable. With DirectSound the channel keeps playing, but it's not reuseable later.
However, in my above code, if I comment out one of the Test() function calls, it doesn't crash! If I comment out the GCCollect it doesn't crash, weird. This must just be something to do with then the GC decides to collect the local variable of TestSound in the Test() function.
First I'd like to verify that other people get the same crash, and if they do then I can raise it as an official bug.
My theory is that DirectSound doesn't like it when you free up a sound that is playing yet the other drivers are happy with this.
Why do I want to free up a sound that is playing? Well imagine a screen with a button with a special click sound. The user clicks the button, the sound plays on a GLOBAL channel, and then the screen is freed up and a new screen is showing. The global button click channel may continue playing for a little bit even though the sound has now been freed up. Then later on the global channel is reused - works in FreeAudio and OpenAL but not DirectSound.
Any help appreciated thanks, it would be nice to get to the bottom of this.