【发布时间】: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 提供,但没有输出,或者有时只是破裂。
我做错了什么?
【问题讨论】:
-
如果你没有和
TPCircularBuffer结婚,另一种选择是我的RingBuffer班级:github.com/sbooth/SFBAudioEngine/blob/master/RingBuffer.h -
谢谢。我试试看!
-
非常感谢@sbooth,它就像一个魅力,而且非常易于使用!
标签: objective-c c macos core-audio circular-buffer