Playing multiple sounds at once?
I have 6 sounds on one view.
However I want it so that I can play more than one at once, So you tap sound 1 (sound 1 is playing) then sound 2 plays. while sound 1 is still playing.
But at the moment I press sound 1 (sound 1 plays), press sound 2 (sound 2 plays, but sound 1 stops)
Here is the code for the audio part.
- (IBAction)oneSound:(id)sender; {
NSString *path = [[NSBundle mainBundle] pathForResource:@"1" ofType:@"wav"];
if (theAudio) [theAudio release];
theAudio = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
theAudio.delegate = self;
[theAudio play];
volumeTimer = [NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:@selector(updateVolume) userInfo:nil repeats:YES];
}
- (IBAction)twoSound:(id)sender; {
NSString *path = [[NSBundle mainBundle] pathForResource:@"2" ofType:@"wav"];
if (theAudio) [theAudio release];
theAudio = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] erro开发者_开发问答r:NULL];
theAudio.delegate = self;
[theAudio play];
volumeTimer = [NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:@selector(updateVolume) userInfo:nil repeats:YES];
}
There is some important code missing, but it looks as if theAudio
is a global you are using to manage the playing of your sounds. Since you destroy it whenever a sound is played whatever is currently playing will stop in preparation for the next sound.
There are several ways to fix this, one being that each sound gets its own unique AVAudioPlayer
instance.
don't release the player just because it exists. release when finished playing
You should implement this in the app delegate or a property of the app delegate so that the delegate reference remains valid if you pop the view.
You should not need to do this for each voice. Each voice will initial the player with a different filename or URL. You gain this by making sure that you will release when finished playing. The other thing to take care of is releasing players if the player doesn't finish because of an interruption.
#pragma mark -
#pragma mark Audio methods
-(void)playNote:(NSInteger)noteNumber {
NSString *soundFilePath =
[[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"%i", noteNumber ]
ofType: @"caf"];
NSURL *fileURL = [[NSURL alloc] initFileURLWithPath: soundFilePath];
AVAudioPlayer *playerToPrepare = [[AVAudioPlayer alloc] initWithContentsOfURL:fileURL
error:nil];
[fileURL release];
[playerToPrepare prepareToPlay];
[playerToPrepare setDelegate: self];
[playerToPrepare play];
}
#pragma mark -
#pragma mark AVAudioPlayer delegate methods
- (void) audioPlayerDidFinishPlaying: (AVAudioPlayer *) playerThatFinished
successfully: (BOOL) completed {
if (completed) {
[playerThatFinished release];
}
}
You can declare and use:
AVAudioPlayer *theAudio1; // for file 1.wav
AVAudioPlayer *theAudio2; // for file 2.wav
...
AVAudioPlayer *theAudio6; // etc.
instead of releasing and reusing just one AVAudioPlayer.
精彩评论