我正在使用行为如下的第三方API:
" chunk"为了论证,我们指的是一些随意的"下一部分"对于数据的数据,并不保证它对应于音频的任何有意义的划分(例如,它可能不与音频帧的特定倍数对齐),每个块中的字节数只是一些任意数字,每个数字可以是不同的大块等)。
现在 - 如果我错了,请纠正我,我不能简单地使用AVAudioPlayer,因为我需要POST到我的网址,所以我需要手动撤回数据"&#34 ;通过NSURLConnection。
所以......鉴于上述情况,那么对于我来说,回放音频的最轻松的方式是什么呢? (我很欣赏我可以连接所有字节数组,然后将整个事物传递给最后的AVAudioPlayer--只是这会延迟播放的开始,因为我必须等待所有数据。)
答案 0 :(得分:5)
我将给出一只鸟的视角来解决问题。我认为这将有助于您找到具体的编码解决方案。
iOS提供了一个音频API动物园,其中一些可以用来播放音频。您选择哪一个取决于您的特定要求。正如您已经写过的那样,AVAudioPlayer
类不适合您的情况,因为有了这个类,您需要在开始播放音频时知道所有音频数据。显然,这不是流媒体的情况,所以我们必须寻找替代方案。
易用性和多功能性之间的良好权衡是Audio Queue Services,我建议你这样做。另一种选择是音频单元,但它们是低级别的C API,因此使用起来不太直观,而且它们存在许多缺陷。所以坚持音频队列。
音频队列允许您定义当需要更多音频数据进行回放时从API调用的回调函数 - 类似于网络代码的回调,当有可用数据时会调用它。
现在困难在于如何连接两个回调,一个提供数据,另一个请求数据。为此,您必须使用缓冲区。更具体地说,是队列(不要将此队列与音频队列内容混淆。音频队列服务是API的名称。另一方面,queue I'm talking about next是容器对象)。为清楚起见,我将这称为缓冲队列。
要将数据填充到缓冲区队列中,您将使用网络回调函数,该函数从网络向您提供数据。数据将通过音频回调函数从缓冲区队列中取出,音频回调函数在需要更多数据时由音频队列服务调用。
您必须找到支持并发访问的缓冲区队列实现(也称为线程安全),因为它将从两个不同的线程(音频线程和网络线程)进行访问。 作为查找已经线程安全的缓冲区队列实现的替代方法,您可以自己处理线程安全,例如:通过在某个dispatch queue (3rd kind of queue here; yes, Apple and IT love them)上执行处理缓冲区队列的所有代码。
现在,如果
,会发生什么调用音频回调,缓冲区队列为空,或
调用网络回调,你的缓冲区队列已经满了吗?
在这两种情况下,相应的回调功能都无法正常进行。如果没有可用的音频回调功能,则无法提供音频数据,如果缓冲队列已满,网络回调功能无法存储传入数据。
在这些情况下,我会首先尝试阻止进一步执行,直到有更多数据可用或分别有空间来存储数据。在网络方面,这很可能会奏效。在音频方面,这可能会导致问题。如果它在音频方面引起问题,你有一个简单的解决方案:如果你没有数据,只需提供静音作为数据。这意味着您需要为音频队列服务提供零帧,它将作为静音来填补空白,直到网络提供更多数据。 这是所有流媒体播放器在突然停止音频时使用的概念,它告诉您“缓冲”#34;旁边是某种旋转图标,表示你必须等待,没人知道多长时间。