gpt4 book ai didi

c++ - AUHAL 单元的 AudioBufferList,其输出流格式被压缩。

转载 作者:太空宇宙 更新时间:2023-11-04 12:51:08 27 4
gpt4 key购买 nike

致谢

我知道这篇文章很长,但我尽量将我的问题放在上下文中,因为我认为它非常独特(除了 this one 之外找不到任何相关问题。最后一个问题在最后帖子和 here's the complete code

首先,了解一下背景。我正在使用 CoreAudioAudioToolbox 库,更准确地说是 Audio Units。我在 macOS 上。我的最终目标是从任何输入设备录制音频(因此在简单的 AudioQueueBuffer 上使用音频单元)并将其写入音频文件。我认为我的程序中最棘手的部分是在单个音频单元内从 LPCM 转换为 AAC(在我的例子中),因此没有使用 AUGraph。

我的程序基本上只是一个音频单元,封装在一个类 AudioUnit mInputUnit 中,这是一个 AUHAL 单元。因此,我遵循了这个 this technical note设置它。基本上,我将输入元素的输入范围(因为输出元素被禁用)链接到音频设备,即我的内置麦克风。

然后我相应地更新单元输出范围的 AudioFormat。

  ...
inputStream.mFormatID = kAudioFormatMPEG4AAC;
inputStream.mFormatFlags = 0;
inputStream.mBitsPerChannel = 0;
checkError(
AudioUnitSetProperty(
mInputUnit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Output,
1,
&inputStream,
propertySize
),
"Couldn't set output stream format."
);

因此,此时,音频单元应该按如下方式工作:

在 LPCM [INPUT SCOPE] 中从输入设备记录 ==> 从 LPCM 转换为 ==> 在 AAC 中渲染。

请注意,每种流格式(输入和输出)使用2 个 channel 。输入流和输出流都没有将其 mFormatFlags 设置为 kAudioFormatIsNonInterleaved,因此它们都是交错的。事实上,我认为这就是问题的来源,但不明白为什么。

此时,似乎一切正常。当我在设置输入回调后尝试渲染音频单元时出现问题。

我发现了一条说明如下的注释:

“By convention, AUHAL deinterleaves multichannel audio. This means that you set up two AudioBuffers of one channel each instead of setting up one AudioBuffer with mNumberChannels==2. A common cause of paramErr (-50) problems in AudioUnitRender() calls is having AudioBufferLists whose topology (or arrangement of buffers) doesn’t match what the unit is prepared to produce. When dealing at the unit level, you almost always want to do noninterleaved like this.”

摘自:Chris Adamson 和 Kevin Avila。 “学习核心音频:Mac 和 iOS 音频编程实践指南”。 iBooks。

因此,我遵循了适当的代码结构来呈现音频。

OSStatus Recorder::inputProc(
void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData
)
{
Recorder *This = (Recorder *) inRefCon;
CAStreamBasicDescription outputStream;
This->getStreamBasicDescription(kAudioUnitScope_Output, outputStream);

UInt32 bufferSizeBytes = inNumberFrames * sizeof(Float32);
UInt32 propertySize = offsetof(AudioBufferList, mBuffers[0]) + (sizeof(AudioBuffer) * outputStream.mChannelsPerFrame);
auto bufferList = (AudioBufferList*) malloc(propertySize);
bufferList->mNumberBuffers = outputStream.mChannelsPerFrame;

for(UInt32 i = 0; i < bufferList->mNumberBuffers; ++i)
{
bufferList->mBuffers[i].mNumberChannels = 1;
bufferList->mBuffers[i].mDataByteSize = bufferSizeBytes;
bufferList->mBuffers[i].mData = malloc(bufferSizeBytes);
}

checkError(
AudioUnitRender(
This->mInputUnit,
ioActionFlags,
inTimeStamp,
inBusNumber,
inNumberFrames,
bufferList
),
"Couldn't render audio unit."
);
free(bufferList);
}

然后,当我尝试渲染音频时,出现以下错误 Error: Couldn't render audio unit。 (-50) 这实际上是应该按照注释修复 的那个,这让我更加困惑。

问题

在这一点上,我不知道这是否与我的整体架构有关,即我是否应该使用 AUGraph 并添加一个输出单元,而不是尝试从规范格式转换为单个 AUHAL 单元内的压缩格式?还是这与我预先分配 AudioBufferList 的方式有关?

最佳答案

我已经通过重新设计整个流程来解决这个问题。简而言之,我仍然有一个独特的 AUHAL 单元,但我不是在 AUHAL 单元内进行格式转换,而是在渲染回调中进行,使用扩展音频文件,它采用源格式和目标格式。整个挑战是找到正确的格式描述,这基本上只是测试 mFormatIDmFormatFlags 等的不同值......

关于c++ - AUHAL 单元的 AudioBufferList,其输出流格式被压缩。,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49038140/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com