如何确保在 iOS 上的时限内呈现音频?
Posted
技术标签:
【中文标题】如何确保在 iOS 上的时限内呈现音频?【英文标题】:How to ensure audio rendered within time limit on iOS? 【发布时间】:2016-07-08 15:35:57 【问题描述】:我正在通过ios Audio Unit render callback 从我的自定义合成器代码中呈现低延迟音频。显然,如果我的渲染代码太慢,那么它将太晚从回调中返回,并且会出现缓冲区欠载。我从经验中知道这会导致输出静音。
我想知道我有什么时间限制,以便我可以管理处理级别以匹配设备限制等。
显然,缓冲区的长度(以样本为单位)决定了音频呈现的持续时间,这设置了一个总体限制。但是我怀疑 Apple 音频引擎在发出渲染回调和要求响应之间会有更小的时间限制。
-
我怎样才能知道这个时间限制,我可以在回调函数本身内做些什么吗?
如果我碰巧超过了时间限制并导致缓冲区不足,是否有我可以接收到的通知或我可以查询的状态对象?
注意:在我的应用程序中,我正在创建一个“输出”音频单元,因此我无需担心将音频单元链接在一起。
【问题讨论】:
【参考方案1】:在音频单元回调中可以完成的音频渲染量取决于 iOS 设备型号和操作系统版本,以及由于温度或背景模式导致的潜在 CPU 时钟速度限制。因此,它需要在您计划支持您的应用程序的最旧、最慢的 iOS 设备上进行配置,并留有一些余量。
为了支持 iOS 9,我非常保守地在 iPhone 4S 测试设备(800 MHz 的 ARM Cortex A9 CPU)或更旧的速度较慢的设备上使用更早的 iOS 版本来分析我的应用程序。在进行此分析时,可以添加一定百分比的“make work”来测试音频回调并查看是否有任何余量(对于 50% 的余量,生成两次样本缓冲区等)。其他开发人员似乎不太保守.
这就是为什么移动音频开发人员拥有(或可以访问)多个 iOS 设备(越旧越好)很重要的原因。如果回调在旧的慢文本设备上满足时间限制,那么在任何较新的 iOS 设备上它很可能已经足够快了。
根据操作系统版本,欠载可能导致静音,或者音频单元停止或崩溃(在可预测的时间内没有更多或没有足够的回调可以检测到)。
但避免欠载的最佳方法是在音频单元线程之外的另一个线程中完成大部分繁重的音频工作,并使用无锁循环 fifo/队列将样本传入/传出音频单元回调。
【讨论】:
您已经概述了一些好的实践要点,但我仍然在回答我提出的 2 个具体问题。这是关于iOS是否可以提供动态数据。在我的应用程序中,我能够动态调整合成的复杂性,因此对于旧设备,我可以降低质量和处理时间,而不是为最坏情况的设备设计一个固定的合成引擎。这意味着我需要即时了解可用时间和/或是否发生欠载。你能帮忙吗? 在开始音频之前(尤其是在您的应用无法识别且具有预先校准的性能测量的设备型号上),您的应用可能会运行一些基准合成例程以查看生成音频需要多少秒或毫秒N 个样本。根据需要更改 N,以在至少十分之一秒内获得多次可重复测量。使用 Mach 计时器为您的基准代码计时。动态中没有用于此的公共 API(CPU 周期计时器和时钟速率对用户空间隐藏)。您可以通过计算每秒回调次数和平均值来检测欠载(为时已晚)。 谢谢。我一直想知道基准测试。遗憾的是没有公共 API 来获得明确的“这是你有多久了”或“嘿,你错过了最后期限”。我将从您的 cmets 中添加一些注释到您的答案中,如果这些编辑被接受,则将其标记为正确答案。【参考方案2】:除了 hotpaw2 所说的,我遇到的性能最差的 iOS 设备是没有后置摄像头的 iPhone touch 16G。我做过项目,除了 ipod touch 16G 之外的所有设备都可以流畅地播放音频。我不得不将缓冲区持续时间提高到下一个大小以适应。
我通常在渲染回调之前在单独的无锁环形缓冲区中完成所有音频准备,并将渲染回调限制为复制数据。我让应用程序“处理”缓冲区不足。
我个人从未测量过渲染回调方差,但我猜想它会始终等于缓冲区持续时间,并且抖动极小(例如 5 毫秒)。我怀疑一次是 4.9 毫秒,下一次是 5.1 毫秒。
要获得一些计时信息,在mach_time.h
您可以使用mach_absolute_time()
获得一些计时。
您并没有真正说明您的时间要求是什么。我假设您需要低延迟音频。否则,您可以将缓冲区持续时间设置得相当大。我假设您想使用此代码增加慢速设备的延迟。我通常会找到适用于 iPod 16G 的设备并将其用作最坏的情况。
NSTimeInterval _preferredDuration = ...
NSError* err;
[[AVAudioSession sharedInstance]setPreferredIOBufferDuration:_preferredDuration error:&err];
当然,您应该得到实际使用的持续时间。操作系统会根据采样率选择 2 的幂:
NSTimeInterval _actualBufferDuration;
_actualBufferDuration = [[AVAudioSession sharedInstance] IOBufferDuration];
就设备性能进行调整。可以设置缓冲时长
【讨论】:
以上是关于如何确保在 iOS 上的时限内呈现音频?的主要内容,如果未能解决你的问题,请参考以下文章