播放在iOS中通过网络连接逐渐流式传输的WAV文件

Nei*_*fey 6 core-audio avaudioplayer ios

我正在使用第三方API,其行为如下:

  • 我必须连接到它的URL并发出我的请求,其中涉及POSTing请求数据;
  • 远程服务器然后一次发回"chunk",相应的WAV数据(我在NSURLConnectionDataDelegate的didReceiveData回调中收到).

对于参数而言,"chunk"是指数据的一些任意"下一部分",并不保证它对应于音频的任何有意义的划分(例如,它可能不与音频帧的特定倍数对齐,数量每个块中的字节数只是一些任意数字,对于每个块可以是不同的,等等).

现在 - 纠正我,如果我错了,我不能简单地使用AVAudioPlayer,因为我需要POST到我的URL,所以我需要通过NSURLConnection"手动"撤回数据.

那么......鉴于上述情况,那么当我从音频线上回来时,播放音频的最轻松的方式是什么呢?(我很欣赏我可以连接所有字节数组,然后将整个事物传递给最后的AVAudioPlayer--只是这会延迟播放的开始,因为我必须等待所有数据.)

Dan*_* S. 5

我将对解决方案进行鸟瞰.我认为这将有助于您找到具体的编码解决方案.

iOS提供了一个音频API动物园,其中一些可以用来播放音频.您选择哪一个取决于您的特定要求.正如您已经写过的那样,该AVAudioPlayer课程不适合您的情况,因为有了这个课程,您需要在开始播放音频时知道所有音频数据.显然,这不是流媒体的情况,所以我们必须寻找替代方案.

音频队列服务之间的良好折衷是易用性和多功能性,我推荐给你.另一种选择是音频单元,但它们是低级别的C API,因此使用起来不太直观,而且它们存在许多缺陷.所以坚持音频队列.

音频队列允许您定义当需要更多音频数据进行回放时从API调用的回调函数 - 类似于网络代码的回调,当有可用数据时调用它.

现在的困难是如何连接两个回调,一个提供数据,一个请求数据.为此,您必须使用缓冲区.更具体地说,一个队列(不要把这个队列与音频队列的东西混淆.音频队列服务是API的名称.另一方面,我接下来谈到队列是容器对象).为清楚起见,我将这个称为缓冲队列.

要将数据填充到缓冲区队列,您将使用网络回调函数,该函数从网络向您提供数据.数据将通过音频回调函数从缓冲区队列中取出,音频回调函数在需要更多数据时由音频队列服务调用.

您必须找到支持并发访问的缓冲区队列实现(也称为线程安全),因为它将从两个不同的线程(音频线程和网络线程)进行访问.或者找到已经线程安全的缓冲区队列实现,您可以自己处理线程安全,例如通过在某个调度队列上执行处理缓冲区队列的所有代码(这里是第三种队列;是的,Apple并且它爱他们).

现在,如果有的话会发生什么

  • 调用音频回调并且您的缓冲区队列为空,或

  • 调用网络回调并且您的缓冲区队列已满?

在这两种情况下,相应的回调函数都无法正常进行.如果没有可用的音频回调函数则无法提供音频数据,如果缓冲区队列已满,则网络回调函数无法存储传入数据.

在这些情况下,我会首先尝试阻止进一步执行,直到有更多数据可用或分别有空间来存储数据.在网络方面,这很可能会奏效.在音频方面,这可能会导致问题.如果它在音频方面引起问题,你有一个简单的解决方案:如果你没有数据,只需提供静音作为数据.这意味着您需要为音频队列服务提供零帧,它将作为静音来填补空白,直到网络提供更多数据.这是所有流媒体播放器在突然停止音频时使用的概念,它告诉您在某种旋转图标旁边"缓冲",表示您必须等待并且没有人知道多长时间.