Audio playback is grinding my app to a halt. [Hair-pulling stage]

I'm loading thirty sounds into a table. The sound files are about 2 seconds a piece. My app begins to lag on an iPhone 4 when four or five sounds are expected to play in the a 5 or so second time window. I've tried various file type, frequencies, mono/stereo... you name it. Typical memory consumption is as follows:

MemUsage: 0.2150576171875 MB
Texture Usage 21.659648

Maybe it is my sounds files. I've tried both 22050Hz and 44100Hz for wav files, mp3, aiff, etc. My bitrate may be a bit high, but other than that i've been through all the combinations I could think of.

Edit: If it helps any, it seems like the app lags a bit on first play of each sound, despite being preloaded and all.

Can any one catch anything below?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
enso = {
        context =
        {
                beatz = {{}, {}, {}, {}, {}, {}}
                
        }
}
 
local beatz = enso.context.beatz
 
-- Voice 1 <Mar>
beatz[1][1] = audio.loadSound("Mar1.wav")
beatz[1][2] = audio.loadSound("Mar2.wav")
beatz[1][3] = audio.loadSound("Mar3.wav")
beatz[1][4] = audio.loadSound("Mar4.wav")
beatz[1][5] = audio.loadSound("Mar5.wav")
-- Voice 2 <Spe>
beatz[2][1] = audio.loadSound("Spe1.wav")
beatz[2][2] = audio.loadSound("Spe2.wav")
beatz[2][3] = audio.loadSound("Spe3.wav")
beatz[2][4] = audio.loadSound("Spe4.wav")
beatz[2][5] = audio.loadSound("Spe5.wav")
-- Voice 3 <Hbr>
beatz[3][1] = audio.loadSound("Hbr1.wav")
beatz[3][2] = audio.loadSound("Hbr2.wav")
beatz[3][3] = audio.loadSound("Hbr3.wav")
beatz[3][4] = audio.loadSound("Hbr4.wav")
beatz[3][5] = audio.loadSound("Hbr5.wav")
-- Voice 4 <Kal>
beatz[4][1] = audio.loadSound("Kal1.wav")
beatz[4][2] = audio.loadSound("Kal2.wav")
beatz[4][3] = audio.loadSound("Kal3.wav")
beatz[4][4] = audio.loadSound("Kal4.wav")
beatz[4][5] = audio.loadSound("Kal5.wav")
-- Voice 5 <Bel>
beatz[5][1] = audio.loadSound("Bel1.wav")
beatz[5][2] = audio.loadSound("Bel2.wav")
beatz[5][3] = audio.loadSound("Bel3.wav")
beatz[5][4] = audio.loadSound("Bel4.wav")
beatz[5][5] = audio.loadSound("Bel5.wav")
-- Voice 6 <Pia>
beatz[6][1] = audio.loadSound("Pia1.wav")
beatz[6][2] = audio.loadSound("Pia2.wav")
beatz[6][3] = audio.loadSound("Pia3.wav")
beatz[6][4] = audio.loadSound("Pia4.wav")
beatz[6][5] = audio.loadSound("Pia5.wav")
audio.setVolume(.2)
 
local minScale = enso.context.minScale
local maxScale = enso.context.maxScale
local bucketSize = (maxScale - minScale) / 5.0
 
function enso.soundWith(circle1, circle2)
        local scale_1 = circle1.imageRect.xScale
        local scale_2 = circle2.imageRect.xScale
        
        -- find bucket for circle 1
        local inf = minScale
        local sup = inf + bucketSize
        local bucket = 5
        while inf < maxScale do
                if inf <= scale_1 and sup >= scale_1 then
                        local availableChannel = audio.findFreeChannel()
                        audio.play(beatz[enso.context.selectedVoiceForColor[circle1.color]][bucket], {channel=availableChannel})
                        break
                end
                
                inf = sup
                sup = inf + bucketSize
                bucket = bucket-1
        end
        
        -- find bucket for circle 2
        inf = minScale
        sup = inf + bucketSize
        bucket = 5
        while inf < maxScale do
                if inf <= scale_2 and sup >= scale_2 then
                        local availableChannel = audio.findFreeChannel()
                        audio.play(beatz[enso.context.selectedVoiceForColor[circle2.color]][bucket], {channel=availableChannel})
                        break
                end
                
                inf = sup
                sup = inf + bucketSize
                bucket = bucket-1
        end
end

Would it be more suitable for this thread to find its way to off topic? If I have made a placement mistake, please do correct me.

If this is iOS 5, please try the next daily build to come out. We yet another workaround for the hideous iOS 5/OpenAL regression bug to deal with a performance lag/stutter that was trying to work around a race condition bug in Apple's framework but injecting delays when pounding on the audio system really hard. (We just dealt with an app trying to fire off up to 75 simultaneous sounds in post collision events.)

Otherwise, superficially, your code looks fine and I don't know why there would be a lag on iPhone 4. However, you don't show how you actually call your play function. It could be that the code leading up to calling audio.play is the slow part in your code.

Hi ewing,
I've been hoping to hear from you. I have a iPhone 4 running 4.3.4 and an iPhone 4S running iOS 5. Both seem to be affected. Im using the .679 build.

In regards to the code leading up to audio.play, i'm not following you entirely. I pass the function two circles from a collision detection function (distance formula, not physics related) like so:

enso.soundWith(circle_i, circle_j)

The application was running brilliantly, up until i added the sounds for when the circles collide. Suddenly the circles are lagging and shuttering. Could you explain the, "We just dealt with an app trying to fire off up to 75 simultaneous sounds in post collision events," bit. It certainly seems relevant. Thanks ewing. It's great hearing from you.

That other app hit the iOS 5 bug I was describing we have a fix for in the next daily build. (Might come out later today.)

Once we fixed the bug, there were no latency issues as you describe in that other app, so I doubt there is a fundamental performance problem in the audio engine for what you are doing. Thus, I suggested it could be surrounding code.

I don't expect these other things will actually help, but you could rule them out:
1) Read the Audio Notes page, and pay special attention to setting the playback frequency in build.settings
2) lower the frequency of all your samples
3) optimize your code to reduce the number of table lookups, e.g.
eatz[enso.context.selectedVoiceForColor[circle2.color]][bucket]
is like 5 table lookups.
4) Remove calls to audio.findFreeChannel() and just call audio.play and let it auto assign a channel itself.

Also, make sure you didn't do something stupid in your code and reassign audio.loadSound to audio.loadStream.

"1) Read the Audio Notes page, and pay special attention to setting the playback frequency in build.settings"

You mean 'audioPlayFrequency = 44100' in the config file?

Yes, try lowering it to say 22050.

views:1834 update:2011/12/1 20:56:45
corona forums © 2003-2011