关于 iPhone:iPhone – 同时启动多个 AVAudioPlayer 实例

iPhone - start multiple instances of AVAudioPlayer simultaneously

我正在使用多个 AVAudioPlayer 实例同时播放多个音频文件。我运行一个循环开始播放音频文件(prepareToPlay 被预先调用,循环只调用 play 方法)

但总是有一个玩家不同步玩。如何确保所有 4 个播放器同时开始播放音频?

谢谢。


Apple 文档讨论了如何"同时播放多个声音,每个音频播放器一个声音,精确同步"。也许您需要调用 playAtTime: 例如[myAudioPlayer playAtTime: myAudioPlayer.deviceCurrentTime + playbackDelay];

事实上,playAtTime 的 Apple 文档:包含以下代码片段:

1
2
3
4
5
NSTimeInterval shortStartDelay = 0.01;            // seconds
NSTimeInterval now = player.deviceCurrentTime;

[player       playAtTime: now + shortStartDelay];
[secondPlayer playAtTime: now + shortStartDelay];

它们应该同时播放(假设您为 shortStartDelay 选择了一个足够大的值——不要太快以至于它在该线程返回之前发生或其他什么)。


不幸的是,你不能。 AVAudioPlayer 不提供任何机制来细粒度控制开始时间。 currentTime 属性设置要读取的文件中的点,它不保证 AVAudioPlayer 实例何时开始在系统时间播放,这是同步多个音频流所需要的。

当我需要这种行为时,我使用 RemoteIO Audio Unit 和 3D Mixer Audio Unit ExtAudioFile。

编辑

请注意,从 iOS 4 开始,您可以使用 playAtTime:

同步多个 AVAudioPlayer 实例


只要您不必立即执行此操作,我的这段代码允许您执行此操作。您可以传入 targetTime 作为您想听到声音的时间戳。诀窍是利用时间戳和 NSObject 的延迟功能。此外,它还利用了更改播放器音量所需的时间比更改当前时间要少得多的事实。应该几乎完美地工作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
- (void) moveTrackPlayerTo:(double) timeInSong atTime:(double) targetTime {
 [trackPlayer play];
 trackPlayer.volume = 0;

 double timeOrig = CFAbsoluteTimeGetCurrent();
 double delay = targetTime - CFAbsoluteTimeGetCurrent();
 [self performSelector:@selector(volumeTo:)
      withObject:[NSNumber numberWithFloat:single.GLTrackVolume]
      afterDelay:delay];
 trackPlayer.currentTime = timeInSong - delay - (CFAbsoluteTimeGetCurrent() - timeOrig);
}

- (void) volumeTo:(NSNumber *) volNumb {
 trackPlayer.volume = [volNumb floatValue];
}


尝试为每个 AVAudioPlayer 对象设置相同的 currentTime 属性值。