audio.play() - 17dTesting Error with clearing buffer from source: Invalid Operation

This code is playing short collision sound.

[blockcode]
local sound = audio.loadSound( ‘sound/hit.wav’ )
local soundId = 1

local function ballContactSound()
audio.stop( soundId )
audio.play( sound, {channel = soundId} )
end

local function ballCollision( self, e )
– play sound
ballContactSound()
end

local ball = display.newCircle( group, 0, 0, 20 )
physics.addBody( ball, ‘dynamic’ )
ball.preCollision = ballCollision
ball:addEventListener(‘preCollision’, ball)
[/blockcode]

At any moment, simulator prints “17dTesting Error with clearing buffer from source: Invalid Operation” error.

this makes me crazy. PLEASE HELP ME [import]uid: 161695 topic_id: 35524 reply_id: 335524[/import]

I suspect the issue is that the pre-collision listener is very “noisy” and it fires a ton of events… so you’re effectively calling the audio stop/play dozens of times in a very short timeframe, which is likely mucking up the audio system. I suggest you filter this to trigger the sound on only the first pre-collision event… you can still use pre-collision (assuming you have a need for it, versus a regular collision listener), but play the sound only on the first one.

Best regards,
Brent [import]uid: 200026 topic_id: 35524 reply_id: 141266[/import]

(Sorry for poor english. English is not my mother tongue)

I already knows preCollision is heavy listener.

My actual code is this.

[blockcode]
function playControl:ballContactSound()
local sound = sound
– fCnt is current frame counter that is increased by enterFrame event
– prevent sound playing too often… ( plays only once in 5 frames )
if sound.contactFrame + 5 < fCnt then
local audio = audio
audio.stop( sound.contactId )
audio.play( sound.contact, {channel = sound.contactId} )
sound.contactFrame = fCnt
end
end

– ball collision event (pre-collision)
function playControl.ballCollision( self, e )
local o = e.other
local ball = self
local oType = o.type

if oType == -1 and e.contact ~= nil then

– PASS-THROUGH with balls each other
e.contact.isEnabled = false

elseif oType == 0 then

– Wall collision
if e.contact == nil then
– CORONA PHYSICS BUG : sometimes e.contact == nil
return true
end

– PASS-THROUGH (do not use corona physics)
e.contact.isEnabled = false

– make collision event only once
if ball.prevCollision == 0 then
return true
end

– reflect ball by custom physics calculation
playControl:barCollision( self, o )
– PLAY SOUND
playControl:ballContactSound()

– save previous collision type
ball.prevCollision = 0

elseif oType == 1 then

– some codes…

end
end
[/blockcode] [import]uid: 161695 topic_id: 35524 reply_id: 141496[/import]

Hello @songinnight,
I think a most simple solution could be achieved. I assume the basic idea is: you need the pre-collision listener because of the Physics Contact feature (this is perfectly correct). And, when certain balls collide, you want to play the sound just once?

Can I ask, how many balls will be colliding in your scenario? Just a few? Dozens? Hundreds? I might have an alternative method, depending on how complex your collision scenario is.

Thanks,
Brent [import]uid: 200026 topic_id: 35524 reply_id: 141545[/import]

1-7 balls can be exist. Maximum ball count is 7
#added

You can download and test game (apk file) here.

http://big4games.com/inc/apps/brick/20130205_135639_brick.apk

You can start game by touching “???” -> “???” button that is orange color and biggest
If you need full source code I can send you. [import]uid: 161695 topic_id: 35524 reply_id: 141636[/import]

Hi @songinnight,
With just 7 balls (or maybe a few more eventually), I would suggest you combine both a pre-collision and normal collision listener. I did something similar to this in the Physics Contact demo I wrote on the blog. In your case, the pre-collision event would handle only the event.contact, while the regular collision handler manages your sounds. This would prevent you from having to deal with counting “frames” and all of that.

Would that potentially solve the issue or might it introduce other issues?

Brent [import]uid: 200026 topic_id: 35524 reply_id: 141704[/import]

As you said, I should try “collision” event handler rather than “preCollision”.
Thank you for your help. [import]uid: 161695 topic_id: 35524 reply_id: 141776[/import]

Hi @songinight,
You’re welcome, always happy to help. Just to be clear though, the normal collision handler would be for the sounds; you’ll still need the pre-collision handler for the physics contact functionality. I’m sure you realize that though. :slight_smile:

Brent [import]uid: 200026 topic_id: 35524 reply_id: 141792[/import]

Thank you Brent. You’re right. preCollision is required. I’ll try to move sound, fx functions to postCollision event. I will post the results.

added

There’s problem. If e.contact.isEnabled set to false, postCollision doesn’t fired. [import]uid: 161695 topic_id: 35524 reply_id: 141794[/import]

Hi @songinnight,
Is the post-collision event needed for some reason? I was thinking this:

  1. pre-collision handles the physics contact
  2. normal collision handles the sounds/effects

Brent

[import]uid: 200026 topic_id: 35524 reply_id: 141803[/import]

I suspect the issue is that the pre-collision listener is very “noisy” and it fires a ton of events… so you’re effectively calling the audio stop/play dozens of times in a very short timeframe, which is likely mucking up the audio system. I suggest you filter this to trigger the sound on only the first pre-collision event… you can still use pre-collision (assuming you have a need for it, versus a regular collision listener), but play the sound only on the first one.

Best regards,
Brent [import]uid: 200026 topic_id: 35524 reply_id: 141266[/import]

Hi, Brent.

The reason why is to check box2D calculation has solved or not and to recover initial velocity of ball.

I sent you an e-mail with full game source code and resources so you can run in simulator.

I’m sorry to bother you.
and thank you. [import]uid: 161695 topic_id: 35524 reply_id: 141952[/import]

(Sorry for poor english. English is not my mother tongue)

I already knows preCollision is heavy listener.

My actual code is this.

[blockcode]
function playControl:ballContactSound()
local sound = sound
– fCnt is current frame counter that is increased by enterFrame event
– prevent sound playing too often… ( plays only once in 5 frames )
if sound.contactFrame + 5 < fCnt then
local audio = audio
audio.stop( sound.contactId )
audio.play( sound.contact, {channel = sound.contactId} )
sound.contactFrame = fCnt
end
end

– ball collision event (pre-collision)
function playControl.ballCollision( self, e )
local o = e.other
local ball = self
local oType = o.type

if oType == -1 and e.contact ~= nil then

– PASS-THROUGH with balls each other
e.contact.isEnabled = false

elseif oType == 0 then

– Wall collision
if e.contact == nil then
– CORONA PHYSICS BUG : sometimes e.contact == nil
return true
end

– PASS-THROUGH (do not use corona physics)
e.contact.isEnabled = false

– make collision event only once
if ball.prevCollision == 0 then
return true
end

– reflect ball by custom physics calculation
playControl:barCollision( self, o )
– PLAY SOUND
playControl:ballContactSound()

– save previous collision type
ball.prevCollision = 0

elseif oType == 1 then

– some codes…

end
end
[/blockcode] [import]uid: 161695 topic_id: 35524 reply_id: 141496[/import]

Hello @songinnight,
I think a most simple solution could be achieved. I assume the basic idea is: you need the pre-collision listener because of the Physics Contact feature (this is perfectly correct). And, when certain balls collide, you want to play the sound just once?

Can I ask, how many balls will be colliding in your scenario? Just a few? Dozens? Hundreds? I might have an alternative method, depending on how complex your collision scenario is.

Thanks,
Brent [import]uid: 200026 topic_id: 35524 reply_id: 141545[/import]

Hi @songinnight,
I didn’t get the email, can you resend?

For checking the collision after resolving, can you just detect the “ended” phase of the regular collision filter, then run a short timer (10-20 milliseconds) and perform your action then? This will let you check the Box2D body properties in the next game cycle, thus, after the collision resolves.

Brent [import]uid: 200026 topic_id: 35524 reply_id: 142337[/import]

1-7 balls can be exist. Maximum ball count is 7
#added

You can download and test game (apk file) here.

http://big4games.com/inc/apps/brick/20130205_135639_brick.apk

You can start game by touching “???” -> “???” button that is orange color and biggest
If you need full source code I can send you. [import]uid: 161695 topic_id: 35524 reply_id: 141636[/import]

Hi @songinnight,
With just 7 balls (or maybe a few more eventually), I would suggest you combine both a pre-collision and normal collision listener. I did something similar to this in the Physics Contact demo I wrote on the blog. In your case, the pre-collision event would handle only the event.contact, while the regular collision handler manages your sounds. This would prevent you from having to deal with counting “frames” and all of that.

Would that potentially solve the issue or might it introduce other issues?

Brent [import]uid: 200026 topic_id: 35524 reply_id: 141704[/import]

Hi, Brent.
I made a mistake. I have sent to “donotreply@coronalabs.com”… : (
Could you tell me your email address? then I will send you the file you can run.
My email address is songinnight@big4games.com

* Normal collision ignores preCollision - contact.enabled false… [import]uid: 161695 topic_id: 35524 reply_id: 142448[/import]

As you said, I should try “collision” event handler rather than “preCollision”.
Thank you for your help. [import]uid: 161695 topic_id: 35524 reply_id: 141776[/import]

Hi @songinight,
You’re welcome, always happy to help. Just to be clear though, the normal collision handler would be for the sounds; you’ll still need the pre-collision handler for the physics contact functionality. I’m sure you realize that though. :slight_smile:

Brent [import]uid: 200026 topic_id: 35524 reply_id: 141792[/import]