如何在iOS中从服务器播放流式PCM数据?

时间:2016-11-22 03:06:44

标签: ios swift core-audio pcm audioqueue

我正在尝试开发app从服务器播放流式PCM数据的内容。

我使用过AudioQueue,但效果不佳。

PCM数据格式(来自服务器):

Sample rate = 48000, num of channel = 2, Bit per sample = 16

并且,服务器不会将固定字节流式传输到客户端。

(流变量字节。例如:30848,128,2764,......字节)

我的源代码:

在这里,ASBD结构我已经设置了&创建音频队列对象 (语言:斯威夫特)

// Create ASBD structure & set properties.
var streamFormat = AudioStreamBasicDescription()

streamFormat.mSampleRate = 48000
streamFormat.mFormatID = kAudioFormatLinearPCM
streamFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked
streamFormat.mFramesPerPacket = 1
streamFormat.mChannelsPerFrame = 2
streamFormat.mBitsPerChannel = 16

streamFormat.mBytesPerFrame = (streamFormat.mBitsPerChannel / 8) * streamFormat.mChannelsPerFrame
streamFormat.mBytesPerPacket = streamFormat.mBytesPerFrame
streamFormat.mReserved = 0

// Create AudioQueue for playing PCM streaming data.
var err = AudioQueueNewOutput(&streamFormat, self.queueCallbackProc, nil, nil, nil, 0, &aq)

...

我已经设置了ASBD结构&像上面一样创建了AudioQueue对象。

AudioQueue播放PCM数据非常好几秒钟,

但很快就会播放声音。我该怎么办?

(仍在流式传输,排队AudioQueue)

请给我任何想法。

1 个答案:

答案 0 :(得分:5)

你需要做(至少)两件事:

您需要缓冲数据以处理来自服务器的数据与音频队列回调请求的数据之间的延迟抖动和不同数据包大小。典型的解决方案涉及使用预先填充了一定数量数据的循环FIFO /缓冲区,足以处理更糟糕的网络抖动(您需要统计分析此数字)。音频队列回调只能从圆形fifo中复制请求的数据量。网络代码试图让它填满。

当两种费率不完全相同时,您可能还需要某种方法来隐藏错误:例如某种方式在网络速率太慢时复制或合成额外的声音,以及在网络速率过高时遗漏样本的某种方式,两种方式都尽可能听不到,并且不会在任何速率不连续时产生大声咔嗒声或网络辍学。