Use an intermediate buffer for writing to the ringbuffer
It doesn't seem as though AudioUnitRender likes being given two buffers to render/capture samples into segmented memory.master
parent
4115df49cf
commit
19d35a45d7
|
@ -548,6 +548,8 @@ struct CoreAudioCapture final : public BackendBase {
|
|||
|
||||
SampleConverterPtr mConverter;
|
||||
|
||||
al::vector<char> mCaptureData;
|
||||
|
||||
RingBufferPtr mRing{nullptr};
|
||||
|
||||
DEF_NEWDEL(CoreAudioCapture)
|
||||
|
@ -566,43 +568,24 @@ OSStatus CoreAudioCapture::RecordProc(AudioUnitRenderActionFlags *ioActionFlags,
|
|||
AudioBufferList*) noexcept
|
||||
{
|
||||
union {
|
||||
al::byte _[sizeof(AudioBufferList) + sizeof(AudioBuffer)*2];
|
||||
al::byte _[maxz(sizeof(AudioBufferList), offsetof(AudioBufferList, mBuffers[1]))];
|
||||
AudioBufferList list;
|
||||
} audiobuf{};
|
||||
|
||||
auto rec_vec = mRing->getWriteVector();
|
||||
inNumberFrames = static_cast<UInt32>(minz(inNumberFrames,
|
||||
rec_vec.first.len+rec_vec.second.len));
|
||||
audiobuf.list.mNumberBuffers = 1;
|
||||
audiobuf.list.mBuffers[0].mNumberChannels = mFormat.mChannelsPerFrame;
|
||||
audiobuf.list.mBuffers[0].mData = mCaptureData.data();
|
||||
audiobuf.list.mBuffers[0].mDataByteSize = static_cast<UInt32>(mCaptureData.size());
|
||||
|
||||
// Fill the ringbuffer's two segments with data from the input device
|
||||
if(rec_vec.first.len >= inNumberFrames)
|
||||
{
|
||||
audiobuf.list.mNumberBuffers = 1;
|
||||
audiobuf.list.mBuffers[0].mNumberChannels = mFormat.mChannelsPerFrame;
|
||||
audiobuf.list.mBuffers[0].mData = rec_vec.first.buf;
|
||||
audiobuf.list.mBuffers[0].mDataByteSize = inNumberFrames * mFormat.mBytesPerFrame;
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto remaining = static_cast<uint>(inNumberFrames - rec_vec.first.len);
|
||||
audiobuf.list.mNumberBuffers = 2;
|
||||
audiobuf.list.mBuffers[0].mNumberChannels = mFormat.mChannelsPerFrame;
|
||||
audiobuf.list.mBuffers[0].mData = rec_vec.first.buf;
|
||||
audiobuf.list.mBuffers[0].mDataByteSize = static_cast<UInt32>(rec_vec.first.len) *
|
||||
mFormat.mBytesPerFrame;
|
||||
audiobuf.list.mBuffers[1].mNumberChannels = mFormat.mChannelsPerFrame;
|
||||
audiobuf.list.mBuffers[1].mData = rec_vec.second.buf;
|
||||
audiobuf.list.mBuffers[1].mDataByteSize = remaining * mFormat.mBytesPerFrame;
|
||||
}
|
||||
OSStatus err{AudioUnitRender(mAudioUnit, ioActionFlags, inTimeStamp, inBusNumber,
|
||||
inNumberFrames, &audiobuf.list)};
|
||||
if(err != noErr)
|
||||
{
|
||||
ERR("AudioUnitRender error: %d\n", err);
|
||||
ERR("AudioUnitRender capture error: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
mRing->writeAdvance(inNumberFrames);
|
||||
mRing->write(mCaptureData.data(), inNumberFrames * mFrameSize);
|
||||
return noErr;
|
||||
}
|
||||
|
||||
|
@ -814,6 +797,8 @@ void CoreAudioCapture::open(const char *name)
|
|||
throw al::backend_exception{al::backend_error::DeviceError,
|
||||
"Could not get input frame count: %u", err};
|
||||
|
||||
mCaptureData.resize(outputFrameCount * mFrameSize);
|
||||
|
||||
outputFrameCount = static_cast<UInt32>(maxu64(outputFrameCount, FrameCount64));
|
||||
mRing = RingBuffer::Create(outputFrameCount, mFrameSize, false);
|
||||
|
||||
|
|
Loading…
Reference in New Issue