Skip to content

AUv2: three edge cases in Render() worth a second look #550

Description

@defiantnerd

Three related observations in WrapAsAUV2::Render() (src/wrapasauv2.cpp), collected while fixing AUV2-1 in the 0.16 release review. Grouped because they all concern the same function.

1. A host passing action flags gets silence

Render() gates on if (_initialized && (inFlags == 0)). AUV2-1 added an else branch that zeroes the output and raises kAudioUnitRenderAction_OutputIsSilence — which fixed the stale-audio bug, but it also means a host passing e.g. kAudioUnitRenderAction_DoNotCheckRenderArgs is now silently muted rather than silently stale.

Arguably still wrong: those flags do not mean "do not process". There is an assert(inFlags == 0) at the top of the function recording the expectation that no host does this, but an assert is not a plan for release builds.

Suggested fix: decide which flags are genuinely incompatible with processing and handle the rest normally, rather than treating any non-zero inFlags as unrenderable.

2. OutputIsSilence can leak in from upstream

ProcessData::flags is a reference passed through to PullInput. An upstream unit setting kAudioUnitRenderAction_OutputIsSilence on its own output can therefore surface as this wrapper's output flag, telling the host the plugin produced silence when it did not — a synth fed by a silent input bus, for instance.

Suggested fix: take a local copy of the flags for the input pull and set the wrapper's own output flag deliberately.

3. The render thread spins on a lock the main thread can hold indefinitely

(This is AUV2-3 from the review.) Render() spins on _processLock, and onIdle() can hold that lock across clap_plugin_params.flush() — plugin code of unbounded duration. If the main thread is preempted while holding it, the render thread spins a whole scheduler quantum.

Scenario: Logic idles a track for more than three blocks, onIdle() starts a flush, the user presses play at that moment.

Suggested fix: try_lock in Render() and skip-and-zero on failure, rather than a blocking spin. AUV2-1 already added a correct "produce silence" path this can reuse.

Notes

macOS-only; none of this was compiled or run here.

Part of the 0.16 review: https://claude.ai/code/artifact/2852de97-bdd0-4364-8c89-6892776b03d5

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions