CoreAudio没有填充设备上运行的缓冲区(但在模拟器中)

时间:2012-08-21 19:24:12

标签: objective-c ios ios5 core-audio circular-buffer

我正在构建一个CoreAudio应用程序,我需要处理来自麦克风的原始输入样本。我使用两个线程,其中一个线程从麦克风输入生成样本,另一个线程正在消耗样本。这些线程共享一个(运行良好的)循环缓冲区,其实现我有taken from Github(一个很好的例子可以在the author's blog找到)。

作为我的问题的最小示例,我已将a small XCode project on Github放在一起,因此您可以看到完整的代码。应用程序将麦克风样本放入循环缓冲区,然后从另一个线程读取缓冲区。消费线程计算500个样本的average rectified value(ARV)并在控制台上输出ARV。

当我在iOS模拟器(5.1)中运行应用程序时,一切正常,我得到了所需的输出:

2012-08-21 20:58:31.882 BufferedSamples[23505:6003] 88
2012-08-21 20:58:31.890 BufferedSamples[23505:6003] 108
2012-08-21 20:58:31.890 BufferedSamples[23505:6003] 137
2012-08-21 20:58:31.891 BufferedSamples[23505:6003] 137
2012-08-21 20:58:31.892 BufferedSamples[23505:6003] 106
2012-08-21 20:58:31.901 BufferedSamples[23505:6003] 140
...

当我尝试在设备上运行应用程序(我尝试使用iPhone 3 / 3GS / 4)时,由于EXC_BAD_ACCESS指针,我在运行时遇到NULL错误。因此,我在CoreAudio回调函数中添加了NULL指针的检查(在文件DummyRecorder.m中):

// render samples into buffer
AudioBufferList bufferList;
bufferList.mNumberBuffers = 1;
bufferList.mBuffers[0].mNumberChannels = 1;
bufferList.mBuffers[0].mDataByteSize = inNumberFrames * kTwoBytesPerSInt16;
bufferList.mBuffers[0].mData = NULL;
AudioUnitRender(dummyRecorder->audioUnit, ioActionFlags, inTimeStamp, kInputBus, inNumberFrames, &bufferList);

// move samples to ring buffer
if (bufferList.mBuffers[0].mData != NULL)
    TPCircularBufferProduceBytes(&dummyRecorder->buffer, bufferList.mBuffers[0].mData, bufferList.mBuffers[0].mDataByteSize);
else
    NSLog(@"null pointer");

当我在模拟器中运行应用程序时,我仍然可以获得所需的输出,但在设备上,我得到以下内容:

2012-08-21 21:15:38.903 BufferedSamples[544:3b03] null pointer
2012-08-21 21:15:38.926 BufferedSamples[544:3b03] null pointer
2012-08-21 21:15:38.949 BufferedSamples[544:3b03] null pointer
2012-08-21 21:15:38.972 BufferedSamples[544:3b03] null pointer
2012-08-21 21:15:38.996 BufferedSamples[544:3b03] null pointer
2012-08-21 21:15:39.019 BufferedSamples[544:3b03] null pointer
...

CoreAudio如何在模拟器中正确分配和填充缓冲区,但在设备上保持缓冲区不变?我错过了什么?

The complete code of my example can be found on Github.

修改

我在CoreAudio调用后添加了method to check for errors@MichaelTyson建议。现在我在回调中这样做:

OSStatus err = AudioUnitRender(dummyRecorder->audioUnit, ioActionFlags, inTimeStamp, kInputBus, inNumberFrames, &bufferList);

// move samples to ring buffer
if (checkResult(err, "AudioUnitRender"))
    TPCircularBufferProduceBytes(&dummyRecorder->buffer, bufferList.mBuffers[0].mData, bufferList.mBuffers[0].mDataByteSize);

我还在Github上更新了代码。在模拟器中运行应用程序不会产生任何错误,而在设备上运行它会给我带来以下错误:

2012-08-22 11:19:49.248 BufferedSamples[637:3b03] /DummyRecorder.m:50: AudioUnitRender result -50 FFFFFFCE Œˇˇˇ
2012-08-22 11:19:49.271 BufferedSamples[637:3b03] /DummyRecorder.m:50: AudioUnitRender result -50 FFFFFFCE Œˇˇˇ
2012-08-22 11:19:49.294 BufferedSamples[637:3b03] /DummyRecorder.m:50: AudioUnitRender result -50 FFFFFFCE Œˇˇˇ
2012-08-22 11:19:49.317 BufferedSamples[637:3b03] /DummyRecorder.m:50: AudioUnitRender result -50 FFFFFFCE Œˇˇˇ
2012-08-22 11:19:49.341 BufferedSamples[637:3b03] /DummyRecorder.m:50: AudioUnitRender result -50 FFFFFFCE Œˇˇˇ
2012-08-22 11:19:49.364 BufferedSamples[637:3b03] /DummyRecorder.m:50: AudioUnitRender result -50 FFFFFFCE Œˇˇˇ
...

1 个答案:

答案 0 :(得分:3)

由于很难记住所有参数,因此通常会有一些猜测工作,因为很难记住所有参数,但我要做的第一件事是在音频单元输入的输出范围上设置流格式巴士(1路公交车)。

目前你只是在输出总线(总线0)的输入范围上设置它,我并不是100%确定这是足够的。