【问题标题】:AVCaptureOutput to Audio Unit callback via TPCircularBufferAVCaptureOutput 通过 TPCircularBuffer 到 Audio Unit 回调
【发布时间】:2014-06-01 10:09:33
【问题描述】:

我正在构建一个 AUGraph,并尝试通过 AVCaptureAudioDataOutput 委托方法从输入设备获取音频。

使用 AVCaptureSession 是 here 解释的问题的结果。 正如Learning Core Audio 一书中所述,我成功地通过 CARingbuffer 使用此方法构建了音频播放。 但是,从 CARingbuffer 获取数据意味着提供有效的采样时间,当我停止 AVCaptureSession 时,来自 AVCaptureOutput 的采样时间和单元输入回调不再同步。 所以,我现在正在尝试使用 Michael Tyson 的 TPCircularBuffer,根据我所读到的内容,这似乎很棒。但是,即使我找到了一些例子,我也无法从中获得一些音频(或只有裂缝)。

我的图表如下所示:

AVCaptureSession -> callback -> AUConverter -> ... -> HALOutput

这是我的 AVCaptureOutput 方法的代码

- (void) captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
{

CMFormatDescriptionRef formatDescription = CMSampleBufferGetFormatDescription(sampleBuffer);
const AudioStreamBasicDescription *sampleBufferASBD = CMAudioFormatDescriptionGetStreamBasicDescription(formatDescription);

if (kAudioFormatLinearPCM != sampleBufferASBD->mFormatID) {

    NSLog(@"Bad format or bogus ASBD!");
    return;

}

if ((sampleBufferASBD->mChannelsPerFrame != _audioStreamDescription.mChannelsPerFrame) || (sampleBufferASBD->mSampleRate != _audioStreamDescription.mSampleRate)) {

    _audioStreamDescription = *sampleBufferASBD;
    NSLog(@"sample input format changed");

}




CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer(sampleBuffer,
                                                        NULL,
                                                        _currentInputAudioBufferList,
                                                        CAAudioBufferList::CalculateByteSize(_audioStreamDescription.mChannelsPerFrame),
                                                        kCFAllocatorSystemDefault,
                                                        kCFAllocatorSystemDefault,
                                                        kCMSampleBufferFlag_AudioBufferList_Assure16ByteAlignment,
                                                        &_blockBufferOut);


TPCircularBufferProduceBytes(&_circularBuffer, _currentInputAudioBufferList->mBuffers[0].mData, _currentInputAudioBufferList->mBuffers[0].mDataByteSize);

还有渲染回调:

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

ozAVHardwareInput *hardWareInput = (ozAVHardwareInput *)inRefCon;
TPCircularBuffer circularBuffer = [hardWareInput circularBuffer];

Float32 *targetBuffer = (Float32 *)ioData->mBuffers[0].mData;

int32_t availableBytes;
TPCircularBufferTail(&circularBuffer, &availableBytes);
UInt32 dataSize = ioData->mBuffers[0].mDataByteSize;

if (availableBytes > ozAudioDataSizeForSeconds(3.)) {

    // There is too much audio data to play -> clear buffer & mute output
    TPCircularBufferClear(&circularBuffer);

    for(UInt32 i = 0; i < ioData->mNumberBuffers; i++)
        memset(ioData->mBuffers[i].mData, 0, ioData->mBuffers[i].mDataByteSize);

} else if (availableBytes > ozAudioDataSizeForSeconds(0.5)) {

    // SHOULD PLAY
    Float32 *cbuffer = (Float32 *)TPCircularBufferTail(&circularBuffer, &availableBytes);
    int32_t min = MIN(dataSize, availableBytes);

    memcpy(targetBuffer, cbuffer, min);
    TPCircularBufferConsume(&circularBuffer, min);
    ioData->mBuffers[0].mDataByteSize = min;

} else {

    // No data to play -> mute output
    for(UInt32 i = 0; i < ioData->mNumberBuffers; i++)
        memset(ioData->mBuffers[i].mData, 0, ioData->mBuffers[i].mDataByteSize);
}

return noErr;

}

TPCIrcularBuffer 由 AudioBufferList 提供,但没有输出,或者有时只是破裂。

我做错了什么?

【问题讨论】:

标签: objective-c c macos core-audio circular-buffer


【解决方案1】:

音频单元渲染回调应始终返回 inNumberFrames 个样本。检查您的回调返回了多少数据。

【讨论】:

  • 我终于使用了@sbooth 环形缓冲区,它运行良好,但我会尝试将我作为“数字帧”传递的值更改为 TPCircularBuffer 进行测试。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多