Phase 24: add mix buses, coherent peak meters and master clipping indicators

This commit is contained in:
Johannes Findeisen 2026-10-27 16:15:34 +01:00
commit 2fd7724065
32 changed files with 632 additions and 61 deletions

View file

@ -9,8 +9,7 @@ recording. Graph edits retain their existing live publication behavior.
Gain is a linear multiplier from 0 to 4. Pan ranges from -1 (left) to +1 (right):
center has unity on both sides and moving away attenuates the opposite side
linearly. This preserves existing centered mono levels; it is not an equal-power
pan law. Mute wins over Solo. If any track is soloed, only soloed, unmuted tracks
play. WAV clips and scheduled MIDI use their containing track's settings before
pan law. Mute wins over Solo. Solo behavior across tracks and buses is defined below. WAV clips and scheduled MIDI use their containing track's settings before
summing into the audio/instrument graph sources. Live MIDI input and independent
graph oscillators/external input are unassigned sources and bypass track mixing.
Stereo WAV files are still downmixed at import; stereo output comes from panning
@ -52,12 +51,50 @@ uses explicit paired buffers, not new port IDs. Output buffers must be distinct;
stereo callers must not alias them with source buffers. Graph-node meter reads
report the maximum of both sides on the processing owner only.
Mixer Output L/R bars show last-block post-graph absolute peaks, polled at 100 ms.
Peaks above unity turn red. Independent lock-free integer snapshots avoid sharing
DSP pointers or float state between callback and GUI; stopped meters show zero.
They are output meters, without per-track RMS, peak hold or loudness analysis.
There is no limiter: finite summed output can exceed unity. GUI polling may miss
brief peaks between refreshes; these bars are not overload history.
Track and bus meters measure coherent audio plus scheduled MIDI sums, after their
own gain/pan/mute/solo controls, before the shared modular graph. A track tap is
before its parent bus: a muted bus can have active member-track meters. Bus taps
are after bus controls. Master L/R measure the final graph output after transport
fades; downstream effects and graph routing can change its level independently.
The backend retains interval sample-peak maxima until one serialized control
reader consumes them with `xtc_backend_read_meters`. The GUI polls about every
100 ms. Atomic channels are independent (not a simultaneous waveform snapshot);
peaks are quantized to 0.000001 linear and capped at 1000. Legacy backend status
peaks remain last-block linear values. GUI bars display 20*log10(peak) dBFS, floor
-90, instantaneous attack and 20 dB/second release, with a +6 display ceiling.
Each channel latches red CLIP at linear peak >=1 (0 dBFS) until Reset peaks.
Reset is session state, not an audio edit. Selection changes reset selected-strip
history. These are sample-peak meters, not RMS, LUFS or true-peak measurements.
There is no limiter; summed levels can exceed unity.
## Mix buses and gain staging (Phase 24)
Use Add bus in Mixer, select an ordinary track, then choose its Route: Master or
an existing bus. Buses share the 64-track capacity and gain/pan automation APIs.
They contain no clips and feed master directly; nesting is rejected. Deleting a
bus reroutes its members to master without deleting their clips; undo restores
routing. Editing uses the existing stopped-transport preparation workflow.
Track controls apply first, then parent bus controls, then the shared graph.
Gain multiplies (track 2 times bus 2 gives 4); pan uses the same center-unity
balance law at both stages. There is no normalization or automatic attenuation.
Solo is one inclusive domain: a soloed track passes through its bus, a soloed bus
admits all its members, and unrelated tracks are silent. Track mute silences
that member; bus mute silences its entire output even when a member is soloed.
Live MIDI, external audio inputs and independent graph oscillators remain
unassigned and outside this solo domain.
Master here means the source mix feeding the shared graph, not independent
per-bus effect chains. Graph fan-out and gain branches permit parallel processing
of shared sources. Independent per-track aux sends, sidechains, bus plugin
inserts and nested buses are not represented and remain deferred.
Preparation allocates shared stereo monitor scratch on the control thread:
2 * track_count * max_frames * sizeof(float), at most 32 MiB at current limits.
The callback clears, accumulates and scans bounded buffers, with no allocation,
I/O, locks or GUI calls. Immutable audio/MIDI snapshots borrow this scratch until
stopped replacement or backend destruction.
## Undo and keyboard workflow
@ -96,3 +133,7 @@ saved/reopened hard-right playback and stereo peaks using only software clients.
A native Xvfb mouse smoke check covers sliders and automation drawing.
Physical stereo devices, listening quality, realtime endurance and high-density
project performance remain unverified; no new dependency was introduced.
`test_buses` covers bus routing, exact taps, audio/MIDI cancellation, controls,
automation, persistence, invalid routes, deletion/undo and dBFS ballistics. Backend
tests cover consuming interval peaks; GUI tests cover routing undo and clipping.