【问题标题】:kAudioUnitProperty_ShouldAllocateBuffer has no effectkAudioUnitProperty_ShouldAllocateBuffer 没有效果
【发布时间】:2012-02-20 20:47:27
【问题描述】:

我正在努力从麦克风中获取样本进行处理。我为输入和输出设置了一个音频单元,并且都有渲染回调。我的问题是关于麦克风回调的回调。

我希望 core-audio 为我分配麦克风回调中的缓冲区。

 UInt32 shouldAllocateBuffer = 1;
AudioUnitSetProperty(audioUnit, kAudioUnitProperty_ShouldAllocateBuffer, kAudioUnitScope_Global, 1, &shouldAllocateBuffer, sizeof(shouldAllocateBuffer));

但是,这样做总是会在回调中导致 NULL ioData 指针。我被困在分配自己的缓冲区了吗?

输入

static OSStatus recordingCallback(void *inRefCon, 
                          AudioUnitRenderActionFlags *ioActionFlags, 
                          const AudioTimeStamp *inTimeStamp, 
                          UInt32 inBusNumber, 
                          UInt32 inNumberFrames, 
                          AudioBufferList *ioData) {

OSStatus status;
status = AudioUnitRender(audioUnit, 
                         ioActionFlags, 
                         inTimeStamp, 
                         inBusNumber, 
                         inNumberFrames, 
                        ioData);  // ioData is null here
}

播放

static OSStatus playbackCallback(void *inRefCon, 
                                  AudioUnitRenderActionFlags *ioActionFlags, 
                                  const AudioTimeStamp *inTimeStamp, 
                                  UInt32 inBusNumber, 
                                  UInt32 inNumberFrames, 
                                  AudioBufferList *ioData) {    
// ioData is not NULL here but I get silence in the headphones.
    return noErr;
}

【问题讨论】:

    标签: core-audio


    【解决方案1】:

    AudioUnitRender 仍然希望 AudioBufferList 参数 (ioData) 为非 NULL。

    如果 ioData 是指向 AudioBufferList 的指针,那么在大多数情况下应该是 ioData->mBuffers[0].mData 的缓冲区(请参阅docs)。如果您不分配缓冲区,则缓冲区列表可能应该是一个局部变量,因为它仅对回调有效。

    所以,基本上使用局部变量而不是 ioData。

    请注意,您仍然需要设置 AudioBufferList 以匹配您描述的拓扑。

    这是一个例子:

    AudioBufferList bufferList;
    bufferList.mNumberBuffers = 1;
    bufferList.mBuffers[0].mData = NULL;
    OSStatus status;
    status = AudioUnitRender(audioUnit, 
                             ioActionFlags, 
                             inTimeStamp, 
                             inBusNumber, 
                             inNumberFrames, 
                             &bufferList); // bufferList.mBuffers[0].mData is null
    // Use the input data in now valid bufferList.mBuffers[0].mData
    // note the buffer is only valid for the callback.
    

    请注意,如果您需要多个缓冲区(您可能不需要,即使是立体声),您可以使用 malloc 来扩展 mBuffers 数组的大小。

    【讨论】:

    • 所以无论什么时候你在录​​音回调中需要分配你自己的缓冲区?此外,如果我想在播放回调中使用此捕获的音频,我可能应该将本地缓冲区数据复制到其他一些自我管理的缓冲区以复制到播放回调 ioData?
    • mData 为 NULL,因此 AudioUnit 正在为您分配和提供它。这与提供自己的缓冲区不同 - 如果您提供自己的缓冲区,则需要先对其进行 malloc 并稍后释放它们。如果你想捕获它以供以后使用,你可以将它复制到另一个缓冲区,但这不是那么有效 - 在这种情况下你可能应该只提供自己的缓冲区。
    • Catch 22。如果您不提供自己的缓冲区并且想要数据,则无论如何您都需要将数据复制到自己的缓冲区。
    • @hotpaw2 不需要复制的一种情况是在同一个回调中处理输入和输出(OP 不这样做)。然后您可以处理输入并直接写入输出。
    • 使用 Apple 的缓冲区是否更高效?即,如果我通过自己的,也许在复制中还有一个额外的步骤。但是如果我用苹果的,可能内部动态分配多了一步,会差很多。
    猜你喜欢
    • 2012-10-30
    • 2018-05-21
    • 2018-07-28
    • 2018-05-15
    • 1970-01-01
    • 2011-10-01
    • 2015-05-31
    • 2020-10-19
    • 2014-04-19
    相关资源
    最近更新 更多