我正在使用行为如下的第三方API:
出于论证的考虑,“块”是指数据的任意“下一部分”,但不能保证它对应于音频的任何有意义的划分(例如,它可能未与音频帧的特定倍数对齐,即每个块中的字节数只是一些任意数字,每个数字可能不同,依此类推)。
现在,如果我错了,请纠正我,我不能简单地使用AVAudioPlayer,因为我需要发布到我的URL,所以我需要通过NSURLConnection“手动”拉回数据。
那么...鉴于以上所述,那么当我通过线路播放音频时,最无痛的方式是什么? (我很欣赏我可以连接所有字节数组,然后在结尾处将整个内容传递给AVAudioPlayer-但这会延迟回放的开始,因为我必须等待所有数据。)
最佳答案
我将鸟瞰该解决方案。我认为这将在很大程度上帮助您找到具体的编码解决方案。
iOS提供了一个音频API动物园,其中一些可用于播放音频。选择哪一种取决于您的特定要求。正如您已经写过的,AVAudioPlayer
类不适合您的情况,因为使用此类,您需要在开始播放音频的那一刻就知道所有音频数据。显然,流式传输不是这种情况,因此我们必须寻找替代方法。
易用性和多功能性之间的一个很好的折衷是Audio Queue Services,我为您推荐。另一个选择是音频单元,但是它们是低级C API,因此使用起来不太直观,并且有很多陷阱。因此,请坚持使用“音频队列”。
音频队列允许您定义需要更多音频数据进行播放时从API调用的回调函数-类似于网络代码的回调(当有可用数据时调用)。
现在的难题是如何连接两个回调,一个提供数据,另一个请求数据。为此,您必须使用缓冲区。更具体地说,是一个队列(不要将此队列与Audio Queue东西混淆。AudioQueue Services是API的名称。另一方面,queue I'm talking about next是一个容器对象)。为了清楚起见,我将其称为一个缓冲区队列。
要将数据填充到缓冲区队列中,您将使用网络回调函数,该函数从网络向您提供数据。音频回调函数会从缓冲区队列中取出数据,当需要更多数据时,音频队列服务会调用该函数。
您必须找到一个支持并发访问的缓冲区队列实现(又名线程安全),因为它将从音频线程和网络线程这两个不同的线程进行访问。
除了查找已经是线程安全的缓冲区队列实现之外,您还可以自己照顾线程安全,例如通过在某个dispatch queue (3rd kind of queue here; yes, Apple and IT love them)上执行所有处理缓冲区队列的代码。
现在,如果发生
在这两种情况下,各自的回调函数均无法正常进行。如果没有可用的音频回调函数,则音频回调函数将无法提供音频数据;如果缓冲区队列已满,则网络回调函数将无法存储传入的数据。
在这些情况下,我将首先尝试阻止进一步执行,直到有更多数据可用或分别有空间存储数据为止。在网络方面,这很可能会起作用。在音频方面,这可能会引起问题。如果它在音频方面造成问题,那么您有一个简单的解决方案:如果没有数据,只需提供静音作为数据即可。这意味着您需要向音频队列服务提供零帧,音频队列服务将以静默的方式填补空白,直到从网络上获得更多数据为止。
这是所有流播放器在音频突然停止时使用的概念,它告诉您在某种旋转图标旁边的“缓冲”,表明您必须等待并且没人知道要持续多长时间。
关于ios - 在iOS中通过网络连接逐渐播放流式播放的WAV文件,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24502197/