Sounds, Audio and Memory Leaks

I have been going through my code, tidying it up and fixing memory leaks but I have something I can’t find an answer to.

I’m not doing anything fancy with my sounds, here’s how I use them.

local correctSoundFX = audio.loadSound( "sounds/success.ogg" ) local correctSound local Vol = 0.5 local someFunction = function() ... correctSound = audio.play( correctSoundFX ) audio.setVolume( Vol, { channel=correctSound }) ... end

Then on exitScene() I dispose of them

audio.stop() audio.dispose(correctSoundFX) correctSound = nil correctSoundFX = nil

What I don’t understand is what happens every time you call the function and the sound gets played, is there a new instance of the correctSound being created each time thus creating a memory leak or is it just played again? Can anyone tell me if there is anything wrong with what I’m doing here?

Many thanks in advance.

Hi @QuizMaster,

Are you sure this is the source of your memory leak? It looks basically OK to me.

What I’d do is not up-value reference “correctSound”. Just localize that in the function:

[lua]

local correctSoundFX = audio.loadSound( “sounds/success.ogg” )

local Vol = 0.5

local someFunction = function()

   local correctSound = audio.play( correctSoundFX )

   audio.setVolume( Vol, { channel=correctSound })

   …

end

[/lua]

Again, this may not be the cause of your memory leak. Can you run only this code and determine if it is?

Take care,

Brent

Thanks Brent.

I’m stumped with this scenario.

I have a sound effect playing and when the user presses a button the sound has to be stopped, this action is done repeatedly.

I have no choice as far as I know but to scope it at the top of my code, like in the example below, so I can stop it in a function and restart it in another function.

What I’m worried about is do I nil the reference?

function scene:enterScene(event) local ticktockFX = audio.loadSound( "sounds/countdown.ogg" ) local ticktockSound local buttonPressed = function(event) ... if ticktockSound ~= nil then audio.stop( ticktockSound ) ticktockSound = nil end ... end

In doing so am I not losing the scope I created to it at the top of my code?

If I do not nil the reference then am I not going to keep creating more instances of it when I play the sound again and again?

local someFunction = function() ... local ticktockSound = audio.play( ticktockFX ) audio.setVolume( Vol, { channel=ticktockSound }) ... end

If I’m localizing the reference to the sound within the function how do I clear it from memory when leaving the scene? The reason I ask is because in this topic: http://forums.coronalabs.com/topic/22091-guide-findingsolving-memory-leaks/ 

Rob pointed out "If you do a:
group:insert(somedisplayobject)
In your createScene(), willEnterScene() or enterscene() it will be purged and nil’ed when the scene is purged.

What is not removed is sound loaded in those scenes , timers, transitions that are not finished, any Runtime listeners (listeners on those display objects will be removed).

By default, storyboard scenes are only purged on low memory event warnings."

This has me puzzled.

Hi @QuizMaster,

Perhaps a better way to consider this is, if you want to play the sound repeatedly, but NOT allow it to overlap, why not just dedicate a channel to that sound? So, when you play it, do “audio.stop()” on the channel, then “audio.play()” on the same channel. This avoids up-values and all that.

Brent

Hi Brent

I was just looking at this, you are right.

If I do this with only the sounds that I have to keep stopping and starting then it fixes all my problems.

I’ve just tried it in my code and although I had an initial issue with trying to use a channel that was already being used I now have it working.

audio.play( ticktockFX, {channel=2} )
                audio.setVolume( Vol, {channel=2} )

audio.stop( 2 )

No up-values!

Thanks Brent.

Hi @QuizMaster,

Are you sure this is the source of your memory leak? It looks basically OK to me.

What I’d do is not up-value reference “correctSound”. Just localize that in the function:

[lua]

local correctSoundFX = audio.loadSound( “sounds/success.ogg” )

local Vol = 0.5

local someFunction = function()

   local correctSound = audio.play( correctSoundFX )

   audio.setVolume( Vol, { channel=correctSound })

   …

end

[/lua]

Again, this may not be the cause of your memory leak. Can you run only this code and determine if it is?

Take care,

Brent

Thanks Brent.

I’m stumped with this scenario.

I have a sound effect playing and when the user presses a button the sound has to be stopped, this action is done repeatedly.

I have no choice as far as I know but to scope it at the top of my code, like in the example below, so I can stop it in a function and restart it in another function.

What I’m worried about is do I nil the reference?

function scene:enterScene(event) local ticktockFX = audio.loadSound( "sounds/countdown.ogg" ) local ticktockSound local buttonPressed = function(event) ... if ticktockSound ~= nil then audio.stop( ticktockSound ) ticktockSound = nil end ... end

In doing so am I not losing the scope I created to it at the top of my code?

If I do not nil the reference then am I not going to keep creating more instances of it when I play the sound again and again?

local someFunction = function() ... local ticktockSound = audio.play( ticktockFX ) audio.setVolume( Vol, { channel=ticktockSound }) ... end

If I’m localizing the reference to the sound within the function how do I clear it from memory when leaving the scene? The reason I ask is because in this topic: http://forums.coronalabs.com/topic/22091-guide-findingsolving-memory-leaks/ 

Rob pointed out "If you do a:
group:insert(somedisplayobject)
In your createScene(), willEnterScene() or enterscene() it will be purged and nil’ed when the scene is purged.

What is not removed is sound loaded in those scenes , timers, transitions that are not finished, any Runtime listeners (listeners on those display objects will be removed).

By default, storyboard scenes are only purged on low memory event warnings."

This has me puzzled.

Hi @QuizMaster,

Perhaps a better way to consider this is, if you want to play the sound repeatedly, but NOT allow it to overlap, why not just dedicate a channel to that sound? So, when you play it, do “audio.stop()” on the channel, then “audio.play()” on the same channel. This avoids up-values and all that.

Brent

Hi Brent

I was just looking at this, you are right.

If I do this with only the sounds that I have to keep stopping and starting then it fixes all my problems.

I’ve just tried it in my code and although I had an initial issue with trying to use a channel that was already being used I now have it working.

audio.play( ticktockFX, {channel=2} )
                audio.setVolume( Vol, {channel=2} )

audio.stop( 2 )

No up-values!

Thanks Brent.