From 99d2002cf4abc0c004c7d4a31bb895c70835a8be Mon Sep 17 00:00:00 2001 From: Aurelius Prochazka Date: Wed, 15 Apr 2026 13:49:23 -0700 Subject: [PATCH] Pass maxFramesToRender to DSP at allocation time MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #16. AudioKitAU already knows maximumFramesToRender from the host but never forwarded it into C++, so DSP kernels had no sanctioned way to pre-size scratch buffers at init time and had to infer the worst case from the first render's output buffer. Store the value as a member on DSPBase, set by allocateRenderResourcesDSP before init() is called. Subclasses opt in by reading maximumFramesToRender in their init() override — the virtual init(int, double) signature is unchanged, so existing overrides (including those in downstream projects) keep compiling. Co-Authored-By: Claude Opus 4.6 --- Sources/AudioKitEX/AudioKitAU.swift | 2 +- Sources/CAudioKitEX/Internals/DSPBase.mm | 3 ++- Sources/CAudioKitEX/include/DSPBase.h | 9 ++++++++- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/Sources/AudioKitEX/AudioKitAU.swift b/Sources/AudioKitEX/AudioKitAU.swift index eec6eca..166417b 100644 --- a/Sources/AudioKitEX/AudioKitAU.swift +++ b/Sources/AudioKitEX/AudioKitAU.swift @@ -39,7 +39,7 @@ open class AudioKitAU: AUAudioUnit { } if let outputFormat = outputBusArray.first?.format { - allocateRenderResourcesDSP(dsp, outputFormat.channelCount, outputFormat.sampleRate) + allocateRenderResourcesDSP(dsp, outputFormat.channelCount, outputFormat.sampleRate, maximumFramesToRender) } } diff --git a/Sources/CAudioKitEX/Internals/DSPBase.mm b/Sources/CAudioKitEX/Internals/DSPBase.mm index cd837e6..42d717b 100644 --- a/Sources/CAudioKitEX/Internals/DSPBase.mm +++ b/Sources/CAudioKitEX/Internals/DSPBase.mm @@ -25,8 +25,9 @@ void setBufferDSP(DSPRef pDSP, AudioBufferList* buffer, size_t busIndex) pDSP->setBuffer(buffer, busIndex); } -void allocateRenderResourcesDSP(DSPRef pDSP, uint32_t channelCount, double sampleRate) +void allocateRenderResourcesDSP(DSPRef pDSP, uint32_t channelCount, double sampleRate, AUAudioFrameCount maxFramesToRender) { + pDSP->setMaximumFramesToRender(maxFramesToRender); pDSP->init(channelCount, sampleRate); } diff --git a/Sources/CAudioKitEX/include/DSPBase.h b/Sources/CAudioKitEX/include/DSPBase.h index ede76f5..c65693a 100644 --- a/Sources/CAudioKitEX/include/DSPBase.h +++ b/Sources/CAudioKitEX/include/DSPBase.h @@ -18,7 +18,7 @@ size_t inputBusCountDSP(DSPRef pDSP); bool canProcessInPlaceDSP(DSPRef pDSP); void setBufferDSP(DSPRef pDSP, AudioBufferList* buffer, size_t busIndex); -void allocateRenderResourcesDSP(DSPRef pDSP, uint32_t channelCount, double sampleRate); +void allocateRenderResourcesDSP(DSPRef pDSP, uint32_t channelCount, double sampleRate, AUAudioFrameCount maxFramesToRender); void deallocateRenderResourcesDSP(DSPRef pDSP); void resetDSP(DSPRef pDSP); @@ -89,6 +89,7 @@ struct DSPBase { int channelCount; double sampleRate; + AUAudioFrameCount maximumFramesToRender = 0; bool isInitialized = false; @@ -134,6 +135,12 @@ struct DSPBase { std::atomic isStarted{true}; void setBuffer(AudioBufferList* buffer, size_t busIndex); + + /// Set by AudioKitAU from AUAudioUnit.maximumFramesToRender before init(). + /// Subclasses may read `maximumFramesToRender` in their init() override to + /// pre-size scratch buffers to the worst-case render size. + void setMaximumFramesToRender(AUAudioFrameCount frames) { maximumFramesToRender = frames; } + AUAudioFrameCount getMaximumFramesToRender() const { return maximumFramesToRender; } size_t getInputBusCount() const { return inputBufferLists.size(); } virtual AUAudioFrameCount framesToPull(AUAudioFrameCount requestedOutputFrameCount) { return requestedOutputFrameCount; };