user798370
user798370

Reputation: 179

AVAudioPlayer Won't Play Repeatedly

I have a relatively simple app that plays a sound using AVAudioPlayer, like this:

NSURL *file3 = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/ball_bounce.aiff", [[NSBundle mainBundle] resourcePath]]];
player3 = [[AVAudioPlayer alloc] initWithContentsOfURL:file3 error:nil];
[player3 prepareToPlay];

to later be called to play, like this:

[player3 play];

But this sound is called in multiple places (collisions with a bouncing ball), many times. Sometimes, the ball hits two things in quick enough succession where the sound from the first bounce is still playing when the ball collides a second time. This second bounce then does not produce a sound. How can I make it play a sound every time it collides, even if it involves paying a sound that overlaps an already playing sound?

Any help is greatly appreciated.

Upvotes: 6

Views: 861

Answers (2)

mkeremkeskin
mkeremkeskin

Reputation: 644

It is an old thread but maybe someone can benefit from this answer. Creating AVAudioPlayer repeatedly can be a burden for the app and can creates lags. In this case you can use SystemSound.

NSString *pathToMySound = [[NSBundle mainBundle] pathForResource:@"yourMusic" ofType:@"mp3"];
SystemSoundID soundID;
AudioServicesCreateSystemSoundID((__bridge CFURLRef)([NSURL fileURLWithPath: pathToMySound]), &soundID);
AudioServicesPlaySystemSound(soundID);

Downside of this solution, you can't adjust the volume.

Upvotes: 0

Jacob Relkin
Jacob Relkin

Reputation: 163308

One way to solve this problem would to be create a new instance of AVAudioPlayer if the previous one is already playing:

if([player3 isPlaying]) {
   AVAudioPlayer *newPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[player3 url]];
   [newPlayer setDelegate:self];
   [newPlayer play];
}

Then, in the delegate method audioPlayerDidFinishPlaying:successfully:, you should send the player the -release message:

- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag {
   if(player != player3) {
      [player release];
   }
}

This is just the way it has to be, as you do need a new source buffer for each concurrent sound playing. :(

Upvotes: 3

Related Questions