in Source/AUBase.cpp [1346:1418]
OSStatus AUBase::DoProcess(AudioUnitRenderActionFlags& ioActionFlags,
const AudioTimeStamp& inTimeStamp, UInt32 inFramesToProcess, AudioBufferList& ioData)
{
const auto errorExit = [this](OSStatus error) {
AUSDK_LogError(" from %s, process err: %d", GetLoggingString(), static_cast<int>(error));
SetRenderError(error);
return error;
};
OSStatus theError = noErr;
[[maybe_unused]] const DenormalDisabler denormalDisabler;
try {
if (CheckRenderArgs(ioActionFlags)) {
AUSDK_Require(IsInitialized(), errorExit(kAudioUnitErr_Uninitialized));
AUSDK_Require(inFramesToProcess <= mMaxFramesPerSlice,
errorExit(kAudioUnitErr_TooManyFramesToProcess));
AUSDK_Require(!UsesFixedBlockSize() || inFramesToProcess == GetMaxFramesPerSlice(),
errorExit(kAudio_ParamError));
const auto& input = Input(0); // will throw if non-existant
if (ASBD::NumberChannelStreams(input.GetStreamFormat()) != ioData.mNumberBuffers) {
AUSDK_LogError(
"ioData.mNumberBuffers=%u, "
"ASBD::NumberChannelStreams(input->GetStreamFormat())=%u; kAudio_ParamError",
static_cast<unsigned>(ioData.mNumberBuffers),
static_cast<unsigned>(ASBD::NumberChannelStreams(input.GetStreamFormat())));
return errorExit(kAudio_ParamError);
}
const unsigned expectedBufferByteSize =
inFramesToProcess * input.GetStreamFormat().mBytesPerFrame;
for (unsigned ibuf = 0; ibuf < ioData.mNumberBuffers; ++ibuf) {
AudioBuffer& buf = ioData.mBuffers[ibuf]; // NOLINT
if (buf.mData != nullptr) {
// only care about the size if the buffer is non-null
if (buf.mDataByteSize < expectedBufferByteSize) {
// if the buffer is too small, we cannot render safely. kAudio_ParamError.
AUSDK_LogError("%u frames, %u bytes/frame, expected %u-byte buffer; "
"ioData.mBuffers[%u].mDataByteSize=%u; kAudio_ParamError",
static_cast<unsigned>(inFramesToProcess),
static_cast<unsigned>(input.GetStreamFormat().mBytesPerFrame),
expectedBufferByteSize, ibuf, static_cast<unsigned>(buf.mDataByteSize));
return errorExit(kAudio_ParamError);
}
// Some clients incorrectly pass bigger buffers than expectedBufferByteSize.
// We will generally set the buffer size at the end of rendering, before we
// return. However we should ensure that no one, DURING rendering, READS a
// potentially incorrect size. This can lead to doing too much work, or
// reading past the end of an input buffer into unmapped memory.
buf.mDataByteSize = expectedBufferByteSize;
}
}
}
if (WantsRenderThreadID()) {
mRenderThreadID = std::this_thread::get_id();
}
if (NeedsToRender(inTimeStamp)) {
theError = ProcessBufferLists(ioActionFlags, ioData, ioData, inFramesToProcess);
} else {
theError = noErr;
}
} catch (const OSStatus& err) {
return errorExit(err);
} catch (...) {
return errorExit(-1);
}
return theError;
}