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

时间:2014-01-03 18:01:53

标签: ios audio core-audio

我在我的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吗?

2 个答案:

答案 0 :(得分:0)

AudioBufferQueueRef是一个指向AudioQueueBuffer的指针,它是一个struct。它是一种用于AudioQueueServices的opaque类型。 (这取决于你想做什么,并不是一个糟糕的方式)。

AudioBufferQueueRef不是一个Objective-c类,因此不能这样对待。

如果沿着音频单元路径向下走,我建议您创建自己的用户信息结构来处理您需要的内容。 Apple文档提供了此示例。

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

如果您正在寻找AVFoundation框架的高级别替代方案。我认为一个快乐的媒介是AudioQueueServices,可以在AudioToolbox框架中找到。

答案 1 :(得分:0)

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