OpenAL Audio thread randomly crashing

During heavy playtesting, we’ve noticed that our app crashes on the OpenAL thread every once in a while (maybe 1 in 15 times). We’re mostly testing on an iPad 3.

Error is as follows:

Thread 6 Crashed:  
0 libsystem\_kernel.dylib 0x3b332350 0x3b321000 + 70480  
1 libsystem\_c.dylib 0x35c9411e 0x35c65000 + 192798  
2 libsystem\_c.dylib 0x35cd096e 0x35c65000 + 440686  
3 libsystem\_c.dylib 0x35c9af14 0x35c65000 + 220948  
4 libsystem\_c.dylib 0x35c9b1b8 0x35c65000 + 221624  
5 libsystem\_c.dylib 0x35c692dc 0x35c65000 + 17116  
6 OpenAL 0x387b4c72 0x387b4000 + 3186  
7 OpenAL 0x387b4c0a 0x387b4000 + 3082  
8 OpenAL 0x387b8192 0x387b4000 + 16786  
9 OpenAL 0x387bd41a 0x387b4000 + 37914  
10 game 0x000f572e 0xbb000 + 239406  
11 game 0x000ef792 0xbb000 + 214930  
12 game 0x000f66ea 0xbb000 + 243434  
13 libsystem\_c.dylib 0x35c7630e 0x35c65000 + 70414  
14 libsystem\_c.dylib 0x35c761d4 0x35c65000 + 70100  

This seems to happen in an area where we frequently load/unload voiceover sounds via loadStream (The user skipping through cutscenes). I’ve looked over the small amount of code we have to do this a dozen times to see if there was anything I could fix, and as far as I can tell we’re doing everything right.

Here’s the function we use to play voice overs. Any insight into if we’re doing something wrong? My only guess at this point is that maybe there’s some sort of race condition that happens when rapidly loading and disposing of audio streams, or re-using the same channel immediately after stopping audio on it.

[code]
function A.playVoiceOver(name)
audio.stop(2)
if(A.voHandle) then
audio.dispose(A.voHandle)
A.voHandle = nil
end

local folder,filetype;
if(system.getInfo( “platformName” ) == ‘Android’) then
folder = ‘android’
filetype = ‘ogg’
else
folder = ‘iOS’
filetype = ‘m4a’
end
– Voice overs will play on channel 2
A.voHandle = audio.loadStream(‘audioAssets/’…folder…’/vo/’…name…’.’…filetype)
audio.play(A.voHandle, { channel=2 })
end
[/code] [import]uid: 135827 topic_id: 34007 reply_id: 334007[/import]

Generally audio crashes occur because you dispose of a buffer that is still playing or has already been disposed. I would suggest calling the dispose function in timer.perFormWithDelay to give the channel time to stop and see if that fixes it. [import]uid: 7559 topic_id: 34007 reply_id: 135284[/import]

Generally audio crashes occur because you dispose of a buffer that is still playing or has already been disposed. I would suggest calling the dispose function in timer.perFormWithDelay to give the channel time to stop and see if that fixes it. [import]uid: 7559 topic_id: 34007 reply_id: 135284[/import]

Hello I am experiencing a problem and I think it is the same problem : I am loading and unloading audio streams regularly. After some time (after the 92th call of audio.loadStream) the music cannot play (audio.play then returns 0). I am testing on iPad but there is also this problem in the corona simulator running on a Mac. I also tested using specific and various channels but exactly the same problems occurred.

Then I tested on Android 4.2 and it works perfectly. I have tried to use performWithDelay to dispose after some time but no effect the bug is still here.

Here is my simplified test program that works on android but not on iOS. (The interval does not impact the result nor the audio file type and size)

local playNextMusicCallInterval = 500 -- milliseconds -- musics that the program will load, play, dispose continuously music = "track1.mp3" -- will store music handle musicHandle = nil -- the active channel activeChannel = 0 playNextMusicCalls = 0 -- playNextMusic() call count = audio.loadStream() call count playErrors = 0 -- play errors count (when audio.play has returned 0) function loadMusic()     musicHandle =  audio.loadStream(music) end function unloadMusic()   local mHandle = musicHandle   musicHandle = nil      timer.performWithDelay(1000, function()     audio.dispose(mHandle)   end) end function playNextMusic()   playNextMusicCalls = playNextMusicCalls + 1   if activeChannel \> 0 then     audio.stop(activeChannel)      unloadMusic()   end   loadMusic()      activeChannel = audio.play(musicHandle, {loops = -1, channel = 1})        if activeChannel == 0 then     playErrors = playErrors + 1 -- increase error counter   end      print ("--STATS--: playNextMusic calls = " .. playNextMusicCalls .." / ERRORS = " .. playErrors)   -- wait again and relaunch a music   timer.performWithDelay(playNextMusicCallInterval, function() playNextMusic(); end, 1); end timer.performWithDelay(playNextMusicCallInterval, function() playNextMusic(); end);  

Thank you so much for the reproducible case!  It now runs essentially forever (I got bored and stopped it):

2013-07-18 13:58:28.830 Corona Simulator[40824:303] --STATS--: playNextMusic calls = 1776 / ERRORS = 0

Thanks to that I was able to find a fix fairly quickly which will be in the next Daily Build.

You’re welcome.

My understanding is that I have to regularly check on the daily builds until I see a new release. Hopefully it will contain the corrective.

I would appreciate if you can provide some explanations about what was the issue.

Build 2013.1168 is now up.  Sorry about the delay.

The issue was that certain audio resources were not being released correctly on a dispose() which meant that they were exhausted when enough sounds had been created and destroyed.

Hello I am experiencing a problem and I think it is the same problem : I am loading and unloading audio streams regularly. After some time (after the 92th call of audio.loadStream) the music cannot play (audio.play then returns 0). I am testing on iPad but there is also this problem in the corona simulator running on a Mac. I also tested using specific and various channels but exactly the same problems occurred.

Then I tested on Android 4.2 and it works perfectly. I have tried to use performWithDelay to dispose after some time but no effect the bug is still here.

Here is my simplified test program that works on android but not on iOS. (The interval does not impact the result nor the audio file type and size)

local playNextMusicCallInterval = 500 -- milliseconds -- musics that the program will load, play, dispose continuously music = "track1.mp3" -- will store music handle musicHandle = nil -- the active channel activeChannel = 0 playNextMusicCalls = 0 -- playNextMusic() call count = audio.loadStream() call count playErrors = 0 -- play errors count (when audio.play has returned 0) function loadMusic()     musicHandle =  audio.loadStream(music) end function unloadMusic()   local mHandle = musicHandle   musicHandle = nil      timer.performWithDelay(1000, function()     audio.dispose(mHandle)   end) end function playNextMusic()   playNextMusicCalls = playNextMusicCalls + 1   if activeChannel \> 0 then     audio.stop(activeChannel)      unloadMusic()   end   loadMusic()      activeChannel = audio.play(musicHandle, {loops = -1, channel = 1})        if activeChannel == 0 then     playErrors = playErrors + 1 -- increase error counter   end      print ("--STATS--: playNextMusic calls = " .. playNextMusicCalls .." / ERRORS = " .. playErrors)   -- wait again and relaunch a music   timer.performWithDelay(playNextMusicCallInterval, function() playNextMusic(); end, 1); end timer.performWithDelay(playNextMusicCallInterval, function() playNextMusic(); end);  

Thank you so much for the reproducible case!  It now runs essentially forever (I got bored and stopped it):

2013-07-18 13:58:28.830 Corona Simulator[40824:303] --STATS--: playNextMusic calls = 1776 / ERRORS = 0

Thanks to that I was able to find a fix fairly quickly which will be in the next Daily Build.

You’re welcome.

My understanding is that I have to regularly check on the daily builds until I see a new release. Hopefully it will contain the corrective.

I would appreciate if you can provide some explanations about what was the issue.

Build 2013.1168 is now up.  Sorry about the delay.

The issue was that certain audio resources were not being released correctly on a dispose() which meant that they were exhausted when enough sounds had been created and destroyed.

Do you have a fix for the downloadable 1137 version ?

We’re preparing a new Public Release and it should be available in the next couple of weeks barring unforeseen circumstances.

The issue relates to loading and disposing of individual audio files.  If your app actually has more than 92 different files then you will need to wait for the fixed release.  Often though, an app will have 20 or 30 sounds and load and dispose of them repeatedly over the course of a session.  If this is the case then you can create a simple cache which arranges for each sound to be loaded just once and then remembered for the next time it’s needed.  Depending on the size of the audio files memory might be a problem but this approach can work in many situations.

Thanks Perry,

In our app, we use a lot of speech.

We temporarily replaced the loadStream with loadSound and everything is back to normal. So far, we did not experience any memory or performance issues because of the lenght of the audio-files. The Android version of our app still uses the loadStream method, because the loading of audio is significantly slower than the iOs version.

Do you have a fix for the downloadable 1137 version ?

We’re preparing a new Public Release and it should be available in the next couple of weeks barring unforeseen circumstances.

The issue relates to loading and disposing of individual audio files.  If your app actually has more than 92 different files then you will need to wait for the fixed release.  Often though, an app will have 20 or 30 sounds and load and dispose of them repeatedly over the course of a session.  If this is the case then you can create a simple cache which arranges for each sound to be loaded just once and then remembered for the next time it’s needed.  Depending on the size of the audio files memory might be a problem but this approach can work in many situations.

Thanks Perry,

In our app, we use a lot of speech.

We temporarily replaced the loadStream with loadSound and everything is back to normal. So far, we did not experience any memory or performance issues because of the lenght of the audio-files. The Android version of our app still uses the loadStream method, because the loading of audio is significantly slower than the iOs version.