我在AVAudioEngine
中使用多个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
}
:
lastRenderTime
虽然这会产生一个相对正确的值,但我可以听到播放时间与听到的第一个声音之间的延迟。因为play(at:)
在我调用prepare(withFrameCount:)
后立即开始前进,并且必须有某种处理/缓冲时间偏移。
明显的延迟大约是100ms,这是非常大的,我需要一个精确的当前时间值来并行进行视觉渲染。
这可能没关系,但是每个音频文件都是AAC音频,我在播放器节点中安排它们的片段,我不直接使用缓冲区。
细分长度可能会有所不同。一旦我安排了音频数据,我也会在每个播放器节点上调用AVAudioPlayerNode
。
所以我的问题是,我观察到的延迟是缓冲问题吗? (我的意思是我应该安排更短的片段),有没有办法精确计算这个值,以便我可以调整当前的播放时间计算?
当我在一个4410
上安装一个点击块时,会使用长度为44100 Hz
的缓冲区调用该块,采样率为someotherpage.php
,这意味着0.1s的音频数据。我应该依靠它来计算延迟吗?
我想知道我是否可以信任我在tap块中获得的缓冲区的长度。或者,我正在尝试计算音频图的总延迟。有人可以提供有关如何准确确定此值的见解吗?
答案 0 :(得分:0)
来自 theanalogkid 在 Apple 开发者论坛上的帖子:
在系统上,延迟通过以下方式衡量:
音频设备 I/O 缓冲区帧大小 + 输出安全偏移 + 输出流延迟 + 输出设备延迟
如果您要计算总往返延迟,您可以添加:
输入延迟 + 输入安全对上述的偏移。
您在渲染过程中看到的时间戳。考虑缓冲区帧大小和安全偏移,但不考虑流和设备延迟。
iOS 允许您通过 AVAudioSession 访问上述信息中最重要的信息,如上所述,您还可以使用“首选”会话设置 - setPreferredIOBufferDuration
和 preferredIOBufferDuration
进行进一步控制。
/ 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);
音频单元还具有您可以查询的 kAudioUnitProperty_Latency
属性。