Commit Graph
2 Commits
Author SHA1 Message Date
OmikronApexandClaude Fable 5 dd40b2f227 fix(audio): renderer-bus flush flag + reconfigure reads user intent (phase 8)
Two deep-read fixes now homed in their phase-1/2 units:

RendererBus (§4): setEnabled(false) no longer writes readIndex from the
control thread — the ring's designated consumer-side writer is pull(). The
drop-on-disable is now a flushRequested atomic the consumer honors at its
next pull, closing the last SPSC-discipline hole (a concurrent pull
mid-drain could overwrite the control thread's store and replay a stale
tail after re-enable). New unit test pins flush-then-fresh-audio.

setAudioDevices (§3): the restart decision reads state.userWantsAudio
(intent, written only by start/stopAudio) instead of the racy device-state
flag that transient audioDeviceStopped() fires clear — a reconfigure landing
inside a transient-stop window no longer leaves the engine configured but
stopped ('no audio until Start/Apply is pressed again').

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 01:47:32 +02:00
OmikronApexandClaude Fable 5 70f3316094 refactor(audio): extract RendererBus (phase 2)
Moves the WebAudio→engine bus — ring, producer-side linear resampler,
prefill gate, fill clamp, metrics — verbatim into
src/audio/engine/RendererBus.h. AudioEngine keeps thin facades
(setRendererBus/pushRendererAudio/pullRendererBus/getRendererBusMetrics) so
the NodeAddon surface is unchanged. JUCE-free: pull() takes raw channel
pointers, which is what lets tests/engine_units drive the resampler
continuity, prime/underflow/clamp, and metrics cases without a device.

The control-thread readIndex write on disable (deep-read §4) is preserved
verbatim and marked; its flush-flag fix lands as the phase-8 commit.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-13 23:46:55 +02:00