Skip to content

Automation, markers and the rest

  • Track::automation: Vec<AutoLane>; each lane has an AutoParam (Volume, Pan, Mute, Send(slot), or Plugin { uid, param, name }) and sorted AutoPoint { pos, value, curve }. Values are in native units: dB for volume and sends (-96..+6), -1..1 for pan, 0/1 for mute, 0..1 normalized for plug-in parameters.
  • automation::value_at interpolates between points, holds the first value before the first point and the last after the last; two points at one position make a step. A point’s curve (-1..1, 0 straight, saved only when set) bends the segment after it: automation::shape is t^(2^(-3·curve)). A straight segment takes exactly the old arithmetic, so projects without curves play bit for bit as before. The frontend’s autoLanes.ts mirrors it for drawing.
  • Track::auto_mode is Logic’s Off / Read / Touch / Latch / Write (AutoMode).
  • The engine gets lanes as Arc<Vec<LaneDsp>> (empty lanes left out) and compares targets with the cheap AutoTarget (no names).
  • Stereo Out has lanes too (Master::automation, auto_mode): every automation command and Cmd takes MASTER_ID for it (session/auto_lanes.rs has strip_lanes), and the engine plays them in dsp/auto.rs (volume and plug-ins, read pdc.total back).
  • Folder stacks automate their volume and mute. A track whose nearest folder (TrackParams::folder) has automation playing works out the folder’s FoldState (fold_at, through the folders above it) at its own fader time, so the lanes line up with its delay-compensated audio, and rebuilds its volume and mute from own_gain, own_mute, bus_mute and its VCA’s vca_gain and vca_mute with the folder’s gain and mute. Without folder automation the session’s static stack values apply as before.
  • Which lanes the UI shows: the main lane’s parameter is UI state (autoLane in the store); the extra lanes below a track are Track::auto_lanes (Master::auto_lanes for the Output track), set with set_auto_lanes (one undo step). layout.ts gives them autoRows after the track’s heights, and the Output track an output row below total.
  • Writing is in session/auto_write.rs: a pass collects points while a control moves (and about 30 times a second from idle), and goes into its lane in one undo step when it ends (on release in Touch, at Stop otherwise). automation::splice inserts it and thin removes points within a per-parameter tolerance (Ramer-Douglas-Peucker on the vertical error).
  • Project::markers is the Marker track, sorted by position (session/markers.rs). Markers are pure project data; the engine never sees them. Marker::length is a marker’s own length; None means it reaches the next marker (markerEnd in markers.ts).
  • Project::arrangement is the Arrangement track: ArrangementMarker { id, name, start, length, color } sections, sorted and tiling the timeline (each starts where the one before ends), in samples like markers (they don’t follow tempo changes). arrangement.rs holds the pure arithmetic: tiling, resize (ripples the later sections only), and the plans for moving, copying and deleting a section with its content. A plan is a time map (see Time maps for section edits): time before the arrangement stays, time after it shifts by the change in length, and neighbouring pieces that stay together are merged, so content is only cut where it comes apart. remap_points adds the old curve’s value at each piece’s first and last sample (pruning those the curve doesn’t need, as auto_move does). session/arrangement.rs applies a plan in one step: a looping region cut at a piece edge first becomes real copies, the first piece of a cut region keeps its id, and markers in a copied section are copied too.
  • Project::punch: Punch { enabled, start, end } is the Autopunch range. While recording, Cmd::Autopunch tells the engine where armed tracks stay silent and where input is captured.

Track::frozen: Option<FreezeInfo { clip, start }> (session/freeze.rs):

  • While set, regions_dsp returns just the freeze file, eq_coeffs returns a flat EQ, the plug-ins are unloaded from the engine, and their settings are kept in PluginSlot::state.
  • Freezing has two steps: render_freeze (an isolated render, may run on a worker thread) and place_freeze (main thread, one undo step capturing plug-ins).
  • Edits to a frozen track’s regions, plug-ins or Channel EQ are refused twice over: check_unfrozen errors before the edit where it can, and frozen_guard (called by every edit wrapper) puts back anything that slipped through and reports why.
  • Freeze files live in the project’s Freeze Files/ folder. Unfreezing deletes the file but keeps the clip in memory, so undo can freeze again; ensure_freeze_files writes a missing file back before saving.

Track::alternatives: Vec<TrackAlternative { name, regions }> holds a track’s inactive region sets and Track::alternative the active one’s name (empty means “A”); Track::regions is always the active set, so nothing else in the engine or the UI needs to know about alternatives (session/track_alternatives.rs). Switching swaps the sets and resends the regions; every operation is an ordinary undoable edit, and restore resends regions that differ. Frozen tracks refuse these edits up front, since frozen_guard only puts regions back. Project::for_ui sends only the inactive alternatives’ names. Region ids in inactive sets stay allocated, and their clips stay in Project::clips.

name, sample_rate, tempo (5..990 BPM), sig_num/sig_den, key (a string such as “C major”), master (Stereo Out: volume, inserts, EQ), cycle, metronome, count_in, clips (id to path, relative to the project folder unless outside it), groups, click (metronome settings), bit_depth (per-project recording format override), notes and alternative (the project alternative’s name, see Persistence; restore keeps the current one, since renaming isn’t an undo step).