commit 19cb24186bb25e9e17586e2055eaee0e6d71b3f9
parent 808d4fea316aa5fda1909a49a2341cad265b3b66
Author: falkTX <falktx@falktx.com>
Date: Mon, 26 Feb 2024 03:30:14 +0100
Deal with more AU audio rendering details
Signed-off-by: falkTX <falktx@falktx.com>
Diffstat:
1 file changed, 248 insertions(+), 68 deletions(-)
diff --git a/distrho/src/DistrhoPluginAU.cpp b/distrho/src/DistrhoPluginAU.cpp
@@ -200,14 +200,33 @@ struct PropertyListener {
void* userData;
};
+struct RenderListener {
+ AURenderCallback proc;
+ void* userData;
+};
+
typedef std::vector<PropertyListener> PropertyListeners;
+typedef std::vector<RenderListener> RenderListeners;
// --------------------------------------------------------------------------------------------------------------------
+#if DISTRHO_PLUGIN_NUM_INPUTS + DISTRHO_PLUGIN_NUM_OUTPUTS == 0
+# define DPF_AU_NUM_BUFFERS 1
+#elif DISTRHO_PLUGIN_NUM_INPUTS > DISTRHO_PLUGIN_NUM_OUTPUTS
+# define DPF_AU_NUM_BUFFERS DISTRHO_PLUGIN_NUM_INPUTS
+#else
+# define DPF_AU_NUM_BUFFERS DISTRHO_PLUGIN_NUM_OUTPUTS
+#endif
+
+typedef struct {
+ UInt32 mNumberBuffers;
+ AudioBuffer mBuffers[DPF_AU_NUM_BUFFERS];
+} d_AudioBufferList;
+
typedef struct {
UInt32 numPackets;
MIDIPacket packets[kMaxMidiEvents];
-} MIDIPacketList;
+} d_MIDIPacketList;
// --------------------------------------------------------------------------------------------------------------------
@@ -233,6 +252,7 @@ public:
fComponent(component),
fLastRenderError(noErr),
fPropertyListeners(),
+ fRenderListeners(),
fSampleRateForInput(d_nextSampleRate),
#if DISTRHO_PLUGIN_NUM_OUTPUTS != 0
fSampleRateForOutput(d_nextSampleRate),
@@ -240,6 +260,7 @@ public:
#if DISTRHO_PLUGIN_NUM_INPUTS + DISTRHO_PLUGIN_NUM_OUTPUTS == 0
fHasWorkingAudio(false),
#endif
+ fUsingRenderListeners(false),
fParameterCount(fPlugin.getParameterCount()),
fLastParameterValues(nullptr),
fBypassParameterIndex(UINT32_MAX)
@@ -256,6 +277,8 @@ public:
, fStateCount(fPlugin.getStateCount())
#endif
{
+ const uint32_t bufferSize = fPlugin.getBufferSize();
+
if (fParameterCount != 0)
{
fLastParameterValues = new float[fParameterCount];
@@ -274,6 +297,15 @@ public:
fInputRenderCallback.inputProc = nullptr;
fInputRenderCallback.inputProcRefCon = nullptr;
+ fAudioBufferList.mNumberBuffers = DPF_AU_NUM_BUFFERS;
+
+ for (uint16_t i=0; i<DPF_AU_NUM_BUFFERS; ++i)
+ {
+ fAudioBufferList.mBuffers[i].mNumberChannels = 1;
+ fAudioBufferList.mBuffers[i].mData = new float[bufferSize];
+ fAudioBufferList.mBuffers[i].mDataByteSize = sizeof(float) * bufferSize;
+ }
+
#if DISTRHO_PLUGIN_WANT_MIDI_INPUT
std::memset(&fMidiEvents, 0, sizeof(fMidiEvents));
#endif
@@ -331,6 +363,9 @@ public:
delete[] fLastParameterValues;
CFRelease(fUserPresetData.presetName);
+ for (uint16_t i=0; i<DPF_AU_NUM_BUFFERS; ++i)
+ delete[] static_cast<float*>(fAudioBufferList.mBuffers[i].mData);
+
#if DISTRHO_PLUGIN_WANT_PROGRAMS
for (uint32_t i=0; i<fProgramCount; ++i)
CFRelease(fFactoryPresetsData[i].presetName);
@@ -1037,7 +1072,7 @@ public:
fPlugin.setSampleRate(sampleRate, true);
}
- notifyListeners(inProp, inScope, inElement);
+ notifyPropertyListeners(inProp, inScope, inElement);
}
return noErr;
}
@@ -1055,7 +1090,7 @@ public:
fPlugin.setSampleRate(sampleRate, true);
}
- notifyListeners(inProp, inScope, inElement);
+ notifyPropertyListeners(inProp, inScope, inElement);
}
return noErr;
}
@@ -1111,8 +1146,8 @@ public:
fPlugin.setSampleRate(desc->mSampleRate, true);
}
- notifyListeners(inProp, inScope, inElement);
- notifyListeners(kAudioUnitProperty_SampleRate, inScope, inElement);
+ notifyPropertyListeners(inProp, inScope, inElement);
+ notifyPropertyListeners(kAudioUnitProperty_SampleRate, inScope, inElement);
}
#if DISTRHO_PLUGIN_NUM_INPUTS + DISTRHO_PLUGIN_NUM_OUTPUTS == 0
fHasWorkingAudio = true;
@@ -1132,8 +1167,8 @@ public:
fPlugin.setSampleRate(desc->mSampleRate, true);
}
- notifyListeners(inProp, inScope, inElement);
- notifyListeners(kAudioUnitProperty_SampleRate, inScope, inElement);
+ notifyPropertyListeners(inProp, inScope, inElement);
+ notifyPropertyListeners(kAudioUnitProperty_SampleRate, inScope, inElement);
}
return noErr;
}
@@ -1145,10 +1180,23 @@ public:
DISTRHO_SAFE_ASSERT_UINT_RETURN(inScope == kAudioUnitScope_Global, inScope, kAudioUnitErr_InvalidScope);
DISTRHO_SAFE_ASSERT_UINT_RETURN(inElement == 0, inElement, kAudioUnitErr_InvalidElement);
DISTRHO_SAFE_ASSERT_UINT_RETURN(inDataSize == sizeof(UInt32), inDataSize, kAudioUnitErr_InvalidPropertyValue);
+ {
+ const UInt32 bufferSize = *static_cast<const UInt32*>(inData);
- if (fPlugin.setBufferSize(*static_cast<const UInt32*>(inData), true))
- notifyListeners(inProp, inScope, inElement);
+ if (fPlugin.setBufferSize(bufferSize, true))
+ {
+ notifyPropertyListeners(inProp, inScope, inElement);
+ #if DISTRHO_PLUGIN_NUM_INPUTS + DISTRHO_PLUGIN_NUM_OUTPUTS != 0
+ for (uint16_t i=0; i<DPF_AU_NUM_BUFFERS; ++i)
+ {
+ delete[] static_cast<float*>(fAudioBufferList.mBuffers[i].mData);
+ fAudioBufferList.mBuffers[i].mData = new float[bufferSize];
+ fAudioBufferList.mBuffers[i].mDataByteSize = sizeof(float) * bufferSize;
+ }
+ #endif
+ }
+ }
return noErr;
case kAudioUnitProperty_BypassEffect:
@@ -1164,7 +1212,7 @@ public:
const float value = bypass ? 1.f : 0.f;
fLastParameterValues[fBypassParameterIndex] = value;
fPlugin.setParameterValue(fBypassParameterIndex, value);
- notifyListeners(inProp, inScope, inElement);
+ notifyPropertyListeners(inProp, inScope, inElement);
}
}
return noErr;
@@ -1190,7 +1238,7 @@ public:
std::memset(&fHostCallbackInfo + usableDataSize, 0, sizeof(HostCallbackInfo) - usableDataSize);
if (changed)
- notifyListeners(inProp, inScope, inElement);
+ notifyPropertyListeners(inProp, inScope, inElement);
}
return noErr;
#else
@@ -1212,7 +1260,7 @@ public:
fCurrentProgram = presetNumber;
fLastFactoryProgram = presetNumber;
fPlugin.loadProgram(fLastFactoryProgram);
- notifyListeners('DPFo', kAudioUnitScope_Global, 0);
+ notifyPropertyListeners('DPFo', kAudioUnitScope_Global, 0);
}
}
else
@@ -1251,16 +1299,16 @@ public:
return noErr;
#if DISTRHO_PLUGIN_WANT_PROGRAMS
- notifyListeners('DPFo', kAudioUnitScope_Global, 0);
+ notifyPropertyListeners('DPFo', kAudioUnitScope_Global, 0);
#endif
#if DISTRHO_PLUGIN_WANT_STATE
for (uint32_t i=0; i<fStateCount; ++i)
- notifyListeners('DPFs', kAudioUnitScope_Global, i);
+ notifyPropertyListeners('DPFs', kAudioUnitScope_Global, i);
#endif
for (uint32_t i=0; i<fParameterCount; ++i)
- notifyListeners('DPFp', kAudioUnitScope_Global, i);
+ notifyPropertyListeners('DPFp', kAudioUnitScope_Global, i);
}
return noErr;
@@ -1310,7 +1358,7 @@ public:
AUEventListenerNotify(NULL, NULL, &event);
if (fBypassParameterIndex == inElement)
- notifyListeners(kAudioUnitProperty_BypassEffect, kAudioUnitScope_Global, 0);
+ notifyPropertyListeners(kAudioUnitProperty_BypassEffect, kAudioUnitScope_Global, 0);
}
return noErr;
@@ -1382,9 +1430,6 @@ public:
prop, proc, userData
};
- if (fPropertyListeners.empty())
- fPropertyListeners.reserve(32);
-
fPropertyListeners.push_back(pl);
return noErr;
}
@@ -1425,15 +1470,29 @@ public:
OSStatus auAddRenderNotify(const AURenderCallback proc, void* const userData)
{
- d_stdout("WIP AddRenderNotify(%p, %p)", proc, userData);
- // TODO
+ fUsingRenderListeners = true;
+
+ const RenderListener rl = {
+ proc, userData
+ };
+
+ fRenderListeners.push_back(rl);
return noErr;
}
OSStatus auRemoveRenderNotify(const AURenderCallback proc, void* const userData)
{
- d_stdout("WIP RemoveRenderNotify(%p, %p)", proc, userData);
- // TODO
+ for (RenderListeners::iterator it = fRenderListeners.begin(); it != fRenderListeners.end(); ++it)
+ {
+ const RenderListener& rl(*it);
+
+ if (rl.proc == proc && rl.userData == userData)
+ {
+ fRenderListeners.erase(it);
+ return auRemoveRenderNotify(proc, userData);
+ }
+ }
+
return noErr;
}
@@ -1468,10 +1527,10 @@ public:
fPlugin.setParameterValue(param, value);
// TODO flag param only, notify listeners later on bg thread (sem_post etc)
- notifyListeners('DPFp', kAudioUnitScope_Global, param);
+ notifyPropertyListeners('DPFp', kAudioUnitScope_Global, param);
if (fBypassParameterIndex == elem)
- notifyListeners(kAudioUnitProperty_BypassEffect, kAudioUnitScope_Global, 0);
+ notifyPropertyListeners(kAudioUnitProperty_BypassEffect, kAudioUnitScope_Global, 0);
}
return noErr;
@@ -1523,61 +1582,158 @@ public:
return noErr;
}
- OSStatus auRender(AudioUnitRenderActionFlags* const ioActionFlags,
+ OSStatus auRender(const AudioUnitRenderActionFlags actionFlags,
const AudioTimeStamp* const inTimeStamp,
const UInt32 inBusNumber,
const UInt32 inFramesToProcess,
- AudioBufferList& ioData)
+ AudioBufferList* const ioData)
{
- DISTRHO_SAFE_ASSERT_UINT_RETURN(inBusNumber == 0, inBusNumber, kAudioUnitErr_InvalidElement);
- DISTRHO_SAFE_ASSERT_UINT_RETURN(ioData.mNumberBuffers == std::max<uint>(DISTRHO_PLUGIN_NUM_INPUTS, DISTRHO_PLUGIN_NUM_OUTPUTS), ioData.mNumberBuffers, kAudio_ParamError);
-
- if (inFramesToProcess > fPlugin.getBufferSize())
- {
- setLastRenderError(kAudioUnitErr_TooManyFramesToProcess);
- return kAudioUnitErr_TooManyFramesToProcess;
- }
-
- for (uint i=0; i<ioData.mNumberBuffers; ++i)
+ if ((actionFlags & kAudioUnitRenderAction_DoNotCheckRenderArgs) == 0x0)
{
- AudioBuffer& buffer(ioData.mBuffers[i]);
+ DISTRHO_SAFE_ASSERT_UINT_RETURN(inBusNumber == 0, inBusNumber, kAudioUnitErr_InvalidElement);
+ DISTRHO_SAFE_ASSERT_UINT_RETURN(ioData->mNumberBuffers == DPF_AU_NUM_BUFFERS,
+ ioData->mNumberBuffers, kAudio_ParamError);
- // TODO there must be something more to this...
- if (buffer.mData == nullptr)
+ if (inFramesToProcess > fPlugin.getBufferSize())
{
- return noErr;
+ setLastRenderError(kAudioUnitErr_TooManyFramesToProcess);
+ return kAudioUnitErr_TooManyFramesToProcess;
}
- DISTRHO_SAFE_ASSERT_UINT_RETURN(buffer.mDataByteSize == inFramesToProcess * sizeof(float), buffer.mDataByteSize, kAudio_ParamError);
+ for (uint16_t i=0; i<DPF_AU_NUM_BUFFERS; ++i)
+ {
+ if (ioData->mBuffers[i].mDataByteSize != sizeof(float) * inFramesToProcess)
+ {
+ setLastRenderError(kAudio_ParamError);
+ return kAudio_ParamError;
+ }
+ }
}
#if DISTRHO_PLUGIN_NUM_INPUTS != 0
const float* inputs[DISTRHO_PLUGIN_NUM_INPUTS];
-
- for (uint16_t i=0; i<DISTRHO_PLUGIN_NUM_INPUTS; ++i)
- {
- inputs[i] = static_cast<const float*>(ioData.mBuffers[i].mData);
- }
#else
constexpr const float** inputs = nullptr;
#endif
#if DISTRHO_PLUGIN_NUM_OUTPUTS != 0
float* outputs[DISTRHO_PLUGIN_NUM_OUTPUTS];
-
- for (uint16_t i=0; i<DISTRHO_PLUGIN_NUM_OUTPUTS; ++i)
- {
- outputs[i] = static_cast<float*>(ioData.mBuffers[i].mData);
- }
#else
constexpr float** outputs = nullptr;
#endif
+ if (fInputRenderCallback.inputProc != nullptr)
+ {
+ bool adjustDataByteSize, usingHostBuffer = true;
+ UInt32 prevDataByteSize;
+
+ for (uint16_t i=0; i<DPF_AU_NUM_BUFFERS; ++i)
+ {
+ if (ioData->mBuffers[i].mData == nullptr)
+ {
+ usingHostBuffer = false;
+ ioData->mBuffers[i].mData = fAudioBufferList.mBuffers[i].mData;
+ }
+ }
+
+ if (! usingHostBuffer)
+ {
+ prevDataByteSize = fAudioBufferList.mBuffers[0].mDataByteSize;
+ adjustDataByteSize = prevDataByteSize != sizeof(float) * inFramesToProcess;
+
+ if (adjustDataByteSize)
+ {
+ for (uint16_t i=0; i<DPF_AU_NUM_BUFFERS; ++i)
+ fAudioBufferList.mBuffers[i].mDataByteSize = sizeof(float) * inFramesToProcess;
+ }
+ }
+ else
+ {
+ adjustDataByteSize = false;
+ }
+
+ AudioUnitRenderActionFlags rActionFlags = 0;
+ AudioBufferList* const rData = usingHostBuffer ? ioData : reinterpret_cast<AudioBufferList*>(&fAudioBufferList);
+ const OSStatus err = fInputRenderCallback.inputProc(fInputRenderCallback.inputProcRefCon,
+ &rActionFlags,
+ inTimeStamp,
+ inBusNumber,
+ inFramesToProcess,
+ rData);
+
+ if (err != noErr)
+ {
+ if (adjustDataByteSize)
+ {
+ for (uint16_t i=0; i<DPF_AU_NUM_BUFFERS; ++i)
+ fAudioBufferList.mBuffers[i].mDataByteSize = prevDataByteSize;
+ }
+
+ setLastRenderError(err);
+ return err;
+ }
+
+ if (usingHostBuffer)
+ {
+ #if DISTRHO_PLUGIN_NUM_INPUTS != 0
+ for (uint16_t i=0; i<DISTRHO_PLUGIN_NUM_INPUTS; ++i)
+ inputs[i] = static_cast<const float*>(ioData->mBuffers[i].mData);
+ #endif
+
+ #if DISTRHO_PLUGIN_NUM_OUTPUTS != 0
+ for (uint16_t i=0; i<DISTRHO_PLUGIN_NUM_OUTPUTS; ++i)
+ outputs[i] = static_cast<float*>(ioData->mBuffers[i].mData);
+ #endif
+
+ }
+ else
+ {
+ #if DISTRHO_PLUGIN_NUM_INPUTS != 0
+ for (uint16_t i=0; i<DISTRHO_PLUGIN_NUM_INPUTS; ++i)
+ inputs[i] = static_cast<const float*>(fAudioBufferList.mBuffers[i].mData);
+ #endif
+
+ #if DISTRHO_PLUGIN_NUM_OUTPUTS != 0
+ for (uint16_t i=0; i<DISTRHO_PLUGIN_NUM_OUTPUTS; ++i)
+ outputs[i] = static_cast<float*>(ioData->mBuffers[i].mData);
+ #endif
+ }
+ }
+ else
+ {
+ #if DISTRHO_PLUGIN_NUM_INPUTS != 0
+ for (uint16_t i=0; i<DISTRHO_PLUGIN_NUM_INPUTS; ++i)
+ {
+ if (ioData->mBuffers[i].mData == nullptr)
+ ioData->mBuffers[i].mData = fAudioBufferList.mBuffers[i].mData;
+
+ inputs[i] = static_cast<const float*>(ioData->mBuffers[i].mData);
+ }
+ #endif
+
+ #if DISTRHO_PLUGIN_NUM_OUTPUTS != 0
+ for (uint16_t i=0; i<DISTRHO_PLUGIN_NUM_OUTPUTS; ++i)
+ {
+ if (ioData->mBuffers[i].mData == nullptr)
+ ioData->mBuffers[i].mData = fAudioBufferList.mBuffers[i].mData;
+
+ outputs[i] = static_cast<float*>(ioData->mBuffers[i].mData);
+ }
+ #endif
+ }
+
+ if (fUsingRenderListeners)
+ {
+ AudioUnitRenderActionFlags ioActionFlags = actionFlags | kAudioUnitRenderAction_PreRender;
+ notifyRenderListeners(&ioActionFlags, inTimeStamp, inBusNumber, inFramesToProcess, ioData);
+ }
+
run(inputs, outputs, inFramesToProcess, inTimeStamp);
- if (ioActionFlags != nullptr)
+ if (fUsingRenderListeners)
{
- // TODO what now?
+ AudioUnitRenderActionFlags ioActionFlags = actionFlags | kAudioUnitRenderAction_PostRender;
+ notifyRenderListeners(&ioActionFlags, inTimeStamp, inBusNumber, inFramesToProcess, ioData);
}
return noErr;
@@ -1667,14 +1823,17 @@ private:
// AUv2 related fields
OSStatus fLastRenderError;
PropertyListeners fPropertyListeners;
+ RenderListeners fRenderListeners;
AURenderCallbackStruct fInputRenderCallback;
Float64 fSampleRateForInput;
#if DISTRHO_PLUGIN_NUM_OUTPUTS != 0
Float64 fSampleRateForOutput;
#endif
+ d_AudioBufferList fAudioBufferList;
#if DISTRHO_PLUGIN_NUM_INPUTS + DISTRHO_PLUGIN_NUM_OUTPUTS == 0
bool fHasWorkingAudio;
#endif
+ bool fUsingRenderListeners;
// Caching
const uint32_t fParameterCount;
@@ -1689,7 +1848,7 @@ private:
#if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT
AUMIDIOutputCallbackStruct fMidiOutput;
- MIDIPacketList fMidiOutputPackets;
+ d_MIDIPacketList fMidiOutputPackets;
#endif
#if DISTRHO_PLUGIN_WANT_PROGRAMS
@@ -1712,7 +1871,7 @@ private:
// ----------------------------------------------------------------------------------------------------------------
- void notifyListeners(const AudioUnitPropertyID prop, const AudioUnitScope scope, const AudioUnitElement elem)
+ void notifyPropertyListeners(const AudioUnitPropertyID prop, const AudioUnitScope scope, const AudioUnitElement elem)
{
for (PropertyListeners::iterator it = fPropertyListeners.begin(); it != fPropertyListeners.end(); ++it)
{
@@ -1723,6 +1882,22 @@ private:
}
}
+ void notifyRenderListeners(AudioUnitRenderActionFlags* const ioActionFlags,
+ const AudioTimeStamp* const inTimeStamp,
+ const UInt32 inBusNumber,
+ const UInt32 inNumberFrames,
+ AudioBufferList* const ioData)
+ {
+ for (RenderListeners::iterator it = fRenderListeners.begin(); it != fRenderListeners.end(); ++it)
+ {
+ const RenderListener& rl(*it);
+
+ rl.proc(rl.userData, ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, ioData);
+ }
+ }
+
+ // ----------------------------------------------------------------------------------------------------------------
+
void run(const float** inputs, float** outputs, const uint32_t frames, const AudioTimeStamp* const inTimeStamp)
{
#if DISTRHO_PLUGIN_WANT_MIDI_INPUT
@@ -1862,7 +2037,7 @@ private:
// TODO flag param only, notify listeners later on bg thread (sem_post etc)
event.mArgument.mParameter.mParameterID = i;
AUEventListenerNotify(NULL, NULL, &event);
- notifyListeners('DPFp', kAudioUnitScope_Global, i);
+ notifyPropertyListeners('DPFp', kAudioUnitScope_Global, i);
}
}
}
@@ -1873,7 +2048,7 @@ private:
return;
fLastRenderError = err;
- notifyListeners(kAudioUnitProperty_LastRenderError, kAudioUnitScope_Global, 0);
+ notifyPropertyListeners(kAudioUnitProperty_LastRenderError, kAudioUnitScope_Global, 0);
}
// ----------------------------------------------------------------------------------------------------------------
@@ -2063,10 +2238,10 @@ private:
{
fLastFactoryProgram = program;
fPlugin.loadProgram(fLastFactoryProgram);
- notifyListeners('DPFo', kAudioUnitScope_Global, 0);
+ notifyPropertyListeners('DPFo', kAudioUnitScope_Global, 0);
}
- notifyListeners(kAudioUnitProperty_PresentPreset, kAudioUnitScope_Global, 0);
+ notifyPropertyListeners(kAudioUnitProperty_PresentPreset, kAudioUnitScope_Global, 0);
}
}
#endif
@@ -2124,7 +2299,7 @@ private:
if (fPlugin.getStateKey(j) == key)
{
if ((fPlugin.getStateHints(i) & kStateIsOnlyForDSP) == 0x0)
- notifyListeners('DPFs', kAudioUnitScope_Global, j);
+ notifyPropertyListeners('DPFs', kAudioUnitScope_Global, j);
break;
}
@@ -2178,10 +2353,10 @@ private:
fLastParameterValues[j] = value;
fPlugin.setParameterValue(j, value);
- notifyListeners('DPFp', kAudioUnitScope_Global, j);
+ notifyPropertyListeners('DPFp', kAudioUnitScope_Global, j);
if (fBypassParameterIndex == j)
- notifyListeners(kAudioUnitProperty_BypassEffect, kAudioUnitScope_Global, 0);
+ notifyPropertyListeners(kAudioUnitProperty_BypassEffect, kAudioUnitScope_Global, 0);
break;
}
@@ -2230,7 +2405,7 @@ private:
fLastParameterValues[index] = value;
AUEventListenerNotify(NULL, NULL, &event);
- notifyListeners('DPFp', kAudioUnitScope_Global, index);
+ notifyPropertyListeners('DPFp', kAudioUnitScope_Global, index);
return true;
}
@@ -2253,7 +2428,7 @@ private:
fStateMap[dkey] = newValue;
if ((fPlugin.getStateHints(i) & kStateIsOnlyForDSP) == 0x0)
- notifyListeners('DPFs', kAudioUnitScope_Global, i);
+ notifyPropertyListeners('DPFs', kAudioUnitScope_Global, i);
return true;
}
@@ -2571,10 +2746,15 @@ struct AudioComponentPlugInInstance {
const UInt32 inNumberFrames,
AudioBufferList* const ioData)
{
- DISTRHO_SAFE_ASSERT_RETURN(inTimeStamp != nullptr, kAudio_ParamError);
- DISTRHO_SAFE_ASSERT_RETURN(ioData != nullptr, kAudio_ParamError);
+ const AudioUnitRenderActionFlags actionFlags = ioActionFlags != nullptr ? *ioActionFlags : 0;
+
+ // if ((actionFlags & kAudioUnitRenderAction_DoNotCheckRenderArgs) == 0x0)
+ {
+ DISTRHO_SAFE_ASSERT_RETURN(inTimeStamp != nullptr, kAudio_ParamError);
+ DISTRHO_SAFE_ASSERT_RETURN(ioData != nullptr, kAudio_ParamError);
+ }
- return self->plugin->auRender(ioActionFlags, inTimeStamp, inOutputBusNumber, inNumberFrames, *ioData);
+ return self->plugin->auRender(actionFlags, inTimeStamp, inOutputBusNumber, inNumberFrames, ioData);
}
#if DISTRHO_PLUGIN_WANT_MIDI_INPUT