【问题标题】:AVAudioPlayer - playing multiple audio files, in sequenceAVAudioPlayer - 按顺序播放多个音频文件
【发布时间】:2010-10-11 21:27:16
【问题描述】:

我想使用 AVAudioPlayer 按顺序(一个接一个)播放多个 MP3 文件。我试了一下,播放第一首MP3后就停止了。但是,如果我进入调试器,它工作正常.. 有什么想法吗?我在某处读到 AVAudioPlayer 在后台播放音频.. 我该如何防止它这样做? 瓦斯

【问题讨论】:

  • 这需要一个iPhoneSDK标签
  • 查看您的代码会有所帮助。要看的东西——你每个声音都使用一个 AVAudioPlayer 吗?当您播放 mp3 文件时,一次只能播放一个文件,因此任何重叠都可能不会产生预期的结果。不知道为什么调试器会有所作为,除非你也在模拟器中。也许模拟器可以同时播放多个 mp3 文件(因为这是 iPhone 中 mp3 解码硬件的结果)。更多信息将帮助我们找到解决方案,因此请随时发布 som 代码。

标签: iphone ios audio avaudioplayer


【解决方案1】:

我认为AVQueuePlayer(AVPlayer 的子类)正是从 iOS 4.1 开始完成这项工作(播放一系列项目): http://developer.apple.com/library/ios/#documentation/AVFoundation/Reference/AVQueuePlayer_Class/Reference/Reference.html

我自己没有尝试过,但肯定会尝试一下。

【讨论】:

  • 虽然这个答案解决了使用 AVAudioPlayer 的替代方案,但它比使用 Looper.* 上面的代码示例更加优雅和“内置”解决方案。这让我不得不不断分配一个新的 AVAudioPlayer 实例。当我最初采用这种方法时,我最终继承了 AVQueuePlayer,它为我提供了顺序音频文件播放所需的功能。所以是的,这是正确的答案。
【解决方案2】:

每个声音使用一个 AVAudioPlayer。

【讨论】:

    【解决方案3】:

    嗯,您的代码示例对我来说不是开箱即用的。太棒了,我想我会用一个固定的版本来回应:

    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
    

    我会这样称呼它:

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

    我在使用 Objective-C 开发 iPhone/iPad 方面只有一年多一点的经验,因此请随时提出更多批评意见。

    【讨论】:

      【解决方案4】:

      我已经实现了一个类来处理这个问题。

      要使用,只需执行以下操作:

      [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
      

      【讨论】:

        【解决方案5】:

        提前初始化、准备项目和排队是个好主意,例如在 viewDidLoad 方法上。

        如果你正在使用 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)
            }
        

        然后当事件发生时,

         queuePlayer.play()
        

        请注意,如果您使用队列,声音之间仍可能存在一些间隙。

        您可以在问题How to do something when AVQueuePlayer finishes the last playeritem中找到Objective-C版本

        希望对你有帮助。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-12-01
          相关资源
          最近更新 更多