AVAudioPlayer - playing multiple audio files, in sequence

后端 未结 5 804
忘了有多久
忘了有多久 2020-12-16 06:14

I want to play multiple MP3 files, in sequence (one after the other) , using AVAudioPlayer. I tried it, and it stops after playing the first MP3. However, if I go into deb

相关标签:
5条回答
  • 2020-12-16 06:23

    I think the AVQueuePlayer (subclass of AVPlayer) does exactly this job (play a sequence of items) since iOS 4.1 : http://developer.apple.com/library/ios/#documentation/AVFoundation/Reference/AVQueuePlayer_Class/Reference/Reference.html

    I didn't try it myself however but will definitely give a try to it.

    0 讨论(0)
  • 2020-12-16 06:29

    I've implemented a class to handle this.

    To use just do something like this:

    [looper playAudioFiles:[NSArray arrayWithObjects:
        @"add.mp3",
        [NSString stringWithFormat:@"%d.mp3", numeral1.tag],
        @"and.mp3",
        [NSString stringWithFormat:@"%d.mp3", numeral2.tag],
        nil
    ]];
    

    Looper.m

    #import "Looper.h"
    @implementation Looper
    @synthesize player, fileNameQueue;
    
    - (id)initWithFileNameQueue:(NSArray*)queue {
        if ((self = [super init])) {
            self.fileNameQueue = queue;
            index = 0;
            [self play:index];
        }
        return self;
    }
    
    - (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag {
        if (index < fileNameQueue.count) {
            [self play:index];
        } else {
            //reached end of queue
        }
    }
    
    - (void)play:(int)i {
        self.player = [[AVAudioPlayer alloc] initWithContentsOfURL:[[NSURL alloc] initFileURLWithPath:[[NSBundle mainBundle] pathForResource:[fileNameQueue objectAtIndex:i] ofType:nil]] error:nil];
        [player release];
        player.delegate = self;
        [player prepareToPlay];
        [player play];    
        index++;
    }
    
    - (void)stop {
        if (self.player.playing) [player stop];
    }
    
    - (void)dealloc {
        self.fileNameQueue = nil;
        self.player = nil;        
        [super dealloc];
    }
    
    @end
    

    Looper.h

    #import <Foundation/Foundation.h>
    
    
    @interface Looper : NSObject <AVAudioPlayerDelegate> {
        AVAudioPlayer* player;
        NSArray* fileNameQueue;
        int index;
    }
    
    @property (nonatomic, retain) AVAudioPlayer* player;
    @property (nonatomic, retain) NSArray* fileNameQueue;
    
    - (id)initWithFileNameQueue:(NSArray*)queue;
    - (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag;
    - (void)play:(int)i;
    - (void)stop;
    
    
    @end
    
    0 讨论(0)
  • 2020-12-16 06:31

    It is a good idea to initialize, prepare the items, and queue ahead of time, for example on the viewDidLoad method.

    If you are working on Swift,

        override func viewDidLoad() {
            super.viewDidLoad()
            let item0 = AVPlayerItem.init(URL: NSBundle.mainBundle().URLForResource("url", withExtension: "wav")!)
    
            let item1 = AVPlayerItem.init(URL: NSBundle.mainBundle().URLForResource("dog", withExtension: "aifc")!)
            let item2 = AVPlayerItem.init(URL: NSBundle.mainBundle().URLForResource("GreatJob", withExtension: "wav")!)
    
    
            let itemsToPlay:[AVPlayerItem] = [item0, item1, item2] 
            queuePlayer = AVQueuePlayer.init(items: itemsToPlay)
        }
    

    and then when an event occurs,

     queuePlayer.play()
    

    Notice that if you use the queue, you still might have some gaps between the sounds.

    You can find the Objective-C version in the question How to do something when AVQueuePlayer finishes the last playeritem

    Hope it helps.

    0 讨论(0)
  • 2020-12-16 06:35

    Use one AVAudioPlayer per sound.

    0 讨论(0)
  • 2020-12-16 06:47

    Well, your code example didn't work out of the box for me. Soooo, I figured I'd respond with a fixed version:

    Looper.h:

    #import <Foundation/Foundation.h>
    #import <AVFoundation/AVFoundation.h>
    
    @interface Looper : NSObject <AVAudioPlayerDelegate> {
        AVAudioPlayer* player;
        NSArray* fileNameQueue;
        int index;
    }
    
    @property (nonatomic, retain) AVAudioPlayer* player;
    @property (nonatomic, retain) NSArray* fileNameQueue;
    
    - (id)initWithFileNameQueue:(NSArray*)queue;
    - (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag;
    - (void)play:(int)i;
    - (void)stop;
    
    @end
    

    Looper.m:

    #import "Looper.h"
    @implementation Looper
    @synthesize player, fileNameQueue;
    
    - (id)initWithFileNameQueue:(NSArray*)queue {
        if ((self = [super init])) {
            self.fileNameQueue = queue;
            index = 0;
            [self play:index];
        }
        return self;
    }
    
    - (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag {
        if (index < fileNameQueue.count) {
            [self play:index];
        } else {
            //reached end of queue
        }
    }
    
    - (void)play:(int)i {
        self.player = [[AVAudioPlayer alloc] initWithContentsOfURL:[[NSURL alloc] initFileURLWithPath:[[NSBundle mainBundle] pathForResource:[fileNameQueue objectAtIndex:i] ofType:nil]] error:nil];
        [player release];
        player.delegate = self;
        [player prepareToPlay];
        [player play];    
        index++;
    }
    
    - (void)stop {
        if (self.player.playing) [player stop];
    }
    
    - (void)dealloc {
        self.fileNameQueue = nil;
        self.player = nil;        
        [super dealloc];
    }
    
    @end
    

    And here's how I would call it:

     Looper * looper = [[Looper alloc] initWithFileNameQueue:[NSArray arrayWithObjects: audioFile, audioFile2, nil ]];
    

    I only have slightly over a year of experience with iPhone/iPad development using Objective-C so feel free to respond with additional criticism.

    0 讨论(0)
提交回复
热议问题