AVAudioPlayerNode lastRenderTime

Vin*_*nce 16 ios avaudioengine avaudioplayernode

我使用了多个AVAudioPlayerNodeAVAudioEngine为混合播放的音频文件.完成所有设置(引擎准备,启动,音频文件段已安排)后,我play()在每个播放器节点上调用方法开始播放.

因为遍历所有播放器节点需要花费时间,所以我拍摄了第一个节点lastRenderTime值的快照,并使用它来计算节点play(at:)方法的开始时间,以保持节点之间的播放同步:

let delay = 0.0
let startSampleTime = time.sampleTime     // time is the snapshot value    
let sampleRate = player.outputFormat(forBus: 0).sampleRate
let startTime = AVAudioTime(
        sampleTime: startSampleTime + AVAudioFramePosition(delay * sampleRate),
        atRate: sampleRate)
player.play(at: startTime)
Run Code Online (Sandbox Code Playgroud)

问题在于当前播放时间.

我使用这个计算得到值,在seekTime我们寻找玩家的情况下,我跟踪的值是哪里.它0.0开始时:

private var _currentTime: TimeInterval {
    guard player.engine != nil,
          let lastRenderTime = player.lastRenderTime,
          lastRenderTime.isSampleTimeValid,
          lastRenderTime.isHostTimeValid else {
        return seekTime
    }

    let sampleRate = player.outputFormat(forBus: 0).sampleRate
    let sampleTime = player.playerTime(forNodeTime: lastRenderTime)?.sampleTime ?? 0
    if sampleTime > 0 && sampleRate != 0 {
        return seekTime + (Double(sampleTime) / sampleRate)
    }
    return seekTime
}
Run Code Online (Sandbox Code Playgroud)

虽然这会产生一个相对正确的值,但我可以听到播放时间和听到的第一个声音之间的延迟.因为lastRenderTime一旦我打电话立即开始前进play(at:),并且必须有某种处理/缓冲时间偏移.

明显的延迟大约是100ms,非常大,我需要一个精确的当前时间值来并行进行视觉渲染.

它可能没关系,但每个音频文件都是AAC音频,我在播放器节点中安排它们的片段,我不直接使用缓冲区.细分长度可能会有所不同.prepare(withFrameCount:)一旦我安排了音频数据,我也会调用每个播放器节点.

所以我的问题是,我观察到的延迟是缓冲问题吗?(我的意思是我应该安排更短的片段),有没有办法精确计算这个值,以便我可以调整当前的播放时间计算?

当我在一个上安装一个tap块时AVAudioPlayerNode,用一个长度缓冲区调用该块4410,采样率是44100 Hz,这意味着0.1s的音频数据.我应该依靠它来计算延迟吗?

我想知道我是否可以信任我在tap块中获得的缓冲区的长度.或者,我正在尝试计算音频图的总延迟.有人可以提供有关如何准确确定此值的见解吗?

sbo*_*oth 2

来自theanalogkid在 Apple 开发者论坛上的帖子:

在系统上,延迟通过以下方式衡量:

音频设备 I/O 缓冲区帧大小 + 输出安全偏移 + 输出流延迟 + 输出设备延迟

如果您尝试计算总往返延迟,您可以添加:

输入延迟 + 输入安全偏移量。

您在渲染过程中看到的时间戳。考虑了缓冲区帧大小和安全偏移,但不考虑流和设备延迟。

iOS 使您可以通过 AVAudioSession 访问上述最重要的信息,并且如上所述,您还可以使用“首选”会话设置- setPreferredIOBufferDurationpreferredIOBufferDuration进行进一步控制。

/ The current hardware input latency in seconds. */
@property(readonly) NSTimeInterval inputLatency  NS_AVAILABLE_IOS(6_0);
/ The current hardware output latency in seconds. */
@property(readonly) NSTimeInterval outputLatency  NS_AVAILABLE_IOS(6_0);
/ The current hardware IO buffer duration in seconds. */
@property(readonly) NSTimeInterval IOBufferDuration  NS_AVAILABLE_IOS(6_0);
Run Code Online (Sandbox Code Playgroud)

音频单元还具有kAudioUnitProperty_Latency您可以查询的属性。