With a CLAP plugin wrapped as AUv3, parameter changes stop synchronizing in both directions while audio processing is suspended, even though parameters remain editable. Resuming audio processing delivers the pending changes.
Reproduced with AUv3 in both hosts:
- REAPER 7.79
- Audio Hijack 4.6.0
Tested on macOS 26.6.2 / Apple Silicon, using next at 9501dad0, matching upstream next when checked.
Expected behavior
Parameter exchange should continue without requiring audio processing to resume. CLAP explicitly provides params.flush() for this purpose. Its parameter contract says host-control changes are delivered through process() or flush(), and host_params.request_flush() requires the host to schedule one of those calls. Here, the wrapper is the CLAP host. CLAP parameter contract, at the SDK revision used.
flush() must not run concurrently with process() and must follow CLAP's active/inactive thread rules. Those constraints require serialized delivery; they do not make audio processing a prerequisite for parameter exchange.
Quick reproduction — no debugger
Attached: passive-parameters-repro.zip. It contains a small CLAP plugin, AUv3 build/install instructions, and detailed reproduction steps. The plugin has one parameter, silent audio output, exact-value buttons, and an event log.
The following steps use Audio Hijack's block off/on control as a concrete example. Build/install the plugin, load Example: Passive Parameters, and start the session with the block on. Locate both the plugin editor and the host's own Value control.
- Click Set 0.25 in the plugin editor; confirm both sides show 0.25.
- Turn the block off, click Set 0.75, and wait five seconds.
Plugin: 0.75; host: still 0.25.
- Turn the block on, without another edit. The host catches up to 0.75.
- Reset both sides to 0.25 while on, then turn the block off again.
- Change Value through the host's control to approximately 0.6 and wait.
Host: new value; plugin: still 0.25.
- Turn the block on. The plugin catches up.
The expected result in steps 2 and 5 is agreement while the block stays off. The log identifies events delivered via process or flush; compare both value displays, since acceptance of a CLAP output event alone does not prove AUv3 delivery.
Investigation
The following runtime observations were collected in Audio Hijack.
- Plugin -> Host: the request reaches
param_request_flush(),
which only logs it. The outgoing change remains pending until processing resumes.
- Host -> Plugin: the
AU parameter observer
sees _renderResourcesAllocated == YES even with the block off, queues the change for audio processing, and skips flush(). We observed pending changes and stale plugin state; enabling the block drained them through process().
Apple defines renderResourcesAllocated as resource-allocation state, not a guarantee of subsequent processing callbacks. Relying on it to defer all delivery leaves parameter exchange stalled in this state.
passive-parameters-repro.zip
With a CLAP plugin wrapped as AUv3, parameter changes stop synchronizing in both directions while audio processing is suspended, even though parameters remain editable. Resuming audio processing delivers the pending changes.
Reproduced with AUv3 in both hosts:
Tested on macOS 26.6.2 / Apple Silicon, using
nextat9501dad0, matching upstreamnextwhen checked.Expected behavior
Parameter exchange should continue without requiring audio processing to resume. CLAP explicitly provides
params.flush()for this purpose. Its parameter contract says host-control changes are delivered throughprocess()orflush(), andhost_params.request_flush()requires the host to schedule one of those calls. Here, the wrapper is the CLAP host. CLAP parameter contract, at the SDK revision used.flush()must not run concurrently withprocess()and must follow CLAP's active/inactive thread rules. Those constraints require serialized delivery; they do not make audio processing a prerequisite for parameter exchange.Quick reproduction — no debugger
Attached: passive-parameters-repro.zip. It contains a small CLAP plugin, AUv3 build/install instructions, and detailed reproduction steps. The plugin has one parameter, silent audio output, exact-value buttons, and an event log.
The following steps use Audio Hijack's block off/on control as a concrete example. Build/install the plugin, load Example: Passive Parameters, and start the session with the block on. Locate both the plugin editor and the host's own Value control.
Plugin: 0.75; host: still 0.25.
Host: new value; plugin: still 0.25.
The expected result in steps 2 and 5 is agreement while the block stays off. The log identifies events delivered via
processorflush; compare both value displays, since acceptance of a CLAP output event alone does not prove AUv3 delivery.Investigation
The following runtime observations were collected in Audio Hijack.
param_request_flush(),which only logs it. The outgoing change remains pending until processing resumes.
AU parameter observer
sees
_renderResourcesAllocated == YESeven with the block off, queues the change for audio processing, and skipsflush(). We observed pending changes and stale plugin state; enabling the block drained them throughprocess().Apple defines
renderResourcesAllocatedas resource-allocation state, not a guarantee of subsequent processing callbacks. Relying on it to defer all delivery leaves parameter exchange stalled in this state.passive-parameters-repro.zip