openmixer — generated API reference
    Preparing search index...

    Interface ChannelSnapshotJson

    A single channel's full snapshot. Optional fields are omitted when absent.

    interface ChannelSnapshotJson {
        alignDelayMs?: number;
        alignReference?: string;
        chain?: readonly PluginSlotJson[];
        colour?: string;
        comp?: CompState;
        delay?: DelayState;
        digitalGainDb?: number;
        divergence?: number;
        drive?: DriveState;
        eq?: EqState;
        fader?: FaderLevelJson;
        fbs?: FbsChannelStateJson;
        gate?: GateState;
        gateKey?: GateKeyState;
        headAmpGainDb?: number;
        hrp?: HrpChannelState;
        id: ChannelRefJson;
        instrument?: string;
        link?: ChannelLinkJson;
        mute?: boolean;
        name?: string;
        pad?: boolean;
        pan?: number;
        phantom?: boolean;
        polarity?: boolean;
        processors?: readonly ProcessorSnapshotJson[];
        record?: boolean;
        recordTaps?: readonly string[];
        reverb?: ReverbState;
        rtaArmed?: boolean;
        sends?: readonly SendJson[];
        soloSafe?: boolean;
        sourceRef?: string;
        sources?: readonly StoredPatchEndpoint[];
        sourceStereo?: boolean;
        stageOrder?: readonly (
            "eq"
            | "gate"
            | "dynamics"
            | "delay"
            | "reverb"
            | "drive"
        )[];
        toMain?: boolean;
        trimDb?: number;
    }
    Index
    alignDelayMs?: number

    INPUT ALIGNMENT delay, ms — the input-stage latency that pushes this microphone back to meet another on the same source. Persisted because a show that restores without it comes back COMBING: the operator aligned two mics, the desk forgot, and nothing says so.

    alignReference?: string

    WHICH channel this one was aligned against — the record the next operator needs to check or redo the alignment. No audio consequence of its own.

    chain?: readonly PluginSlotJson[]

    Ordered insert chain (the per-strip plugin chain).

    colour?: string

    Scribble-strip colour (a token hue key, e.g. "red"); absent = the surface default.

    comp?: CompState
    delay?: DelayState

    The built-in TIME-BASED inserts — the native FX delay and reverb — persisted for the same reason and by the same rule as eq/gate/comp above: present only for a channel whose store has actually been touched, absent meaning "never set" (the console default plays).

    They must ride the show because the boot / post-load lane assert pushes whatever these stores hold onto every lane. While they were unpersisted (audit D2) a load wrote nothing into them, so loading tonight's show left LAST night's echoes and tail running underneath it — audible, and invisible on every row.

    digitalGainDb?: number

    The CONSOLE's own digital gain (dB), on a channel with no analog head-amp — the encoder value the adapter applies directly. Its counterpart is headAmpGainDb, the BOX's gain; the two names are the whole disambiguation (operator ruling, 2026-08-12: "We must distinguish digital gain that belongs to the console, from headAmp gain that belongs to the box. The distinction is clear enough with these names."). undefined on a head-amp channel: its gain is the preamp's, and lives there.

    Replaces the retired gainDb/gainIsSens pair (2026-07-30, no back-compat). That pair tried to disambiguate whether a stored gainDb meant the digital stage or the analog preamp; guessing wrong jumped a channel's real gain by up to 20 dB. There is nothing to guess now, and the reason has not changed with the unit: which stage a number belongs to is settled by WHICH KEY IT IS IN, never by a flag. A session still carrying gainDb — or the retired sensDbu (see headAmpGainDb) — is detected at load as an unknown field and reported LOUDLY via WarningsController under 'session.load', never silently reinterpreted.

    divergence?: number

    Per-source LCR image (#176, 2026-09-08-lcr-mains.md §8.1): 0 (hard discrete centre) .. 1 (full phantom). Absent ⇒ 1 — an unset divergence plays exactly today's stereo image, so a bus flipped to lcr with no operator action yet does not silently snap every source to hard-centre. Meaningful only where this channel's tap lands on an lcr-format bus.

    drive?: DriveState

    The native DRIVE stage — the strip's saturator. Rides the show by the same rule and for the same reason as delay and reverb above: the boot / post-load lane assert pushes whatever this store holds onto every lane, so a drive that did not persist would leave the LAST show's saturation running under tonight's — audible, and invisible on every row.

    eq?: EqState

    The built-in EQ / gate / compressor stores — separate from the plugin insert chain.

    The channel's FBS auto-corrector arming (mode / hold / cap) — restored on boot so an armed channel stays armed across a restart (the planted bands themselves ride eq).

    gate?: GateState
    gateKey?: GateKeyState

    WHAT the gate's detector listens to — the KEY (keyed gates §3): the source channel (absent or null = self), the two detector-filter edges and the listen latch. Rides the show for the same reason the gate's own curve does: a bass gate keyed off the kick that came back un-keyed would open on the bass's own decay, which is the fault the operator set the key to cure. Present only for a channel whose key store has been touched; absence means "never set", and the console's own default (self, no filter, not listening) plays.

    headAmpGainDb?: number

    The BOX's head-amp GAIN in dB — the preamp's, never the console's digital stage (that is digitalGainDb). Persistence: see phantom.

    Replaces the retired sensDbu key (2026-08-12, #165 — one wire unit, no back-compat). The desk stored Roland's dBu SENS convention, so the same fact was published in dBu beside a range in dB and every consumer re-derived it. A file carrying the old key is NOT converted in place at load: reading a sensDbu of −40 as a gain would set the preamp to the floor, and reading a gainDb of 30 as dBu would put it near the top — the two scales run OPPOSITE ways, so a wrong guess here is worse than the 20 dB one that retired gainIsSens. The key is reported loudly and ignored; the conversion is an explicit, scripted, offline rename.

    The harmonic resonance processor's arming. Persisted for the same reason fbs is: it is a decision the operator made about THIS mic in THIS room, and a show that reopens without it would silently stop correcting a channel the operator believes is being corrected.

    instrument?: string

    What this input IS — a factory template id; absent = the operator has not said.

    Stereo-link state (M32 / Roland paradigm). Present only on a linked channel; persisting it lets a reload re-establish the link so the pair restores as one stereo strip.

    mute?: boolean
    name?: string
    pad?: boolean

    −20 dB analog pad ahead of the box's preamp. Persistence: see phantom.

    pan?: number
    phantom?: boolean

    +48 V phantom on the channel's physical input. Like pad and headAmpGainDb, persisted under the KNOWN-set rule where the head-amp entity resolves the channel: only a value an operator set or the box reported is written to the file, and an absent field means "never asserted" — a restore then leaves the preamp exactly as it is. On a console without the entity these mirror the strip fields.

    polarity?: boolean
    processors?: readonly ProcessorSnapshotJson[]

    The strip's PROCESSING ARRANGEMENT — its ordered Processor chain, the one processing model (mixer-standard.md: "there are no fixed eq/dynamics/inserts slots on a strip; there is only chain"). Order is load-bearing (ADR-0006) and reaches audio through the native step walk, so a show that reopens with its stages in the console default order is a different-sounding show.

    Absent means the strip was never assembled and loads to the kind's normalized default.

    record?: boolean

    Whether the operator wants this channel CAPTURED by the multitrack recorder (/channel/{kind}/{index}/record — recording-vsc §0.2's per-channel opt-out).

    ABSENT means the kind's own answer, never "off" (see recordDefaultFor): an input and MAIN arm by default, an aux or a matrix does not. So a show only ever writes the channels whose arming the operator MOVED, and a saved show stays sparse — a desk full of channels nobody touched carries no record field at all.

    The wish only, never the outcome. Whether a channel actually lands in a take is decided at record start, where the patch filters this against what is really feeding the head; a channel that is unpatched today records again the moment something is patched into it, because nothing here changed.

    recordTaps?: readonly string[]

    WHICH TAP POINTS the recorder captures for this channel — the per-channel override behind /channel/{kind}/{index}/record's taps (recording-vsc §0.3: "input + post-fader by default; pre-fader opt-in", "simultaneously").

    ABSENT means the kind's own answer (recordTapsDefaultFor), never "none": a show only ever writes the channels whose tap set the operator MOVED, exactly as record does. A stored EMPTY list is a real decision and not an absence — it says "capture nothing here", which is the same thing as record: false said a different way, and both spellings survive because record answers whether and this answers where.

    The ids are TapPointIds from the ONE catalogue (tap-points.ts), never a private input/preFader/postFader vocabulary: two desks offering a pre-fader capture must be offering the SAME point under two labels, which is what a template is for.

    reverb?: ReverbState
    rtaArmed?: boolean

    Whether the operator has armed this channel's real-time ANALYZER (/channel/{kind}/{index}/rta's armed). Persisted for the same reason fbs is: it is a decision the operator made about the show, not a display state, so it outlives a reload and a restart. Absent means never armed — the desk then analyses this channel only while something is displaying it.

    sends?: readonly SendJson[]

    Sends from this channel into output buses.

    soloSafe?: boolean

    Solo-safe (SIP-mute exemption only — cue/solo-to-monitor spec, resolved Open Question #2). Absent reads as the kind-based default (see soloSafeDefaultFor), so a session predating this feature restores unchanged.

    sourceRef?: string

    The registered source-layer reference feeding the channel (ChannelStrip.sourceRef / SourceId — the WING/Roland source model), when one is assigned. Persisted BESIDE the resolved sources endpoints because the two carry different halves of the patch: the endpoints are the projection, the reference is the provenance plus the preamp ownership (a source-fed channel's analog trio follows the source). While this was not persisted, a restore re-patched by raw endpoint and thereby ERASED the reference — the source layer's raw-endpoint door demotes the channel to an implicit source — so every reload silently downgraded source-fed channels (channel contract, phase 2 adjudication). On restore the reference door is preferred where present; the raw endpoints remain the fallback for a channel with no registered source.

    sources?: readonly StoredPatchEndpoint[]

    The channel input patch: the full set of source endpoints feeding the channel head ([primary, ...extras]), each { l, r? } by port name (persistence-by-name, never a transient PipeWire id). The crosspoint patchbay's multi-in — more than one entry means several inputs sum at the head. Present only when a source patch is known; a reload re-establishes each entry so the patch restores.

    sourceStereo?: boolean

    The channel's semantic source width at capture: true when its patch made the channel stereo (a stereo pair patched in). Mirrors ChannelPatchJson.stereo (the standalone-patch field); stored explicitly because a construction-seeded engine feed is 2-channel plumbing (mono by convention) while the same-shaped operator patch is a stereo source. Absent → the loader derives from the stored endpoint shapes.

    stageOrder?: readonly (
        "eq"
        | "gate"
        | "dynamics"
        | "delay"
        | "reverb"
        | "drive"
    )[]

    The strip's STAGE ORDER, as the operator's OVERRIDE and never as the derivation (2026-09-15-channel-stage-order.md §8): a strip running the default order writes no field, and an absent field restores as the default. Rides the show for drive's reason with one edge of its own — a lane outlives every session, so an order that did not persist would leave LAST show's walk running under tonight's, on a row that would read the default back the whole time.

    toMain?: boolean

    Whether the channel is assigned to the main mix (the console MAIN routing toggle beside the group assigns). A channel feeds main by default, so an absent value reads true (see channelRoutesToMain); only an explicit false — a channel reaching main solely through its subgroups — keeps it out.

    trimDb?: number

    Digital input trim in dB (composes with the channel's gain — see ChannelStrip.trimDb).