从字节数组填充音频缓冲区并使用渲染回调播放

Posted

技术标签:

【中文标题】从字节数组填充音频缓冲区并使用渲染回调播放【英文标题】:filling an audio buffer from an array of bytes and playing using a render callback 【发布时间】:2014-01-03 18:01:53 【问题描述】:

我在我的 obj-c 代码中收到了一个字节数组,如下所示:

void sendAudio(int length, Byte* byteArrPtr) 
bufferStream *newBuffer = [bufferStream getInstance];
for (int i=0; i<length;, i++)

uint16_t intData = OSReadBigInt16(byteArrPtr,2);
//How do I add intData to buffer here?
byteArrPtr++;



音频是交错的,44.1KHz 采样率,并以 2048 帧为一组发送。

我的目标是使用渲染回调在设备上播放此音频数据,但我不清楚如何用此数据填充音频缓冲区并让我的 remoteIO 音频单元从缓冲区中拉出。我在 SO 上找到的最接近的东西是这篇文章Setting up an Audio Unit format and render callback for interleaved PCM audio,其中答案建议为帧数(在我的情况下为 2048)预分配一个缓冲区,并让渲染回调中的 AudioBufferList 对象指向这个新的缓冲区。

我创建了一个缓冲区类,我正在尝试对其进行写入和读取,如下所示:

#import <Foundation/Foundation.h>
#import <AudioToolbox/AudioToolbox.h>

@interface bufferStream : NSObject 
AudioQueueBufferRef *buffer;


@property (nonatomic,assign)AudioQueueBufferRef *buffer;
+(bufferStream*)getInstance;

@end

在实现中:

#import "bufferStream.h"

@implementation bufferStream
@synthesize buffer;
static bufferStream *instance = nil;
+(bufferStream*)getInstance

@synchronized(self)

    if(instance==nil)
    
        instance = [bufferStream new];
    

return instance;


@end

我一直不知道如何填充这个缓冲区,以便我可以在代码的其他地方从中提取。我应该为此使用 AudioBufferQueueRef 吗?

【问题讨论】:

【参考方案1】:

AudioBufferQueueRef 是一个指向 AudioQueueBuffer 的指针,它是一个结构。它是一种用于 AudioQueueServices 的不透明类型。 (这取决于你想做什么,这不是一个坏方法)。

AudioBufferQueueRef 不是objective-c 类,因此不能这样对待。

如果您使用音频单元路径,我建议您创建自己的用户信息结构来处理您需要的内容。 Apple 文档提供了这方面的示例。

我还建议重新考虑您正在实施的设计模式,因为 Objective-c 可能会对性能产生影响。最好尽可能保持在 C 或 C++ 级别。

如果您追求高级别的替代方案,请查看 AVFoundation 框架。我认为一个快乐的媒介是 AudioQueueServices,它位于 AudioToolbox 框架中。

【讨论】:

“如果你沿着音频单元路径走,我建议创建你自己的用户信息结构来处理你需要的东西。Apple 文档给出了这方面的例子。”您可以扩展用户信息结构或链接到您引用的文档吗?你的意思是设置一个 AudiostreamBasicDescription 吗?我打算最终将此音频流发布为应用程序间音频节点,据我所知,这需要我为 IAA 注册一个音频单元【参考方案2】:

iOS 音频队列使用拉模型,而不是推模型。因此,您不要直接将数据推送到音频驱动程序。相反,您的应用程序必须将数据临时保存到中间数据缓冲区(循环队列或 fifo)中,然后返回到运行循环。然后,当调用音频回调函数时,该函数可以从中间缓冲区复制(拉取)所需的数据量(如果可用),并更新参数(标志、指针或索引)以表明它有。

【讨论】:

感谢您的回答。我知道 Core Audio 的拉动模型。您知道将浮点数组加载到循环缓冲区中进行播放的任何代码示例吗?谢谢!

以上是关于从字节数组填充音频缓冲区并使用渲染回调播放的主要内容,如果未能解决你的问题,请参考以下文章

音频队列播放完成的准确时间

如何通过 javascript/html5 播放 wav 音频字节数组?

如何桥接字节数组和音频流?

Java 音频字节缓冲区需要不同的时间来填充

核心音频:文件播放渲染回调函数

PCM音频实时播放:音频字节数组(16/8位)转为PCM ArrayBuffer流