我正在构建一个 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 怎么可能在模拟器中正确分配和填充缓冲区,但在设备上保持缓冲区不变?我错过了什么?
编辑
按照建议,我添加了一种方法来检查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 Œˇˇˇ
...