AVAudioEngine:立即启动一组 AVAudioPlayerNode

Dar*_*ack 4 core-audio ios avaudioengine

我正在开发一个同时启动多个循环的应用程序,并且应该保持它们的同步。

使用以前的简单方法来解决该问题(不使用 AVAudioEngine),我发现以编程方式按顺序启动多个音频播放器会在调用之间产生足够的延迟,从而导致结果无用;节拍明显不同步。

我可以使用 AVAudioEngine 实现这种功能吗?

目前,我正在将 AVAudioPlayerNodes 连接到混音器,并将缓冲区附加到它们并控制来自那里的输入。但我可以让它们同时启动吗?

看来节点在我调用播放之前不会开始产生声音,而在引擎启动之前这是无法完成的......

mra*_*sch 5

如需更深入的解释,请查看我的回答

AVAudioEngine 多个 AVAudioInputNode 无法完美同步播放


简而言之:

如果你的引擎已经在运行,你在 AVAudioNode 中有一个@property lastRenderTime - 你的播放器的超类 - 这是你获得 100% 样本帧精确同步的门票......

AVAudioFormat *outputFormat = [playerA outputFormatForBus:0];

const float kStartDelayTime = 0.0; // seconds - in case you wanna delay the start

AVAudioFramePosition startSampleTime = playerA.lastRenderTime.sampleTime;

AVAudioTime *startTime = [AVAudioTime timeWithSampleTime:(startSampleTime + (kStartDelayTime * outputFormat.sampleRate)) atRate:outputFormat.sampleRate];

[playerA playAtTime: startTime];
[playerB playAtTime: startTime];
[playerC playAtTime: startTime];
[playerD playAtTime: startTime];

[player...
Run Code Online (Sandbox Code Playgroud)

顺便说一句 - 您可以使用 AVAudioPlayer 类获得相同的 100% 样本帧准确结果...

NSTimeInterval startDelayTime = 0.0; // seconds - in case you wanna delay the start
NSTimeInterval now = playerA.deviceCurrentTime;

NSTimeIntervall startTime = now + startDelayTime;

[playerA playAtTime: startTime];
[playerB playAtTime: startTime];
[playerC playAtTime: startTime];
[playerD playAtTime: startTime];

[player...
Run Code Online (Sandbox Code Playgroud)

如果没有 startDelayTime,所有播放器的前 100-200 毫秒将被剪掉,因为启动命令实际上需要时间进入运行循环,尽管播放器现在已经 100% 同步启动(好吧,已被安排。但如果startDelayTime = 0.25就可以了。并且永远不要忘记提前准备播放你的玩家,这样在开始时就不需要进行额外的缓冲或设置 - 只需启动他们即可;-)