OSStatus AUBase::DoProcess()

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;
}