【发布时间】:2017-07-12 04:59:03
【问题描述】:
我在AVAudioEngine 中使用多个AVAudioPlayerNode 来混合音频文件以进行播放。
一旦完成所有设置(引擎准备好、启动、音频文件段计划),我将在每个播放器节点上调用 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)
问题出在当前播放时间上。
我使用此计算来获取值,其中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
}
虽然这会产生一个相对正确的值,但我可以听到我播放的时间和我听到的第一个声音之间的延迟。因为一旦我调用play(at:),lastRenderTime 立即开始前进,并且必须有某种处理/缓冲时间偏移。
明显的延迟在100ms左右,非常大,我需要一个精确的当前时间值来并行进行视觉渲染。
这可能没关系,但每个音频文件都是 AAC 音频,我在播放器节点中安排它们的片段,我不直接使用缓冲区。
段长度可能会有所不同。安排好音频数据后,我还会在每个播放器节点上调用prepare(withFrameCount:)。
所以我的问题是,我观察到的延迟是缓冲问题吗? (例如,我的意思是我应该安排较短的片段),有没有办法精确计算这个值,以便我可以调整我当前的播放时间计算?
当我在一个AVAudioPlayerNode 上安装一个 Tap 块时,该块被调用一个长度为4410 的缓冲区,采样率为44100 Hz,这意味着 0.1 秒的音频数据。我应该依靠它来计算延迟吗?
我想知道我是否可以相信我在点击块中获得的缓冲区的长度。或者,我正在尝试计算我的音频图的总延迟。有人可以提供有关如何精确确定此值的见解吗?
【问题讨论】:
标签: ios avaudioengine avaudioplayernode