0

我正在构建一个 CoreAudio 应用程序,我需要在其中处理来自麦克风的原始输入样本。我使用两个线程,其中一个线程从麦克风输入产生样本,另一个线程正在消耗样本。这些线程共享一个(运行良好的)循环缓冲区,我从 Github 获取了它的实现(一个很好的例子可以在作者的博客上找到)。

作为我的问题的一个最小示例,我在 Github 上整理了一个小型 XCode 项目,因此您可以看到完整的代码。App 将麦克风样本放入循环缓冲区,然后从另一个线程读取缓冲区。消费线程计算 500 个样本的平均校正值(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 怎么可能在模拟器中正确分配和填充缓冲区,但在设备上保持缓冲区不变?我错过了什么?

我的示例的完整代码可以在 Github 上找到。

编辑

按照建议,我添加了一种方法来检查CoreAudio 调用后的错误@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 Œˇˇˇ
...
4

1 回答 1

3

弄清楚这些东西通常需要一些猜测工作,因为很难记住所有参数,但我要尝试的第一件事是在音频单元输入总线的输出范围上设置流格式(总线1)。

目前,您仅将其设置在输出总线(总线 0)的输入范围内,我不能 100% 确定这是否足够。

于 2012-08-22T21:25:03.143 回答