xtc/docs/MIXER.md

195 lines
12 KiB
Markdown

# Studio mixer
Open **View / Mixer** (Ctrl+2) to see a channel strip for every track and bus.
The horizontal scrollbar reveals additional channels; the master output monitor
stays pinned on the right. The bank supports the full 64-track/bus project limit.
Channel order follows the sequencer, and colors match the track headers.
Each strip offers:
- A name button that selects its track for automation below the bank.
- **Mute** and **Solo** switches using the existing inclusive track/bus solo rules.
- A flat **Pan** knob: left -1, center 0, right +1. Drag to turn it;
double-click to center. The text shows direction and percentage.
- An output dropdown for **Master** or a project bus. Bus outputs stay at Master;
nested bus routing remains unsupported. **Add bus** creates a new bus strip.
- A vertical level fader, displayed in dB. Zero dB is unity gain. The upper limit
is approximately +12.04 dB (linear gain 4); the -60 dB bottom position is silence.
- Independent stereo sample-peak meters, numeric dBFS readouts and sticky clip
indications. **Reset peaks** clears all strip and master clip latches.
Changing a fader or knob commits on release, so a completed gesture is one undo
step. The existing preparation guard stops playback before model edits and
rejects changes while recording. Failed edits restore the displayed model values.
Selections are UI state and create no undo step. Track IDs keep controls attached
to the correct channel after reordering, undo, deletion or project replacement.
The top Track selector provides another way to select automation targets; the
bank scrolls to reveal the selection. M/S toggle the selected track's mute/solo,
Left/Right adjust its linear gain, Shift+Left/Right adjust pan, and Up/Down select
adjacent tracks. The existing automation controls below the bank retain Gain/Pan,
First tick and Linear/Hold interpolation. Click to add a point and right-click
near a point to remove it.
Faders and knobs display **static** mix values. Automation replaces those values
during playback; the controls are not motorized automation displays. Automation
values retain their existing linear gain and pan units. Existing project files
store mix values and automation without a format change. Very small nonzero
gains display at the fader floor; pan/mute/solo edits preserve their actual value.
Moving the fader to its bottom explicitly sets silence.
Meters use the backend's consumed peak snapshot for every track and bus,
including offscreen channels. Track taps are after track controls and before the
bus, bus taps follow bus controls, and the master follows the modular graph and
transport envelope. Missing taps decay to silence. Displays use instant attack,
20 dB/s release and sticky clipping at a linear sample peak of 1 or more.
Numeric displays have a -90 dBFS floor, channel bars a -60 dBFS floor; master
bars cover -90 to +6 dBFS. These are sample-peak meters, not loudness or true-peak
meters. The master strip is an output monitor, not a new gain control.
## Engine mixing 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. 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
those mono sources. Separate per-track graph inserts/sends are deferred.
## Automation lanes
Choose Gain or Pan under Automation. The lane shows four bars (15360 ticks);
First tick moves its viewport across the project. Grid labels are absolute ticks.
Click to add a point or replace the point at that snapped time (1/16 note, 240
ticks). Vertical position maps to gain 0..4 or pan -1..1, top to bottom descending.
Right-click near a point's time to remove it. Removing every point restores the
static control. There are at most 1024 points globally, with one per
track/parameter/tick. Track deletion cascades to its automation.
A nonempty lane replaces that parameter's static value. Between points the C
engine interpolates linearly or holds each segment (Interpolation chooser),
holding the first/last value outside
their range. Preparation converts ticks to integer sample endpoints, sorts and
indexes lanes. When several ticks quantize to one sample at very low sample
rates, the last point wins at that sample. Rendering searches prepared bounded
arrays; it never sorts, allocates, accesses project data, or calls the GUI.
Seeking and block partitioning give the same timeline values. Mute/solo are
static; automation capture, modes, curves and tempo automation are deferred.
## Stereo output and meters
The GUI opens the JACK backend with two audio output ports: `output` (left) and
`output_right`. Input and raw WAV recording remain mono. Connect both outputs
explicitly using an external JACK routing tool. Nothing connects hardware
automatically. Legacy configurations with channel_count=1 and the original
port/route APIs remain supported; output_name(channel) queries either stereo
port. Old mono audio/MIDI render functions apply gain/mute/solo and gain
automation while ignoring pan; the stereo variants apply both lanes.
The graph executes the same topology separately on left and right buses;
oscillators advance once per frame and are centered on both sides. Existing
port metadata and validation describe the mono graph topology. Stereo processing
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.
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 readouts display 20*log10(peak) dBFS, floor -90, with instantaneous
attack and 20 dB/second release. Channel bars cover -60 to +6 dBFS; master
bars cover -90 to +6 dBFS.
Each channel latches red CLIP at linear peak >=1 (0 dBFS) until Reset peaks.
Reset is session state, not an audio edit. Selection changes preserve every strip's meter 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
Ctrl+Z undoes; Ctrl+Shift+Z or Ctrl+Y redoes. The C history keeps 32 project edits
plus a baseline, cloning metadata and graph, never audio samples. Common graph,
track, clip, note, mixer, import/relink and automation edits are included. One
accepted gesture is one step; selection, scrolling and graph-node placement are
GUI state and are not undoable. New/Open resets history; Save retains it.
Undo/redo stops and resets transport; Phase 27 preserves surviving selections
by stable ID (layout remains session state). The
candidate is installed before moving the history cursor: validation, asset-plan
or backend failure retains the current document and history position. Missing
assets retain the existing silent/reporting behavior. A new edit after Undo
removes the redo branch; the oldest state is evicted at capacity. Allocation
ID high-water marks survive Undo/branching so abandoned IDs are not reused. History is
session-only and Undo marks the document dirty even if it matches a saved state.
External WAV files are never deleted or restored by Undo; recording itself cannot
be undone while active. Phase 27 reserves snapshot storage before GUI commands mutate/publish, so an
allocation failure rejects the command before adoption; reserved capture itself
does not allocate. C clients using unreserved history record must handle errors.
With mixer focus, M/S toggles mute/solo, Left/Right changes gain by 0.05,
Shift+Left/Right changes pan, and Up/Down selects a track. Native sliders also
support keyboard navigation; Ctrl+1/2/3 switches views, Ctrl+4 opens Piano roll,
F5/F8/Space controls transport and F9 panics, as before. There is no multiselection,
clipboard editing, track rename or automation-point dragging yet.
## Verification and limits
`test_mixer` verifies exact stereo gain/pan, mute/solo precedence, automation
samples and block equivalence, stereo graph phase/routing, WAV mixing, v4 exact
roundtrip/truncations/malformed records, lane capacities and history eviction and
branching. Backend fault injection verifies stereo registration failure, output
names, output separation and atomic meters. GUI tests edit lanes with mouse
events, use mixer keys and exercise undo/redo, failed installation rollback,
branching, save/reopen and history reset. Live JACK MIDI acceptance verifies
saved/reopened hard-right playback and stereo peaks using only software clients.
A native Xvfb mouse smoke check covers sliders and automation drawing.
Phase 36 adds checks for independent strip callbacks/meters, fader gestures, pan
centering, failed-edit restoration, routing, undo/reload, duplicate names and
stable IDs across reorder/removal. A 64-channel GUI session verifies scrolling
and minimum/large layouts. Screenshots include live JACK meters and a bus strip.
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.
Phase 26 adds Linear/Hold interpolation for each point added or replaced. The
point's mode applies to its following segment. Static controls remain fallbacks
while a lane exists; moving/splitting clips does not move absolute track/bus lanes.
See CONTROL.md for common parameter IDs and controller/automation precedence.