9 KiB
Mixer, automation and undo
Phase 8 provides one selectable channel strip per project track. Open Mixer (Ctrl+2), select a track, and set Gain, Pan, Mute and Solo. Changes stop transport; Play prepares independent audio/MIDI snapshots with the accepted settings. No edit changes a plan that the callback is using. Editing is blocked while 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. 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 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
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 and resets editor selections/layout. 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. An allocation failure retaining a new history snapshot reports an error; the accepted edit remains in the document.
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.
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.