AVAudioPlayer Help: Playing multiple sounds simultaneously, stopping them all at once, and working around Automatic Reference Counting
First off, put the declaration and alloc/init of audioplayer
on the same line. Also, you can only play one sound per AVAudioPlayer
BUT you can make as many as you want simultaneously. And then to stop all of the sounds, maybe use a NSMutableArray
, add all of the players to it, and then iterate though and [audioplayer stop];
//Add this to the top of your file
NSMutableArray *soundsArray;
//Add this to viewDidLoad
soundsArray = [NSMutableArray new]
//Add this to your stop method
for (AVAudioPlayer *a in soundsArray) [a stop];
//Modified playSound method
-(IBAction)playSound:(id)sender {
NSString *soundFile = [[NSBundle mainBundle] pathForResource:@"Hello" ofType:@"wav"];
AVAudioPlayer *audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:soundFile] error:nil];
[soundsArray addObject:audioPlayer];
[audioPlayer prepareToPlay];
[audioPlayer play];
}
That should do what you need.
bgottlob
Updated on June 28, 2022Comments
-
bgottlob almost 2 years
I am trying to create buttons that
play
single sound files and onebutton
thatstops
all of the sounds that are currently playing. If the user clicks multiple buttons or the samebutton
in a short amount of time, the app should be playing all of the sounds simultaneously. I have accomplished this without much difficulty using the System Sound Services of iOS. However, the System Sound Services play the sounds through thevolume
that theiPhone's
ringer is set to. I am now trying to use theAVAudioPlayer
so that users canplay
the sounds through the media volume. Here is the code that I am currently (yet unsuccessfully) using the play the sounds:-(IBAction)playSound:(id)sender { AVAudioPlayer *audioPlayer; NSString *soundFile = [[NSBundle mainBundle] pathForResource:@"Hello" ofType:@"wav"]; audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:soundFile] error:nil]; [audioPlayer prepareToPlay]; [audioPlayer play]; }
Whenever I run this code in the iPhone Simulator, it does not play the sound but does display a ton of output. When I run this on my iPhone, the sound simply does not play. After doing some research and testing, I found that the
audioPlayer
variable is being released by Automatic Reference Counting. Also, this code works when the audioPlayer variable is defined as an instance variable and a property in my interface file, but it does not allow me to play multiple sounds at once.First thing's first: How can I play an infinite number of sounds at once using the
AVAudioPlayer
and sticking with Automatic Reference Counting? Also: When these sounds are playing, how can I implement a secondIBAction
method to stop playing all of them?-
lothorp over 10 yearsIt's worth noting that under ARC, you can't just allocate a local instance of
AVAudioPlayer
and play it. You have to retain it in some way. A strong property worked in my case.
-
-
bgottlob almost 12 yearsThanks, this works perfectly. Just for future reference, aside from allowing the audio players to be manipulated in the stop method, does putting the audio players in the array prevent Automatic Reference Counting from releasing the audio players' memory before the end of the playSound method?
-
Dustin almost 12 yearsIt should, but ARC has a habit of working perfectly until it randomly doesn't. I wouldn't worry about it.
-
adrian Coye over 10 yearsIn order to avoid leaks you want to set the delegate of audioPlayer and in the following delegate method remove the reference from the array : - (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag { [self.soundsArray removeObject:player]; }