Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

xArtx

macrumors 6502a
Original poster
Mar 30, 2012
764
1
Hi :)
I'm having a small problem with a sound sample I'm playing over & over in a program.
It's a wav file set up like this:
Code:
    NSURL *jurl = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/shot.wav", [[NSBundle mainBundle] resourcePath]]];
    
    NSError *jerror;
    shot = [[AVAudioPlayer alloc] initWithContentsOfURL:jurl error:&jerror];
    shot.numberOfLoops = 0;
    shot.volume = 0.20;
    
    [shot play]; // shot sound

Now what happens is, it works, but every so often when I play the sound,
there is about a half second pause in all the graphics when the sound is
about to play. The action resumes just as the sample begins.

Any ideas what might be happening?
Cheers, Art.
 
Last edited:

xStep

macrumors 68020
Jan 28, 2003
2,031
143
Less lost in L.A.
I don't know, but from parsing the documentation, I'd try the prepareToPlay method.

I'd also look to see how playAtTime: might work into this issue.

If your actual code is inline like that, I suggest trying the allocation at some earlier point and making shot an ivar.

Based on the name I'm wondering if this is a short sample sound like a gun shot. Perhaps there are better ways to execute such a thing and have it timed with the a graphic such as a gun shooting. Describe what you are trying to do as that might trigger someone with the experience to pop in on your question.
 

xArtx

macrumors 6502a
Original poster
Mar 30, 2012
764
1
Whoops..
Should have mentioned that the code above is only executed once,
then I just use:
Code:
[shot play];

Still, I'll look into your other suggestions.
Funny how it seems to only occur more if the sample hasn't played for a while.
 

xArtx

macrumors 6502a
Original poster
Mar 30, 2012
764
1
Which suggests there's a cache of audio samples, and a Least Recently Used cache algorithm has ejected the audio you want, so it has to be reloaded into RAM.

It could look that way, but this is the only sample in the program at the time I wrote the first post.
Usually I use at least two instances of the same sample in case they have
to be played simultaneously though.

Code:
if (swap == 0) {
[shota play];
swap = 1;
} else {
[shotb play];
swap = 0;
}
 

xStep

macrumors 68020
Jan 28, 2003
2,031
143
Less lost in L.A.
It could look that way, but this is the only sample in the program at the time I wrote the first post.
Usually I use at least two instances of the same sample in case they have
to be played simultaneously though.

Code:
if (swap == 0) {
[shota play];
swap = 1;
} else {
[shotb play];
swap = 0;
}

Your code doesn't support your statement of simultaneous playback. More importantly, the Apple docs clearly show how to play more than one sample in sync, if that is what you are referring to.
 

xArtx

macrumors 6502a
Original poster
Mar 30, 2012
764
1
Your code doesn't support your statement of simultaneous playback. More importantly, the Apple docs clearly show how to play more than one sample in sync, if that is what you are referring to.

At the time I wrote the first post,
I'm only referring to a program that has one instance of one sample.
Problem is the same if I load another instance of it though.
It makes no difference to the problem.
Still, it's only minor.
 

xArtx

macrumors 6502a
Original poster
Mar 30, 2012
764
1
Have you considered using AudioServicesPlaySystemSound instead of AVAudioPlayer?

I have used it in my very first iPhone program, and it was suitable for that,
but the problem is if the user has their ringer volume and normal (iPod)
volume set to different levels, system sound plays at the ringer volume level.
This means the user has to go into settings to adjust the ringer volume to change
the volume level of that particular app, which is going to be undesirable.

Documentation suggested you can't play sounds simultaneously,
but I did find that you can at least play (different) samples simultaneously,
which means the little routine I posted above could likely play different
instances of the same sound simultaneously.

It was fun cycling through all of the stock system sounds though.
You can cycle and play their IDs very fast, so the next sounds starts
before the other has finished, and quite a few overlap each other.
I was going to record it and use it as a ringtone :)
 

dejo

Moderator emeritus
Sep 2, 2004
15,982
452
The Centennial State
I have used it in my very first iPhone program, and it was suitable for that,
but the problem is if the user has their ringer volume and normal (iPod)
volume set to different levels, system sound plays at the ringer volume level.
This means the user has to go into settings to adjust the ringer volume to change
the volume level of that particular app, which is going to be undesirable.

Understood. Just thought I'd check.
 

xArtx

macrumors 6502a
Original poster
Mar 30, 2012
764
1
This seems to help.. every time you play the sample:

Code:
        [shoot play];
        [shoot prepareToPlay];
 

xArtx

macrumors 6502a
Original poster
Mar 30, 2012
764
1
Shouldn't play come after prepareToPlay?

I'm using prepareToPlay at the start when the sound files are loaded.
From there it's:

Code:
        [shoot play]; // play the sound instantly
        [shoot prepareToPlay]; // prepare to play for the next time


So play is always called after prepareToPlay.
 

xStep

macrumors 68020
Jan 28, 2003
2,031
143
Less lost in L.A.
Ok, I get it. You. Have an initial prep and then a prep right after the play command. I wonder of there might be a better way. My concern would be that if the next play occurs after a long period if time that the prep buffersogjt bee purged.
 

xArtx

macrumors 6502a
Original poster
Mar 30, 2012
764
1
Ok, I get it. You. Have an initial prep and then a prep right after the play command. I wonder of there might be a better way. My concern would be that if the next play occurs after a long period if time that the prep buffersogjt bee purged.

I understand, and If you are wondering I'll be able to update soon
with one more little experiment.

I was going to post & say the problem is about 90% solved,
but before posting this, I went through my source, and there
were a couple of instances where I forgot to put the prepareToPlay
after the play. Now everything is running smoothly :)

Note that this is an action game where the shot sample can (and should)
be called several times per second.

If it turns out the prep command keeps the file in RAM for the long term,
I guess it would be good to use it when the program shows a menu or something.
Then the button push or whatever triggers the play.

I have some other samples in the game that are called not so often.
One can be called up to 50 seconds into the game, and it's still fine.

I might test a longer period though, with a sample used only once or something like that.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.