ALmixer_FreeData: alDeleteBuffers failed. Invalid Operation - Again

I have been working on this OpenAL problem many times and I can't find the best way to ensure audio reproduction in the application.

This is the story: I have music, speech narration and sound effects as far as 150 different sound files in .caf and .mp3 format (only for music/narrations).

The application is an interactive-book, therefore each screen has different graphics and sounds, none of them are repeated (I didn't make the design and concept, so... I am just coding).

The way that I use the sounds is in this format:

First, each screen is switched by using Director Class, after that I use to load the sound by: audio.loadSound (for short sounds) and audio.loadStream (for narration). Sound files for narrations are between 550Kb and 1.2Mb uncompressed.

To reproduce sounds, I use to call audio.play(sound, params)

Then (here I guess the problem reside) when the screen has to be switched to another one, the Clean (director function in the lua code) is invoked with the following lines:

audio.stop(channel)
audio.dispose(sound)
sound=nil

Now, if the sound is reproduced until the end and then the user switch the screen, there is no problem. The channel is liberated and the sound is eliminated (I guess from the memory, but I am not really sure). Then if the user switch the screen in the middle of a sound, (playing) sometimes the stop works well, but dispose seems to not free the resource from the memory, therefore ALmixer_FreeData: alDeleteBuffers failed. Invalid Operation is raised. Some times, after several screens the sound, music or narrations are totally lost. Some times, the volume (really I don't know why..), goes down without any reason. If the application still running at the end, a crash is produced either in the simulator (including Corona exception and close) or device (app crash).

So, I did some workarounds like add audio.stop(0) on the start of every screen, after the switch. It helps only if there was a previous sound played. If not, it will stop sounds and no more reproductions are executed. (strange behaviour, but happens).

I tried to stop only the active channel, paused or playing one but it seems that it does not work as expected.

In my code the line check if the channel is active by using:

if audio.isChannelPlaying(soundChannel) or audio.isChannelActive(soundChannel) then
audio.pause(soundChannel)

But even so, the audio is not stopped and therefore is not disposed as it is supposed to be. So, at the end, the problem persists.

I tried different scenarios without to much result. I saw there was/is a bug in the Apple OpenAl implementation, but I am also saw applications running well without this problem, so where is the problem? In the Apple OpenAl mixer implementation, in the Corona wrapper or in my code?

I even saw many threats about this issue in the forum without to many clues and I guess Ansca help is required here to put an example code on how to deal with this situation (different screens with Director class, with different sounds loaded, played and disposed in every screen).

Flavio.

Sorry this is the right code of the stop rutine:

if soundChannel~=nil and soundChannel~=0 then
if audio.isChannelPlaying(soundChannel) or audio.isChannelPaused(soundChannel) or audio.isChannelActive(soundChannel) then
audio.stop(soundChannel)
end
end

Thx.

I am using Corona Build 2011.645

Flavio

And sometimes I even get this: 1133 Segmentation fault where Corona Simulator close.

Flavio.

Providing simple, isolated example programs really help us fix problems. We can't verify and fix problems unless we can reproduce them. And the more complicated the sample program, the harder it is for us to isolate the problem.

Yes, there have been bugs in Apple's OpenAL implementation. As you may have seen iOS 5.0, has a very bad one. However, there have been other ones in other versions of iOS. (iOS 4.3.x has probably been the best so far.) What version of iOS have you had your problem on? And does it happen on Mac or Android or Windows? What versions?

If the bug happens on all the platforms, it probably is not an OpenAL bug but a Corona bug.

I am just testing and developing for iOS devices.

It fails on the Mac version simulator and ipod (4.3.3), iphone 3G (4.1), iphone 4 (4.3.5) and iPad 1 (version 4.3.2).

I didn't test it on iOS 5. But I need the sounds working on those versions.

Flavio.

We really need a simple reproducible test case to help you further. I can only give you general advice without it. The general advice is that audio.dispose() will only work correctly if nothing is currently using the handle you are disposing. The most common mistake that can lead to the failures and crashes you see is if you call dispose while the file is still being used. For example, a paused channel is still using the file so it is NOT safe to call dispose yet. Calling audio.stop() on everything should make it safe to dispose the handle.

A new mistake I've recently seen is people using timer.performWithDelay to tell them when a sound finishes playing. timer.performWithDelay doesn't have perfect accuracy so if you are not careful, you might get the performWithDelay callback before the audio finishes playing and calling dispose will create errors/crashes. Instead, the audio completion callbacks are designed to do this kind of work and are guaranteed to fire after the audio completes.

Ewing,

Thanks for your guideline.

I would like to share my code, but it has more than 75 .lua files as each section of the e-book is loaded by Director Class. And I guess even if I put a small code, that small code would work, because it doesn't have the load of the application, files opened, stack of callbacks, sounds loaded in the memory and so on. That's why I asked a proper example on how to deal with that scenario.

Just to give you an idea of the project that I have, it contains more than 1000 files (.png, jpg, mp3, .caf and .lua). Of course not all of them are opened at the same time, but could be useful to know how can I verify that load (printing to standard output/terminal) to see what is happening there. Because for me they should be downloaded from the memory after each dispose and nilling. May be they still in the memory and they don't allow any other sound in the memory, causing no reproduction. But in that case, I guess channel if ch is assigned after a ch=audio.play(soundHandler), but the sound is not reproduced, does it mean that soundHandler is already loaded? If not, why audio library assign a valid channel if the sound is not present?

However the general rule that I use is exactly what you mention above. Even so, let's say I wish to cancel a sound immediately and dispose that sound from the memory, even if that sound will be played again seconds later (because is user-driven between pages of the e-book) so I play the sound, but when it is playing, the user changes the screen to see another page, therefore everything from that previous page has to be cleared. Therefore the Clean function is called from Director class, where I've put audio.stop(soundChannel) and the audio.dispose(handleSound) and finally handleSound=nil.

I've noticed that if I put an audio.stop() or audio.stop(0) at the beginning of each page, all sounds will be stop abrupt (which is not so ideal) but when the next page tries to reproduce a sound or music, even if a channel is assigned (I did a wrapper to intercept each call and see if the channel is assigned to the sound handler) to that particular sound, the sound is not heard.

Sometimes music is not heard but short-sound effects are reproduced and sometimes the general volume for the music channel is too low (I really don't know why that thing happens), it seems like a funnel is eating the sounds after several retries.

So, may be there is other way to load, play and dispose sounds or any other available function to monitor that situation???

Thx..

Flavio.

views:3701 update:2011/10/28 9:34:19
corona forums © 2003-2011