LAA
LAA

Reputation: 31

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] error:NULL];
    theAudio.delegate = self;
    [theAudio play];   
    volumeTimer = [NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:@selector(updateVolume) userInfo:nil repeats:YES];
}

Upvotes: 3

Views: 4296

Answers (3)

hotpaw2
hotpaw2

Reputation: 70693

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.

Upvotes: 1

griotspeak
griotspeak

Reputation: 13247

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];
    }
}

Upvotes: 3

fbrereto
fbrereto

Reputation: 35925

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.

Upvotes: 4

Related Questions