Skip to content

A PluginEffect clip effect prepares its plugin at a sample rate of ZERO #417

Description

@KeatonStromberg

Found while building a JUCE + Tracktion Engine DAW. Measured on 494e91d (develop) and re-checked against develop 18e307f: the code referenced is unchanged. Happy to provide the test fixture.

Where: PluginEffect::createRenderJob (tracktion_ClipEffects.cpp:1430
on develop 18e307f; PitchShiftEffect::createRenderJob at 1205 has the
same shape) constructs its PluginNode with job->processState.sampleRate,
which is 0 at that moment - the job has not run createAndPrepareRenderContext
yet, and when the stage's INPUT is an earlier stage's not-yet-rendered file
the source info reads 0 too. PluginNode's constructor calls
initialisePlugin (sampleRateToUse, ...)plugin->baseClassInitialise ({0_tp, 0, 512}) unconditionally (tracktion_PluginNode.cpp:48, :304).

What goes wrong: the hosted plugin is initialised at 0 Hz and the render
runs it that way. PluginNode::prepareToPlay then asserts the rate mismatch
(tracktion_PluginNode.cpp:112) and continues. Anything rate-dependent in
the plugin - a delay line, a filter, an oversampler - is silently absent from
the render. Measured with te's own LatencyPlugin set to 20 ms and hosted as a
clip effect: the render is byte-for-byte the input (transient still at
0.250 s) while the same object reports 20.000 ms of latency, because
latencyTimeSeconds * sampleRate rounds to zero samples. A third-party
saturator with oversampling renders as if it had none.

Reproduction: one wave clip; add a PluginEffect wrapping LatencyPlugin
(latency 0.02) to its ClipEffects; let the chain render; compare the render
with the source. Identical. Assertion at PluginNode.cpp:112 in Debug.

Why an app cannot work around it: preparing the plugin at the right rate
before the render does not survive - Plugin::baseClassInitialise re-runs
initialise whenever the rate or block size CHANGED, so the constructor's
0 Hz call undoes any earlier prepare.

Fix: construct the PluginNode with the source file's sample rate (the
job knows its source), or defer the node's construction to
createAndPrepareRenderContext, where processState.sampleRate is set from
the writer.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    claude-dispatchedA local Claude session has been dispatched for this issueclaude-localOpt this PR in for the local Claude PR-concierge sessionclaude-started

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions