C++ 核心音频环缓冲区数据为空
我正在制作《学习核心音频:Mac和iOS音频编程实践指南》一书中的一个演示。第8章展示了如何设置一个简单的音频单元图,以便从AUHAL输入单元播放到输出单元。此设置实际上没有连接音频单元;相反,这两个单元都使用回调并通过CARingBuffer实例传递音频数据。我正在为MacOS 10.15.6编写代码,并直接使用出版商提供的代码。下面是它的工作原理图: 代码生成并运行,但我没有得到音频。请注意,稍后,在引入语音合成单元后,我确实得到了回放,因此我知道基本功能正常 InputRenderProc请求AUHAL单元输入并将其存储在环形缓冲区中C++ 核心音频环缓冲区数据为空,c++,c,macos,audio,core-audio,C++,C,Macos,Audio,Core Audio,我正在制作《学习核心音频:Mac和iOS音频编程实践指南》一书中的一个演示。第8章展示了如何设置一个简单的音频单元图,以便从AUHAL输入单元播放到输出单元。此设置实际上没有连接音频单元;相反,这两个单元都使用回调并通过CARingBuffer实例传递音频数据。我正在为MacOS 10.15.6编写代码,并直接使用出版商提供的代码。下面是它的工作原理图: 代码生成并运行,但我没有得到音频。请注意,稍后,在引入语音合成单元后,我确实得到了回放,因此我知道基本功能正常 InputRenderPro
MyAUGraphPlayer *player = (MyAUGraphPlayer*) inRefCon;
// have we ever logged input timing? (for offset calculation)
if (player->firstInputSampleTime < 0.0) {
player->firstInputSampleTime = inTimeStamp->mSampleTime;
if ((player->firstOutputSampleTime > -1.0) &&
(player->inToOutSampleTimeOffset < 0.0)) {
player->inToOutSampleTimeOffset = player->firstInputSampleTime - player->firstOutputSampleTime;
}
}
// render into our buffer
OSStatus inputProcErr = noErr;
inputProcErr = AudioUnitRender(player->inputUnit,
ioActionFlags,
inTimeStamp,
inBusNumber,
inNumberFrames,
player->inputBuffer);
if (! inputProcErr) {
inputProcErr = player->ringBuffer->Store(player->inputBuffer,
inNumberFrames,
inTimeStamp->mSampleTime);
UInt32 sz = sizeof(player->inputBuffer);
printf ("stored %d frames at time %f (%d bytes)\n", inNumberFrames, inTimeStamp->mSampleTime, sz);
for (int i = 0; i < player->inputBuffer->mNumberBuffers; i++ ){
//printf("stored audio string[%d]: %s\n", i, player->inputBuffer->mBuffers[i].mData);
}
}
然而,当我像这样从GraphRenderCallback中的环形缓冲区提取时
MyAUGraphPlayer *player = (MyAUGraphPlayer*) inRefCon;
// have we ever logged output timing? (for offset calculation)
if (player->firstOutputSampleTime < 0.0) {
player->firstOutputSampleTime = inTimeStamp->mSampleTime;
if ((player->firstInputSampleTime > -1.0) &&
(player->inToOutSampleTimeOffset < 0.0)) {
player->inToOutSampleTimeOffset = player->firstInputSampleTime - player->firstOutputSampleTime;
}
}
// copy samples out of ring buffer
OSStatus outputProcErr = noErr;
// new CARingBuffer doesn't take bool 4th arg
outputProcErr = player->ringBuffer->Fetch(ioData,
inNumberFrames,
inTimeStamp->mSampleTime + player->inToOutSampleTimeOffset);
这不是许可问题;我有其他可以获得麦克风输入的非音频单元代码。此外,我还创建了一个plist,使这个应用程序每次都提示访问麦克风,所以我知道它正在工作。我不明白为什么数据会进入这个环形缓冲区,但永远不会出来。现在你需要声明你想使用麦克风,并提供一个解释字符串。2012年发布Learning Core Audio时并非如此 简而言之,您现在需要:
NSMicrophoneUsageDescription
字符串添加到您的Info.plist
Info.plist
,就像在.app包中一样。另外,如果从Xcode运行代码,代码似乎也不起作用。在我的情况下,它必须为Terminal.app运行。这可能是因为我的终端具有麦克风权限(可在系统首选项>安全与隐私>麦克风中查看)。通过在AVCaptureDevice
上使用requestAccessForMediaType
,您可以也可能应该明确请求用户(在本例中是您自己!)访问麦克风。没错,AVFoundation
code在Core Audio
tutorial中,世界将走向何方
中有关于上述步骤的更多详细信息
p、 我认为,那些认为捕获零而不是返回错误是个好主意的人,可能是那些发明了在正文中包含错误代码返回HTTP 200的人的好朋友。感谢您的回复。我已经在plist中有了NSMicrophoneUsageDescription,并在构建设置中链接了它。我知道它在工作,因为我被提示启用麦克风输入,我可以在安全和隐私中看到这个应用程序(CH08_AUGraphInput)和终端启用。我甚至似乎在回调中获得了麦克风字节;他们就是无法在环缓冲区获取中生存。发布一个链接到一个可运行的项目
MyAUGraphPlayer *player = (MyAUGraphPlayer*) inRefCon;
// have we ever logged output timing? (for offset calculation)
if (player->firstOutputSampleTime < 0.0) {
player->firstOutputSampleTime = inTimeStamp->mSampleTime;
if ((player->firstInputSampleTime > -1.0) &&
(player->inToOutSampleTimeOffset < 0.0)) {
player->inToOutSampleTimeOffset = player->firstInputSampleTime - player->firstOutputSampleTime;
}
}
// copy samples out of ring buffer
OSStatus outputProcErr = noErr;
// new CARingBuffer doesn't take bool 4th arg
outputProcErr = player->ringBuffer->Fetch(ioData,
inNumberFrames,
inTimeStamp->mSampleTime + player->inToOutSampleTimeOffset);
fetched 512 frames at time 160776.000000
fetched audio string[0, size 2048]: xx
fetched audio string[1, size 2048]: xx
fetched 512 frames at time 161288.000000
fetched audio string[0, size 2048]: xx
fetched audio string[1, size 2048]: xx