@openmixer/omx-contract 2.6.0 → 2.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/data/kernels/comp.json +2 -2
- package/data/kernels/deesser.json +1 -1
- package/data/kernels/delay.json +3 -3
- package/data/kernels/drive.json +16 -0
- package/data/kernels/eq.json +2 -2
- package/data/kernels/fbs.json +1 -1
- package/data/kernels/gate.json +25 -0
- package/data/kernels/hrp.json +2 -2
- package/data/kernels/limiter.json +1 -1
- package/data/kernels/mixmatrix.json +1 -1
- package/data/kernels/reverb.json +2 -2
- package/data/kernels/rta.json +1 -1
- package/data/kernels/transient.json +1 -1
- package/data/kernels/trim.json +1 -1
- package/data/rates.json +1 -1
- package/dist/ts/omx-contract.d.ts +44 -19
- package/dist/ts/omx-contract.js +48 -19
- package/include/omxcontract/omx_contract_limits.h +12 -0
- package/lib/semver.mjs +1 -1
- package/package.json +1 -1
- package/render/c/contract-limits-render.mjs +8 -6
- package/render/doors.mjs +2 -2
- package/share/omx-contract/omx-contract.json +73 -20
package/README.md
CHANGED
|
@@ -49,7 +49,7 @@ pkg-config --cflags omx-contract
|
|
|
49
49
|
```
|
|
50
50
|
|
|
51
51
|
Pin one version and build against its renders instead of keeping a copy: the installed package at exactly
|
|
52
|
-
that version (`pkg-config --exact-version=2.
|
|
52
|
+
that version (`pkg-config --exact-version=2.8.0 omx-contract`), else the npm tarball, unpacked, and
|
|
53
53
|
`omx-contract render --target c --out build/omx-contract/include`. A kernel's controls and readouts, in their
|
|
54
54
|
order, are in `share/omx-contract/omx-contract.json`; how a declaration is written is in
|
|
55
55
|
[docs/kernel-files.md](docs/kernel-files.md), and what a readout is in [docs/readouts.md](docs/readouts.md).
|
package/data/kernels/comp.json
CHANGED
|
@@ -127,7 +127,7 @@
|
|
|
127
127
|
"name": "detectorTopology",
|
|
128
128
|
"kind": "choice",
|
|
129
129
|
"global": "DETECTOR_TOPOLOGY",
|
|
130
|
-
"doc": "Where the compressor's detector listens: `feedforward` hears the slot's input (or its key), `feedback` hears the slot's own pre-make-up output DYN_FB_LOOP_DELAY_SAMPLES late, through one envelope stage, and a keyed slot stays feed-forward (omx-dsp's OMX_DYN_TOPOLOGY_FEEDFORWARD 0 and _FEEDBACK 1, in that order; the set is named for its control, so C spells them OMX_DETECTOR_TOPOLOGY_*). The console's comp row carries it (`detectorTopology`,
|
|
130
|
+
"doc": "Where the compressor's detector listens: `feedforward` hears the slot's input (or its key), `feedback` hears the slot's own pre-make-up output DYN_FB_LOOP_DELAY_SAMPLES late, through one envelope stage, and a keyed slot stays feed-forward (omx-dsp's OMX_DYN_TOPOLOGY_FEEDFORWARD 0 and _FEEDBACK 1, in that order; the set is named for its control, so C spells them OMX_DETECTOR_TOPOLOGY_*). The console's comp row carries it (`detectorTopology`, the SSL bus compressor design §3a) and comes up `feedforward`, so a zeroed atom is the compressor every slot runs.",
|
|
131
131
|
"ids": [
|
|
132
132
|
"feedforward",
|
|
133
133
|
"feedback"
|
|
@@ -158,7 +158,7 @@
|
|
|
158
158
|
"constants": {
|
|
159
159
|
"PROGRAM_RELEASE": {
|
|
160
160
|
"kind": "sheet",
|
|
161
|
-
"doc": "The program-dependent release's model constants — the LA-2A's opto cell as DATA (
|
|
161
|
+
"doc": "The program-dependent release's model constants — the LA-2A's opto cell as DATA (compressor models design §3b). `chargeMs`/`dischargeMs` are the word's memory constants, shared by every profile; each profile's `fastMs`, `slowMinMs`, `slowMaxMs` and `share` fit the unit's published two-stage recovery. Not operator controls: generated into `omx_contract_limits.h` as `OMX_PROGRAM_RELEASE_*`, which libomxdsp's `omx_env_program_release` reads.",
|
|
162
162
|
"value": {
|
|
163
163
|
"chargeMs": 1000,
|
|
164
164
|
"dischargeMs": 5000,
|
|
@@ -128,7 +128,7 @@
|
|
|
128
128
|
"constants": {
|
|
129
129
|
"DEESS_KNEE_DB": {
|
|
130
130
|
"kind": "scalar",
|
|
131
|
-
"doc": "The knee, in dB — a CONSTANT of the stage and not a row field
|
|
131
|
+
"doc": "The knee, in dB — a CONSTANT of the stage and not a row field: a de-esser without a soft knee latches audibly on the first sibilant of a phrase, and no other value of this number is a de-esser anyone would dial. The controller pushes it to the node and this is the same number; a second spelling would be a picture that disagrees with the audio about where the reduction starts.",
|
|
132
132
|
"unit": "dB",
|
|
133
133
|
"value": 6
|
|
134
134
|
}
|
package/data/kernels/delay.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"name": "fxDelayTime",
|
|
6
6
|
"kind": "travel",
|
|
7
7
|
"global": "FX_DELAY_TIME_RANGE",
|
|
8
|
-
"doc": "The FX delay's time travel. `max` is the NATIVE ring's ceiling — the same number as `OMX_FXDELAY_MAX_MS` in `omx_delay.h`, pinned to it by
|
|
8
|
+
"doc": "The FX delay's time travel. `max` is the NATIVE ring's ceiling — the same number as `OMX_FXDELAY_MAX_MS` in `omx_delay.h`, pinned to it by the engine's conformance test. Distinct from the per-route ALIGNMENT delay (`OUTPUT_DELAY_RANGE`, 1 s, `OMX_DELAY_MAX_MS`): one is a musical echo with feedback and mix, the other is a pure latency. Two facts, two rings, two ceilings — sharing the word \"delay\" is why they keep being confused for each other.",
|
|
9
9
|
"travel": {
|
|
10
10
|
"min": 0,
|
|
11
11
|
"max": 2000,
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
{
|
|
39
39
|
"name": "tone",
|
|
40
40
|
"kind": "travel",
|
|
41
|
-
"doc": "The FX delay's TONE — a NORMALIZED_RANGE instance with its own come-up value, matching
|
|
41
|
+
"doc": "The FX delay's TONE — a NORMALIZED_RANGE instance with its own come-up value, matching the console's delay default tone. See REVERB_SIZE_RANGE for why this is a named constant rather than a default on the shared shape.",
|
|
42
42
|
"travel": {
|
|
43
43
|
"min": 0,
|
|
44
44
|
"max": 1,
|
|
@@ -84,7 +84,7 @@
|
|
|
84
84
|
"constants": {
|
|
85
85
|
"FX_DELAY_PINGPONG_DEFAULT": {
|
|
86
86
|
"kind": "scalar",
|
|
87
|
-
"doc": "The FX delay's PING-PONG come-up value — a toggle, so it has no travel, only this. Declared here rather than as a literal in the
|
|
87
|
+
"doc": "The FX delay's PING-PONG come-up value — a toggle, so it has no travel, only this. Declared here rather than as a literal in the console's delay default state (which now reads it) so the DPF plugin generator (omx-plugins, DPF plugin design §3a) reads the same fact the desk seeds a fresh strip with.",
|
|
88
88
|
"unit": "",
|
|
89
89
|
"value": false
|
|
90
90
|
}
|
package/data/kernels/drive.json
CHANGED
|
@@ -161,6 +161,22 @@
|
|
|
161
161
|
"12 kHz",
|
|
162
162
|
"16 kHz"
|
|
163
163
|
]
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
"name": "oversample",
|
|
167
|
+
"kind": "choice",
|
|
168
|
+
"doc": "The drive's OVERSAMPLING factor: the shaper runs inside the console's one oversampler at 1x, 2x or 4x, and the id is the factor (`omx_drive.h`'s `omx_drive_factor_of` member set, `struct omx_drive.os_factor`). A field of the console's drive row (`DriveState.oversample`, the console's DRIVE_OVERSAMPLE_FACTORS; the set is named for its control), 4 at come-up there and in omx-dsp's drive face (OMX_DRIVE_INSTANCE_FACTOR, the oversampler's largest).",
|
|
169
|
+
"ids": [
|
|
170
|
+
1,
|
|
171
|
+
2,
|
|
172
|
+
4
|
|
173
|
+
],
|
|
174
|
+
"default": 4,
|
|
175
|
+
"labels": [
|
|
176
|
+
"1x",
|
|
177
|
+
"2x",
|
|
178
|
+
"4x"
|
|
179
|
+
]
|
|
164
180
|
}
|
|
165
181
|
],
|
|
166
182
|
"constants": {
|
package/data/kernels/eq.json
CHANGED
|
@@ -107,7 +107,7 @@
|
|
|
107
107
|
{
|
|
108
108
|
"name": "gain",
|
|
109
109
|
"kind": "travel",
|
|
110
|
-
"doc": "The parametric-band gain travel, in dB. The ± scalar `clampEqGain` enforces is READ off this (
|
|
110
|
+
"doc": "The parametric-band gain travel, in dB. The ± scalar `clampEqGain` enforces is READ off this (the engine derives its gain limit from `max`), so the bound is stated once and a surface cannot draw a wider knob than the clamp will honour.",
|
|
111
111
|
"travel": {
|
|
112
112
|
"min": -15,
|
|
113
113
|
"max": 15,
|
|
@@ -162,7 +162,7 @@
|
|
|
162
162
|
"constants": {
|
|
163
163
|
"EQ_MAX_BANDS": {
|
|
164
164
|
"kind": "scalar",
|
|
165
|
-
"doc": "The maximum number of parametric bands a channel EQ may hold — the operator can add up to this many. Generated into `omx_contract_limits.h` as `OMX_EQ_MAX_BANDS`, which `omx_biquad.h` reads (
|
|
165
|
+
"doc": "The maximum number of parametric bands a channel EQ may hold — the operator can add up to this many. Generated into `omx_contract_limits.h` as `OMX_EQ_MAX_BANDS`, which `omx_biquad.h` reads (the engine's conformance test reads the header): the native lane allocates exactly this many biquad slots per channel and silently clamps above it, so the model, the wire, and the DSP agree by test, not by memory.",
|
|
166
166
|
"unit": "",
|
|
167
167
|
"value": 24
|
|
168
168
|
},
|
package/data/kernels/fbs.json
CHANGED
|
@@ -130,7 +130,7 @@
|
|
|
130
130
|
},
|
|
131
131
|
"FBS_MAX_NOTCH_DEPTH_DB": {
|
|
132
132
|
"kind": "scalar",
|
|
133
|
-
"doc": "THE NOTCH DEPTH LAW: the deepest cut any machine planter may propose from one reading, in dB. A number, not a literal at the call site, because two planters now lean on it. FBS derives a candidate's depth from the peak-to-average ratio around its bin and stops here; Room Analysis derives a mode's depth from its height above the median curve and is held to the SAME ceiling (
|
|
133
|
+
"doc": "THE NOTCH DEPTH LAW: the deepest cut any machine planter may propose from one reading, in dB. A number, not a literal at the call site, because two planters now lean on it. FBS derives a candidate's depth from the peak-to-average ratio around its bin and stops here; Room Analysis derives a mode's depth from its height above the median curve and is held to the SAME ceiling (the room-analysis design §4 — \"never more than the FBS notch depth law\"). Written twice as `18` those two bounds would be equal by coincidence and could drift apart in silence. It is a CEILING ON THE PROPOSAL, not the final gain: a band that lands as a rampable BELL is bounded again by `EQ_GAIN_RANGE`, which is tighter. A planter must honour both and REPORT when either bit, never quietly deliver a shallower cut than it was asked for.",
|
|
134
134
|
"unit": "dB",
|
|
135
135
|
"value": 18
|
|
136
136
|
},
|
package/data/kernels/gate.json
CHANGED
|
@@ -126,6 +126,28 @@
|
|
|
126
126
|
"default": 16,
|
|
127
127
|
"defaultFrom": "desk"
|
|
128
128
|
}
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
"name": "hpHz",
|
|
132
|
+
"kind": "travel",
|
|
133
|
+
"table": "GATE_KEY_LIMITS",
|
|
134
|
+
"travel": {
|
|
135
|
+
"min": 0,
|
|
136
|
+
"max": 20000,
|
|
137
|
+
"step": 1,
|
|
138
|
+
"unit": "Hz"
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
"name": "lpHz",
|
|
143
|
+
"kind": "travel",
|
|
144
|
+
"table": "GATE_KEY_LIMITS",
|
|
145
|
+
"travel": {
|
|
146
|
+
"min": 0,
|
|
147
|
+
"max": 20000,
|
|
148
|
+
"step": 1,
|
|
149
|
+
"unit": "Hz"
|
|
150
|
+
}
|
|
129
151
|
}
|
|
130
152
|
],
|
|
131
153
|
"readouts": [
|
|
@@ -146,6 +168,9 @@
|
|
|
146
168
|
"tables": {
|
|
147
169
|
"GATE_LIMITS": {
|
|
148
170
|
"doc": "The legal range of each gate field (engineering units). The widget clamps drags to these, `normalizeGate` enforces them, the row's codec refuses by them and the travel sheet publishes them — one source of truth. `rangeDb` reaches GATE_RANGE_FLOOR_DB, shown as \"−∞\" in readouts (a gate fully closed is silence)."
|
|
171
|
+
},
|
|
172
|
+
"GATE_KEY_LIMITS": {
|
|
173
|
+
"doc": "The travel of each edge of the keyed gate's detector filter, 0 (off) up to 20 kHz in whole Hz, as the console's `/channel/{kind}/{index}/gate/key` row serves them (the console's GATE_KEY_LIMITS). A property of the detector filter, not of any desk: no come-up value is declared."
|
|
149
174
|
}
|
|
150
175
|
}
|
|
151
176
|
}
|
package/data/kernels/hrp.json
CHANGED
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
},
|
|
25
25
|
"HRP_MAX_VOICES": {
|
|
26
26
|
"kind": "scalar",
|
|
27
|
-
"doc": "How many simultaneous musical voices the detector may report on one channel. PINNED to `OMX_HRP_MAX_VOICES` in `pipewire-native/src/hrp_pitch.h` — the C voice set is a FIXED-SIZE array, so a TS number above the macro promises voices the analyser structurally cannot return, and one below it silently drops notes the C already found.
|
|
27
|
+
"doc": "How many simultaneous musical voices the detector may report on one channel. PINNED to `OMX_HRP_MAX_VOICES` in `pipewire-native/src/hrp_pitch.h` — the C voice set is a FIXED-SIZE array, so a TS number above the macro promises voices the analyser structurally cannot return, and one below it silently drops notes the C already found. the engine's conformance test reads the header and holds the pair equal. EIGHT (operator sizing, 2026-09-01): a guitar sounds six strings, a piano or string-section voicing sits at eight. It is a SEARCH ceiling, not a cost — the detector abandons a round as soon as no credible candidate remains, so monophonic material costs what it always did.",
|
|
28
28
|
"unit": "",
|
|
29
29
|
"value": 8
|
|
30
30
|
},
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
},
|
|
61
61
|
"HRP_DEFAULT_MAX_AUTO_BANDS": {
|
|
62
62
|
"kind": "scalar",
|
|
63
|
-
"doc": "How many bands HRP may plant on ONE channel — its half of the machine budget, and the number that makes the budget FORECASTABLE rather than emergent. Without it the count is whatever the material happens to provoke: the placement law is sparse, so a clean note plants two bands and a resonant room plants nine, and nobody can answer \"will this fit?\" until it does not. With FBS senior (§9.3(b)) that discovery would happen at showtime, to the junior planter, silently. Declared instead, the whole sum is arithmetic an operator can read before a note is played: operator bands + FBS maxAutoBands + HRP maxAutoBands <= EQ_MAX_BANDS EIGHT — ONE CORRECTION PER VOICE at full polyphony (operator sizing, 2026-09-01). The detector's ceiling is HRP_MAX_VOICES voices, a guitar's six strings and a piano/string voicing's eight, and a budget below the voice count would decide by arithmetic which of the notes actually sounding may be corrected — a limit nobody could read off the desk. Scarcity is handled where it belongs instead: the candidates from every voice meet in ONE globally ranked list (spec §29) and the head of it is what gets planted. It is NOT a claim to seniority, and it is larger than FBS's six. Seniority is the ALLOCATION ORDER — `HrpPlanter` takes only `EQ_MAX_BANDS − others.length`, the remainder after the operator and every other machine — so a bigger junior default cannot reach a senior slot; it only means HRP asks for more of what is left.
|
|
63
|
+
"doc": "How many bands HRP may plant on ONE channel — its half of the machine budget, and the number that makes the budget FORECASTABLE rather than emergent. Without it the count is whatever the material happens to provoke: the placement law is sparse, so a clean note plants two bands and a resonant room plants nine, and nobody can answer \"will this fit?\" until it does not. With FBS senior (§9.3(b)) that discovery would happen at showtime, to the junior planter, silently. Declared instead, the whole sum is arithmetic an operator can read before a note is played: operator bands + FBS maxAutoBands + HRP maxAutoBands <= EQ_MAX_BANDS EIGHT — ONE CORRECTION PER VOICE at full polyphony (operator sizing, 2026-09-01). The detector's ceiling is HRP_MAX_VOICES voices, a guitar's six strings and a piano/string voicing's eight, and a budget below the voice count would decide by arithmetic which of the notes actually sounding may be corrected — a limit nobody could read off the desk. Scarcity is handled where it belongs instead: the candidates from every voice meet in ONE globally ranked list (spec §29) and the head of it is what gets planted. It is NOT a claim to seniority, and it is larger than FBS's six. Seniority is the ALLOCATION ORDER — `HrpPlanter` takes only `EQ_MAX_BANDS − others.length`, the remainder after the operator and every other machine — so a bigger junior default cannot reach a senior slot; it only means HRP asks for more of what is left. the engine's conformance test asserts both halves. The per-channel DEFAULT; the row's travel is HRP_AUTO_BANDS_RANGE, so a channel that needs more can have more, as an explicit decision with a visible cost.",
|
|
64
64
|
"unit": "",
|
|
65
65
|
"value": 8
|
|
66
66
|
}
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
],
|
|
60
60
|
"tables": {
|
|
61
61
|
"LIMITER_LIMITS": {
|
|
62
|
-
"doc": "The precision limiter's travels
|
|
62
|
+
"doc": "The precision limiter's travels, rendered into `omx_contract_limits.h` as `OMX_LIMITER_*` by the engine's limits generator, so `mix_limiter.h` reads them and never restates one (R-094). The ceiling is a TRUE peak in dBFS (the ×4 detector); the look-ahead sets the declared latency; the release is the envelope's time constant on the gain depth."
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"constants": {
|
|
4
4
|
"BUS_INPUT_CAP": {
|
|
5
5
|
"kind": "scalar",
|
|
6
|
-
"doc": "The input cap a summing bus can be sized to — **the engine's declared input ceiling**, read from `@freemixer/declarations` rather than re-typed here. A gig with more than this many inputs needs more than one engine node; below it a bus is sized to `min(N, BUS_INPUT_CAP)`. It was a literal 64 until 2026-09-15, said to mirror the engine's `MAX_BUS_INPUTS` — and it did, but that 64 was the PipeWire builtin mixer's single-tier fan-in (8 × 8), never the engine's bound: the native node has allocated `OMX_MAX_STRIPS` (128) strips all along. Two literals agreeing by hand is how the console came to refuse a 96-channel desk it could carry.
|
|
6
|
+
"doc": "The input cap a summing bus can be sized to — **the engine's declared input ceiling**, read from `@freemixer/declarations` rather than re-typed here. A gig with more than this many inputs needs more than one engine node; below it a bus is sized to `min(N, BUS_INPUT_CAP)`. It was a literal 64 until 2026-09-15, said to mirror the engine's `MAX_BUS_INPUTS` — and it did, but that 64 was the PipeWire builtin mixer's single-tier fan-in (8 × 8), never the engine's bound: the native node has allocated `OMX_MAX_STRIPS` (128) strips all along. Two literals agreeing by hand is how the console came to refuse a 96-channel desk it could carry. the engine's conformance test holds this to the C header; the console allocation design §9 carries the ruling and the measured cost of width.",
|
|
7
7
|
"unit": "",
|
|
8
8
|
"value": 128
|
|
9
9
|
}
|
package/data/kernels/reverb.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
{
|
|
5
5
|
"name": "plateModDepth",
|
|
6
6
|
"kind": "travel",
|
|
7
|
-
"doc": "PLATE's tank MODULATION DEPTH, in percent of Dattorro's own excursion (±8 samples at his 29 761 Hz tuning rate, scaled to the live rate the way the tank lengths are). 100 is the depth the plate has always run at, so the come-up is bit-identical to the plate before the field; 0 brings back the unmodulated tank's ring; 400 is the wide, chorused EMT-style swing. The rate stays 1 Hz. Only PLATE reads it
|
|
7
|
+
"doc": "PLATE's tank MODULATION DEPTH, in percent of Dattorro's own excursion (±8 samples at his 29 761 Hz tuning rate, scaled to the live rate the way the tank lengths are). 100 is the depth the plate has always run at, so the come-up is bit-identical to the plate before the field; 0 brings back the unmodulated tank's ring; 400 is the wide, chorused EMT-style swing. The rate stays 1 Hz. Only PLATE reads it.",
|
|
8
8
|
"travel": {
|
|
9
9
|
"min": 0,
|
|
10
10
|
"max": 400,
|
|
@@ -111,7 +111,7 @@
|
|
|
111
111
|
{
|
|
112
112
|
"name": "reverse",
|
|
113
113
|
"kind": "travel",
|
|
114
|
-
"doc": "REVERSE's MIRROR WINDOW — how long a slice of the wet is played backward, in milliseconds
|
|
114
|
+
"doc": "REVERSE's MIRROR WINDOW — how long a slice of the wet is played backward, in milliseconds. A DECLARED travel and never derived from `size`'s RT60: an RT60 of seconds cannot be buffered at 192 kHz, and a window silently clamped to fit is the silent-clamp defect. The ceiling is what `mix_reverb.h`'s pool budgets a ring for (`OMX_REVERB_REVERSE_MAX_MS`), so the console offers exactly the travel the kernel accepts — nothing wider, nothing narrower.",
|
|
115
115
|
"travel": {
|
|
116
116
|
"min": 50,
|
|
117
117
|
"max": 500,
|
package/data/kernels/rta.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"constants": {
|
|
4
4
|
"RTA_TARGET_BIN_HZ": {
|
|
5
5
|
"kind": "scalar",
|
|
6
|
-
"doc": "The RTA's target bin resolution — generated into `omx_contract_limits.h` as `OMX_RTA_TARGET_BIN_HZ`, which `mix_dsp.h` reads;
|
|
6
|
+
"doc": "The RTA's target bin resolution — generated into `omx_contract_limits.h` as `OMX_RTA_TARGET_BIN_HZ`, which `mix_dsp.h` reads; the engine's conformance test reads it back from the header.",
|
|
7
7
|
"unit": "Hz",
|
|
8
8
|
"value": 5.9
|
|
9
9
|
},
|
|
@@ -69,7 +69,7 @@
|
|
|
69
69
|
],
|
|
70
70
|
"tables": {
|
|
71
71
|
"TRANSIENT_LIMITS": {
|
|
72
|
-
"doc": "The legal range of each transient-designer field (engineering units), transient spec §3. Every kind comes up flat: no per-kind default differs.
|
|
72
|
+
"doc": "The legal range of each transient-designer field (engineering units), transient spec §3. Every kind comes up flat: no per-kind default differs. the engine's limits generator emits each as `OMX_TRANSIENT_<FIELD>_{MIN,MAX,DEFAULT}` for `mix_transient.h`'s resolve; the row publishes them on OPTIONS when it lands (issue #921)."
|
|
73
73
|
}
|
|
74
74
|
},
|
|
75
75
|
"constants": {
|
package/data/kernels/trim.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"name": "trimDb",
|
|
6
6
|
"kind": "travel",
|
|
7
7
|
"global": "TRIM_RANGE",
|
|
8
|
-
"doc": "The digital input trim, in dB: the console's fine head gain, applied first in a channel's lane as a click-free ramp from the last block's gain to this one (
|
|
8
|
+
"doc": "The digital input trim, in dB: the console's fine head gain, applied first in a channel's lane as a click-free ramp from the last block's gain to this one (the console's trim range, -24..+24 dB in 0.1 dB steps, spelled minDb/maxDb/stepDb there). It comes up at 0 dB, the trim a channel has when none is set. omx-dsp's trim face takes it as `trim_db`.",
|
|
9
9
|
"travel": {
|
|
10
10
|
"min": -24,
|
|
11
11
|
"max": 24,
|
package/data/rates.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "../schema/omx-contract.schema.json",
|
|
3
3
|
"STANDARD_SAMPLE_RATES": {
|
|
4
4
|
"kind": "list",
|
|
5
|
-
"doc": "The standard sample rates (Hz) the desk recognises — the pro-audio superset. One source of truth for the clock controller's `clock.allowed-rates` seed, the force row's validation ceiling and the device-rate probe fallback. What the operator is OFFERED is always the DEVICE's own `supportedRates`
|
|
5
|
+
"doc": "The standard sample rates (Hz) the desk recognises — the pro-audio superset. One source of truth for the clock controller's `clock.allowed-rates` seed, the force row's validation ceiling and the device-rate probe fallback. What the operator is OFFERED is always the DEVICE's own `supportedRates` — this is the ceiling a write is refused by, never a menu.",
|
|
6
6
|
"unit": "Hz",
|
|
7
7
|
"values": [
|
|
8
8
|
44100,
|
|
@@ -255,13 +255,13 @@ export declare const COMP_KINDS: readonly ["comp", "limiter"];
|
|
|
255
255
|
export declare const DETECTOR_OVERSAMPLINGS: readonly ["auto", "off", "x4"];
|
|
256
256
|
|
|
257
257
|
/**
|
|
258
|
-
* Where the compressor's detector listens: `feedforward` hears the slot's input (or its key), `feedback` hears the slot's own pre-make-up output DYN_FB_LOOP_DELAY_SAMPLES late, through one envelope stage, and a keyed slot stays feed-forward (omx-dsp's OMX_DYN_TOPOLOGY_FEEDFORWARD 0 and _FEEDBACK 1, in that order; the set is named for its control, so C spells them OMX_DETECTOR_TOPOLOGY_*). The console's comp row carries it (`detectorTopology`,
|
|
258
|
+
* Where the compressor's detector listens: `feedforward` hears the slot's input (or its key), `feedback` hears the slot's own pre-make-up output DYN_FB_LOOP_DELAY_SAMPLES late, through one envelope stage, and a keyed slot stays feed-forward (omx-dsp's OMX_DYN_TOPOLOGY_FEEDFORWARD 0 and _FEEDBACK 1, in that order; the set is named for its control, so C spells them OMX_DETECTOR_TOPOLOGY_*). The console's comp row carries it (`detectorTopology`, the SSL bus compressor design §3a) and comes up `feedforward`, so a zeroed atom is the compressor every slot runs.
|
|
259
259
|
* @see data/kernels/comp.json
|
|
260
260
|
*/
|
|
261
261
|
export declare const DETECTOR_TOPOLOGY: readonly ["feedforward", "feedback"];
|
|
262
262
|
|
|
263
263
|
/**
|
|
264
|
-
* The program-dependent release's model constants — the LA-2A's opto cell as DATA (
|
|
264
|
+
* The program-dependent release's model constants — the LA-2A's opto cell as DATA (compressor models design §3b). `chargeMs`/`dischargeMs` are the word's memory constants, shared by every profile; each profile's `fastMs`, `slowMinMs`, `slowMaxMs` and `share` fit the unit's published two-stage recovery. Not operator controls: generated into `omx_contract_limits.h` as `OMX_PROGRAM_RELEASE_*`, which libomxdsp's `omx_env_program_release` reads.
|
|
265
265
|
* @see data/kernels/comp.json
|
|
266
266
|
*/
|
|
267
267
|
export declare const PROGRAM_RELEASE: {
|
|
@@ -381,13 +381,13 @@ export declare const DEESS_RELEASE_RANGE: {
|
|
|
381
381
|
export declare const DEESS_MODES: readonly ["split", "wideband"];
|
|
382
382
|
|
|
383
383
|
/**
|
|
384
|
-
* The knee, in dB — a CONSTANT of the stage and not a row field
|
|
384
|
+
* The knee, in dB — a CONSTANT of the stage and not a row field: a de-esser without a soft knee latches audibly on the first sibilant of a phrase, and no other value of this number is a de-esser anyone would dial. The controller pushes it to the node and this is the same number; a second spelling would be a picture that disagrees with the audio about where the reduction starts.
|
|
385
385
|
* @see data/kernels/deesser.json
|
|
386
386
|
*/
|
|
387
387
|
export declare const DEESS_KNEE_DB: 6;
|
|
388
388
|
|
|
389
389
|
/**
|
|
390
|
-
* The FX delay's time travel. `max` is the NATIVE ring's ceiling — the same number as `OMX_FXDELAY_MAX_MS` in `omx_delay.h`, pinned to it by
|
|
390
|
+
* The FX delay's time travel. `max` is the NATIVE ring's ceiling — the same number as `OMX_FXDELAY_MAX_MS` in `omx_delay.h`, pinned to it by the engine's conformance test. Distinct from the per-route ALIGNMENT delay (`OUTPUT_DELAY_RANGE`, 1 s, `OMX_DELAY_MAX_MS`): one is a musical echo with feedback and mix, the other is a pure latency. Two facts, two rings, two ceilings — sharing the word "delay" is why they keep being confused for each other.
|
|
391
391
|
* @see data/kernels/delay.json
|
|
392
392
|
*/
|
|
393
393
|
export declare const FX_DELAY_TIME_RANGE: {
|
|
@@ -413,7 +413,7 @@ export declare const FX_DELAY_FEEDBACK_RANGE: {
|
|
|
413
413
|
};
|
|
414
414
|
|
|
415
415
|
/**
|
|
416
|
-
* The FX delay's TONE — a NORMALIZED_RANGE instance with its own come-up value, matching
|
|
416
|
+
* The FX delay's TONE — a NORMALIZED_RANGE instance with its own come-up value, matching the console's delay default tone. See REVERB_SIZE_RANGE for why this is a named constant rather than a default on the shared shape.
|
|
417
417
|
* @see data/kernels/delay.json
|
|
418
418
|
*/
|
|
419
419
|
export declare const DELAY_TONE_RANGE: {
|
|
@@ -448,7 +448,7 @@ export declare const DELAY_MIX_RANGE: {
|
|
|
448
448
|
export declare const DELAY_PINGPONGS: readonly ["off", "on"];
|
|
449
449
|
|
|
450
450
|
/**
|
|
451
|
-
* The FX delay's PING-PONG come-up value — a toggle, so it has no travel, only this. Declared here rather than as a literal in the
|
|
451
|
+
* The FX delay's PING-PONG come-up value — a toggle, so it has no travel, only this. Declared here rather than as a literal in the console's delay default state (which now reads it) so the DPF plugin generator (omx-plugins, DPF plugin design §3a) reads the same fact the desk seeds a fresh strip with.
|
|
452
452
|
* @see data/kernels/delay.json
|
|
453
453
|
*/
|
|
454
454
|
export declare const FX_DELAY_PINGPONG_DEFAULT: false;
|
|
@@ -548,6 +548,12 @@ export declare const DRIVE_STEREO_LINKS: readonly ["off", "on"];
|
|
|
548
548
|
*/
|
|
549
549
|
export declare const DRIVE_HF_ROLLOFFS: readonly [0, 12000, 16000];
|
|
550
550
|
|
|
551
|
+
/**
|
|
552
|
+
* The drive's OVERSAMPLING factor: the shaper runs inside the console's one oversampler at 1x, 2x or 4x, and the id is the factor (`omx_drive.h`'s `omx_drive_factor_of` member set, `struct omx_drive.os_factor`). A field of the console's drive row (`DriveState.oversample`, the console's DRIVE_OVERSAMPLE_FACTORS; the set is named for its control), 4 at come-up there and in omx-dsp's drive face (OMX_DRIVE_INSTANCE_FACTOR, the oversampler's largest).
|
|
553
|
+
* @see data/kernels/drive.json
|
|
554
|
+
*/
|
|
555
|
+
export declare const DRIVE_OVERSAMPLES: readonly [1, 2, 4];
|
|
556
|
+
|
|
551
557
|
/**
|
|
552
558
|
* The bias at `character = +1`, in the SHAPER's own input units — `OMX_DRIVE_BIAS_MAX`. DERIVED, not chosen (§4b). In the saturating limit every knee tends to `sgn`, the output is a rectangular wave of duty `d = ½ + asin(b)/π`, and its `n`th harmonic goes as `sin(nπd)/n` — so `|H2|` is maximal at `d = ¾`, which is `b = sin(π/4) = 1/√2` exactly. Measured too: the H2-maximising bias for a full-scale sine at unity drive is 0.712 (soft), 0.658 (tape), 0.645 (tube), and this one value costs 0.000 / 0.035 / 0.088 dB of H2 against each curve's own optimum. ONE normalised bias for all three knees, not three.
|
|
553
559
|
* @see data/kernels/drive.json
|
|
@@ -612,7 +618,7 @@ export declare const EQ_FREQ_RANGE: {
|
|
|
612
618
|
};
|
|
613
619
|
|
|
614
620
|
/**
|
|
615
|
-
* The parametric-band gain travel, in dB. The ± scalar `clampEqGain` enforces is READ off this (
|
|
621
|
+
* The parametric-band gain travel, in dB. The ± scalar `clampEqGain` enforces is READ off this (the engine derives its gain limit from `max`), so the bound is stated once and a surface cannot draw a wider knob than the clamp will honour.
|
|
616
622
|
* @see data/kernels/eq.json
|
|
617
623
|
*/
|
|
618
624
|
export declare const EQ_GAIN_RANGE: {
|
|
@@ -651,7 +657,7 @@ export declare const EQ_NOTCH_Q_RANGE: {
|
|
|
651
657
|
export declare const EQ_BAND_ONS: readonly ["off", "on"];
|
|
652
658
|
|
|
653
659
|
/**
|
|
654
|
-
* The maximum number of parametric bands a channel EQ may hold — the operator can add up to this many. Generated into `omx_contract_limits.h` as `OMX_EQ_MAX_BANDS`, which `omx_biquad.h` reads (
|
|
660
|
+
* The maximum number of parametric bands a channel EQ may hold — the operator can add up to this many. Generated into `omx_contract_limits.h` as `OMX_EQ_MAX_BANDS`, which `omx_biquad.h` reads (the engine's conformance test reads the header): the native lane allocates exactly this many biquad slots per channel and silently clamps above it, so the model, the wire, and the DSP agree by test, not by memory.
|
|
655
661
|
* @see data/kernels/eq.json
|
|
656
662
|
*/
|
|
657
663
|
export declare const EQ_MAX_BANDS: 24;
|
|
@@ -846,7 +852,7 @@ export declare const DEFAULT_THRESHOLDS: {
|
|
|
846
852
|
};
|
|
847
853
|
|
|
848
854
|
/**
|
|
849
|
-
* THE NOTCH DEPTH LAW: the deepest cut any machine planter may propose from one reading, in dB. A number, not a literal at the call site, because two planters now lean on it. FBS derives a candidate's depth from the peak-to-average ratio around its bin and stops here; Room Analysis derives a mode's depth from its height above the median curve and is held to the SAME ceiling (
|
|
855
|
+
* THE NOTCH DEPTH LAW: the deepest cut any machine planter may propose from one reading, in dB. A number, not a literal at the call site, because two planters now lean on it. FBS derives a candidate's depth from the peak-to-average ratio around its bin and stops here; Room Analysis derives a mode's depth from its height above the median curve and is held to the SAME ceiling (the room-analysis design §4 — "never more than the FBS notch depth law"). Written twice as `18` those two bounds would be equal by coincidence and could drift apart in silence. It is a CEILING ON THE PROPOSAL, not the final gain: a band that lands as a rampable BELL is bounded again by `EQ_GAIN_RANGE`, which is tighter. A planter must honour both and REPORT when either bit, never quietly deliver a shallower cut than it was asked for.
|
|
850
856
|
* @see data/kernels/fbs.json
|
|
851
857
|
*/
|
|
852
858
|
export declare const FBS_MAX_NOTCH_DEPTH_DB: 18;
|
|
@@ -1012,6 +1018,25 @@ export declare const GATE_LIMITS: {
|
|
|
1012
1018
|
};
|
|
1013
1019
|
};
|
|
1014
1020
|
|
|
1021
|
+
/**
|
|
1022
|
+
* The travel of each edge of the keyed gate's detector filter, 0 (off) up to 20 kHz in whole Hz, as the console's `/channel/{kind}/{index}/gate/key` row serves them (the console's GATE_KEY_LIMITS). A property of the detector filter, not of any desk: no come-up value is declared.
|
|
1023
|
+
* @see data/kernels/gate.json
|
|
1024
|
+
*/
|
|
1025
|
+
export declare const GATE_KEY_LIMITS: {
|
|
1026
|
+
readonly hpHz: {
|
|
1027
|
+
readonly min: 0;
|
|
1028
|
+
readonly max: 20000;
|
|
1029
|
+
readonly step: 1;
|
|
1030
|
+
readonly unit: "Hz";
|
|
1031
|
+
};
|
|
1032
|
+
readonly lpHz: {
|
|
1033
|
+
readonly min: 0;
|
|
1034
|
+
readonly max: 20000;
|
|
1035
|
+
readonly step: 1;
|
|
1036
|
+
readonly unit: "Hz";
|
|
1037
|
+
};
|
|
1038
|
+
};
|
|
1039
|
+
|
|
1015
1040
|
/**
|
|
1016
1041
|
* The generator kinds, in surface order: its position is the integer omx-dsp's omx_gen_fill takes as its kind (OMX_GEN_OSC, OMX_GEN_WHITE, OMX_GEN_PINK).
|
|
1017
1042
|
* @see data/kernels/generator.json
|
|
@@ -1075,7 +1100,7 @@ export declare const HRP_AMOUNT_RANGE: {
|
|
|
1075
1100
|
export declare const HRP_MAX_CUT_DB: 6;
|
|
1076
1101
|
|
|
1077
1102
|
/**
|
|
1078
|
-
* How many simultaneous musical voices the detector may report on one channel. PINNED to `OMX_HRP_MAX_VOICES` in `pipewire-native/src/hrp_pitch.h` — the C voice set is a FIXED-SIZE array, so a TS number above the macro promises voices the analyser structurally cannot return, and one below it silently drops notes the C already found.
|
|
1103
|
+
* How many simultaneous musical voices the detector may report on one channel. PINNED to `OMX_HRP_MAX_VOICES` in `pipewire-native/src/hrp_pitch.h` — the C voice set is a FIXED-SIZE array, so a TS number above the macro promises voices the analyser structurally cannot return, and one below it silently drops notes the C already found. the engine's conformance test reads the header and holds the pair equal. EIGHT (operator sizing, 2026-09-01): a guitar sounds six strings, a piano or string-section voicing sits at eight. It is a SEARCH ceiling, not a cost — the detector abandons a round as soon as no credible candidate remains, so monophonic material costs what it always did.
|
|
1079
1104
|
* @see data/kernels/hrp.json
|
|
1080
1105
|
*/
|
|
1081
1106
|
export declare const HRP_MAX_VOICES: 8;
|
|
@@ -1111,13 +1136,13 @@ export declare const HRP_COLLISION_CENTS: 100;
|
|
|
1111
1136
|
export declare const HRP_ATTRIBUTION_CENTS: 60;
|
|
1112
1137
|
|
|
1113
1138
|
/**
|
|
1114
|
-
* How many bands HRP may plant on ONE channel — its half of the machine budget, and the number that makes the budget FORECASTABLE rather than emergent. Without it the count is whatever the material happens to provoke: the placement law is sparse, so a clean note plants two bands and a resonant room plants nine, and nobody can answer "will this fit?" until it does not. With FBS senior (§9.3(b)) that discovery would happen at showtime, to the junior planter, silently. Declared instead, the whole sum is arithmetic an operator can read before a note is played: operator bands + FBS maxAutoBands + HRP maxAutoBands <= EQ_MAX_BANDS EIGHT — ONE CORRECTION PER VOICE at full polyphony (operator sizing, 2026-09-01). The detector's ceiling is HRP_MAX_VOICES voices, a guitar's six strings and a piano/string voicing's eight, and a budget below the voice count would decide by arithmetic which of the notes actually sounding may be corrected — a limit nobody could read off the desk. Scarcity is handled where it belongs instead: the candidates from every voice meet in ONE globally ranked list (spec §29) and the head of it is what gets planted. It is NOT a claim to seniority, and it is larger than FBS's six. Seniority is the ALLOCATION ORDER — `HrpPlanter` takes only `EQ_MAX_BANDS − others.length`, the remainder after the operator and every other machine — so a bigger junior default cannot reach a senior slot; it only means HRP asks for more of what is left.
|
|
1139
|
+
* How many bands HRP may plant on ONE channel — its half of the machine budget, and the number that makes the budget FORECASTABLE rather than emergent. Without it the count is whatever the material happens to provoke: the placement law is sparse, so a clean note plants two bands and a resonant room plants nine, and nobody can answer "will this fit?" until it does not. With FBS senior (§9.3(b)) that discovery would happen at showtime, to the junior planter, silently. Declared instead, the whole sum is arithmetic an operator can read before a note is played: operator bands + FBS maxAutoBands + HRP maxAutoBands <= EQ_MAX_BANDS EIGHT — ONE CORRECTION PER VOICE at full polyphony (operator sizing, 2026-09-01). The detector's ceiling is HRP_MAX_VOICES voices, a guitar's six strings and a piano/string voicing's eight, and a budget below the voice count would decide by arithmetic which of the notes actually sounding may be corrected — a limit nobody could read off the desk. Scarcity is handled where it belongs instead: the candidates from every voice meet in ONE globally ranked list (spec §29) and the head of it is what gets planted. It is NOT a claim to seniority, and it is larger than FBS's six. Seniority is the ALLOCATION ORDER — `HrpPlanter` takes only `EQ_MAX_BANDS − others.length`, the remainder after the operator and every other machine — so a bigger junior default cannot reach a senior slot; it only means HRP asks for more of what is left. the engine's conformance test asserts both halves. The per-channel DEFAULT; the row's travel is HRP_AUTO_BANDS_RANGE, so a channel that needs more can have more, as an explicit decision with a visible cost.
|
|
1115
1140
|
* @see data/kernels/hrp.json
|
|
1116
1141
|
*/
|
|
1117
1142
|
export declare const HRP_DEFAULT_MAX_AUTO_BANDS: 8;
|
|
1118
1143
|
|
|
1119
1144
|
/**
|
|
1120
|
-
* The precision limiter's travels
|
|
1145
|
+
* The precision limiter's travels, rendered into `omx_contract_limits.h` as `OMX_LIMITER_*` by the engine's limits generator, so `mix_limiter.h` reads them and never restates one (R-094). The ceiling is a TRUE peak in dBFS (the ×4 detector); the look-ahead sets the declared latency; the release is the envelope's time constant on the gain depth.
|
|
1121
1146
|
* @see data/kernels/limiter.json
|
|
1122
1147
|
*/
|
|
1123
1148
|
export declare const LIMITER_LIMITS: {
|
|
@@ -1148,7 +1173,7 @@ export declare const LIMITER_LIMITS: {
|
|
|
1148
1173
|
};
|
|
1149
1174
|
|
|
1150
1175
|
/**
|
|
1151
|
-
* The input cap a summing bus can be sized to — **the engine's declared input ceiling**, read from `@freemixer/declarations` rather than re-typed here. A gig with more than this many inputs needs more than one engine node; below it a bus is sized to `min(N, BUS_INPUT_CAP)`. It was a literal 64 until 2026-09-15, said to mirror the engine's `MAX_BUS_INPUTS` — and it did, but that 64 was the PipeWire builtin mixer's single-tier fan-in (8 × 8), never the engine's bound: the native node has allocated `OMX_MAX_STRIPS` (128) strips all along. Two literals agreeing by hand is how the console came to refuse a 96-channel desk it could carry.
|
|
1176
|
+
* The input cap a summing bus can be sized to — **the engine's declared input ceiling**, read from `@freemixer/declarations` rather than re-typed here. A gig with more than this many inputs needs more than one engine node; below it a bus is sized to `min(N, BUS_INPUT_CAP)`. It was a literal 64 until 2026-09-15, said to mirror the engine's `MAX_BUS_INPUTS` — and it did, but that 64 was the PipeWire builtin mixer's single-tier fan-in (8 × 8), never the engine's bound: the native node has allocated `OMX_MAX_STRIPS` (128) strips all along. Two literals agreeing by hand is how the console came to refuse a 96-channel desk it could carry. the engine's conformance test holds this to the C header; the console allocation design §9 carries the ruling and the measured cost of width.
|
|
1152
1177
|
* @see data/kernels/mixmatrix.json
|
|
1153
1178
|
*/
|
|
1154
1179
|
export declare const BUS_INPUT_CAP: 128;
|
|
@@ -1323,7 +1348,7 @@ export declare const PITCH_KERNEL: {
|
|
|
1323
1348
|
};
|
|
1324
1349
|
|
|
1325
1350
|
/**
|
|
1326
|
-
* PLATE's tank MODULATION DEPTH, in percent of Dattorro's own excursion (±8 samples at his 29 761 Hz tuning rate, scaled to the live rate the way the tank lengths are). 100 is the depth the plate has always run at, so the come-up is bit-identical to the plate before the field; 0 brings back the unmodulated tank's ring; 400 is the wide, chorused EMT-style swing. The rate stays 1 Hz. Only PLATE reads it
|
|
1351
|
+
* PLATE's tank MODULATION DEPTH, in percent of Dattorro's own excursion (±8 samples at his 29 761 Hz tuning rate, scaled to the live rate the way the tank lengths are). 100 is the depth the plate has always run at, so the come-up is bit-identical to the plate before the field; 0 brings back the unmodulated tank's ring; 400 is the wide, chorused EMT-style swing. The rate stays 1 Hz. Only PLATE reads it.
|
|
1327
1352
|
* @see data/kernels/reverb.json
|
|
1328
1353
|
*/
|
|
1329
1354
|
export declare const REVERB_PLATE_MOD_DEPTH_RANGE: {
|
|
@@ -1430,7 +1455,7 @@ export declare const REVERB_HIGHCUT_RANGE: {
|
|
|
1430
1455
|
};
|
|
1431
1456
|
|
|
1432
1457
|
/**
|
|
1433
|
-
* REVERSE's MIRROR WINDOW — how long a slice of the wet is played backward, in milliseconds
|
|
1458
|
+
* REVERSE's MIRROR WINDOW — how long a slice of the wet is played backward, in milliseconds. A DECLARED travel and never derived from `size`'s RT60: an RT60 of seconds cannot be buffered at 192 kHz, and a window silently clamped to fit is the silent-clamp defect. The ceiling is what `mix_reverb.h`'s pool budgets a ring for (`OMX_REVERB_REVERSE_MAX_MS`), so the console offers exactly the travel the kernel accepts — nothing wider, nothing narrower.
|
|
1434
1459
|
* @see data/kernels/reverb.json
|
|
1435
1460
|
*/
|
|
1436
1461
|
export declare const REVERB_REVERSE_RANGE: {
|
|
@@ -1726,7 +1751,7 @@ export declare const ROTARY_STOP_EPS: 0.0001;
|
|
|
1726
1751
|
export declare const ROTARY_RING_FLOATS: 256;
|
|
1727
1752
|
|
|
1728
1753
|
/**
|
|
1729
|
-
* The RTA's target bin resolution — generated into `omx_contract_limits.h` as `OMX_RTA_TARGET_BIN_HZ`, which `mix_dsp.h` reads;
|
|
1754
|
+
* The RTA's target bin resolution — generated into `omx_contract_limits.h` as `OMX_RTA_TARGET_BIN_HZ`, which `mix_dsp.h` reads; the engine's conformance test reads it back from the header.
|
|
1730
1755
|
* @see data/kernels/rta.json
|
|
1731
1756
|
*/
|
|
1732
1757
|
export declare const RTA_TARGET_BIN_HZ: 5.9;
|
|
@@ -1762,7 +1787,7 @@ export declare const SRC_ROLLOFF: 0.92;
|
|
|
1762
1787
|
export declare const SRC_MAX_L: 1024;
|
|
1763
1788
|
|
|
1764
1789
|
/**
|
|
1765
|
-
* The legal range of each transient-designer field (engineering units), transient spec §3. Every kind comes up flat: no per-kind default differs.
|
|
1790
|
+
* The legal range of each transient-designer field (engineering units), transient spec §3. Every kind comes up flat: no per-kind default differs. the engine's limits generator emits each as `OMX_TRANSIENT_<FIELD>_{MIN,MAX,DEFAULT}` for `mix_transient.h`'s resolve; the row publishes them on OPTIONS when it lands (issue #921).
|
|
1766
1791
|
* @see data/kernels/transient.json
|
|
1767
1792
|
*/
|
|
1768
1793
|
export declare const TRANSIENT_LIMITS: {
|
|
@@ -1909,7 +1934,7 @@ export declare const TREMOLO_TRAVELS: {
|
|
|
1909
1934
|
};
|
|
1910
1935
|
|
|
1911
1936
|
/**
|
|
1912
|
-
* The digital input trim, in dB: the console's fine head gain, applied first in a channel's lane as a click-free ramp from the last block's gain to this one (
|
|
1937
|
+
* The digital input trim, in dB: the console's fine head gain, applied first in a channel's lane as a click-free ramp from the last block's gain to this one (the console's trim range, -24..+24 dB in 0.1 dB steps, spelled minDb/maxDb/stepDb there). It comes up at 0 dB, the trim a channel has when none is set. omx-dsp's trim face takes it as `trim_db`.
|
|
1913
1938
|
* @see data/kernels/trim.json
|
|
1914
1939
|
*/
|
|
1915
1940
|
export declare const TRIM_RANGE: {
|
|
@@ -2075,7 +2100,7 @@ export declare const EQ_CONTINUOUS_TRAVELS: {
|
|
|
2075
2100
|
export declare const READOUT_RATE_HZ: 50;
|
|
2076
2101
|
|
|
2077
2102
|
/**
|
|
2078
|
-
* The standard sample rates (Hz) the desk recognises — the pro-audio superset. One source of truth for the clock controller's `clock.allowed-rates` seed, the force row's validation ceiling and the device-rate probe fallback. What the operator is OFFERED is always the DEVICE's own `supportedRates`
|
|
2103
|
+
* The standard sample rates (Hz) the desk recognises — the pro-audio superset. One source of truth for the clock controller's `clock.allowed-rates` seed, the force row's validation ceiling and the device-rate probe fallback. What the operator is OFFERED is always the DEVICE's own `supportedRates` — this is the ceiling a write is refused by, never a menu.
|
|
2079
2104
|
* @see data/rates.json
|
|
2080
2105
|
*/
|
|
2081
2106
|
export declare const STANDARD_SAMPLE_RATES: readonly [44100, 48000, 88200, 96000, 176400, 192000];
|
package/dist/ts/omx-contract.js
CHANGED
|
@@ -265,7 +265,7 @@ export const DETECTOR_OVERSAMPLINGS = [
|
|
|
265
265
|
];
|
|
266
266
|
|
|
267
267
|
/**
|
|
268
|
-
* Where the compressor's detector listens: `feedforward` hears the slot's input (or its key), `feedback` hears the slot's own pre-make-up output DYN_FB_LOOP_DELAY_SAMPLES late, through one envelope stage, and a keyed slot stays feed-forward (omx-dsp's OMX_DYN_TOPOLOGY_FEEDFORWARD 0 and _FEEDBACK 1, in that order; the set is named for its control, so C spells them OMX_DETECTOR_TOPOLOGY_*). The console's comp row carries it (`detectorTopology`,
|
|
268
|
+
* Where the compressor's detector listens: `feedforward` hears the slot's input (or its key), `feedback` hears the slot's own pre-make-up output DYN_FB_LOOP_DELAY_SAMPLES late, through one envelope stage, and a keyed slot stays feed-forward (omx-dsp's OMX_DYN_TOPOLOGY_FEEDFORWARD 0 and _FEEDBACK 1, in that order; the set is named for its control, so C spells them OMX_DETECTOR_TOPOLOGY_*). The console's comp row carries it (`detectorTopology`, the SSL bus compressor design §3a) and comes up `feedforward`, so a zeroed atom is the compressor every slot runs.
|
|
269
269
|
* @see data/kernels/comp.json
|
|
270
270
|
*/
|
|
271
271
|
export const DETECTOR_TOPOLOGY = [
|
|
@@ -274,7 +274,7 @@ export const DETECTOR_TOPOLOGY = [
|
|
|
274
274
|
];
|
|
275
275
|
|
|
276
276
|
/**
|
|
277
|
-
* The program-dependent release's model constants — the LA-2A's opto cell as DATA (
|
|
277
|
+
* The program-dependent release's model constants — the LA-2A's opto cell as DATA (compressor models design §3b). `chargeMs`/`dischargeMs` are the word's memory constants, shared by every profile; each profile's `fastMs`, `slowMinMs`, `slowMaxMs` and `share` fit the unit's published two-stage recovery. Not operator controls: generated into `omx_contract_limits.h` as `OMX_PROGRAM_RELEASE_*`, which libomxdsp's `omx_env_program_release` reads.
|
|
278
278
|
* @see data/kernels/comp.json
|
|
279
279
|
*/
|
|
280
280
|
export const PROGRAM_RELEASE = {
|
|
@@ -397,13 +397,13 @@ export const DEESS_MODES = [
|
|
|
397
397
|
];
|
|
398
398
|
|
|
399
399
|
/**
|
|
400
|
-
* The knee, in dB — a CONSTANT of the stage and not a row field
|
|
400
|
+
* The knee, in dB — a CONSTANT of the stage and not a row field: a de-esser without a soft knee latches audibly on the first sibilant of a phrase, and no other value of this number is a de-esser anyone would dial. The controller pushes it to the node and this is the same number; a second spelling would be a picture that disagrees with the audio about where the reduction starts.
|
|
401
401
|
* @see data/kernels/deesser.json
|
|
402
402
|
*/
|
|
403
403
|
export const DEESS_KNEE_DB = 6;
|
|
404
404
|
|
|
405
405
|
/**
|
|
406
|
-
* The FX delay's time travel. `max` is the NATIVE ring's ceiling — the same number as `OMX_FXDELAY_MAX_MS` in `omx_delay.h`, pinned to it by
|
|
406
|
+
* The FX delay's time travel. `max` is the NATIVE ring's ceiling — the same number as `OMX_FXDELAY_MAX_MS` in `omx_delay.h`, pinned to it by the engine's conformance test. Distinct from the per-route ALIGNMENT delay (`OUTPUT_DELAY_RANGE`, 1 s, `OMX_DELAY_MAX_MS`): one is a musical echo with feedback and mix, the other is a pure latency. Two facts, two rings, two ceilings — sharing the word "delay" is why they keep being confused for each other.
|
|
407
407
|
* @see data/kernels/delay.json
|
|
408
408
|
*/
|
|
409
409
|
export const FX_DELAY_TIME_RANGE = {
|
|
@@ -429,7 +429,7 @@ export const FX_DELAY_FEEDBACK_RANGE = {
|
|
|
429
429
|
};
|
|
430
430
|
|
|
431
431
|
/**
|
|
432
|
-
* The FX delay's TONE — a NORMALIZED_RANGE instance with its own come-up value, matching
|
|
432
|
+
* The FX delay's TONE — a NORMALIZED_RANGE instance with its own come-up value, matching the console's delay default tone. See REVERB_SIZE_RANGE for why this is a named constant rather than a default on the shared shape.
|
|
433
433
|
* @see data/kernels/delay.json
|
|
434
434
|
*/
|
|
435
435
|
export const DELAY_TONE_RANGE = {
|
|
@@ -467,7 +467,7 @@ export const DELAY_PINGPONGS = [
|
|
|
467
467
|
];
|
|
468
468
|
|
|
469
469
|
/**
|
|
470
|
-
* The FX delay's PING-PONG come-up value — a toggle, so it has no travel, only this. Declared here rather than as a literal in the
|
|
470
|
+
* The FX delay's PING-PONG come-up value — a toggle, so it has no travel, only this. Declared here rather than as a literal in the console's delay default state (which now reads it) so the DPF plugin generator (omx-plugins, DPF plugin design §3a) reads the same fact the desk seeds a fresh strip with.
|
|
471
471
|
* @see data/kernels/delay.json
|
|
472
472
|
*/
|
|
473
473
|
export const FX_DELAY_PINGPONG_DEFAULT = false;
|
|
@@ -587,6 +587,16 @@ export const DRIVE_HF_ROLLOFFS = [
|
|
|
587
587
|
16000
|
|
588
588
|
];
|
|
589
589
|
|
|
590
|
+
/**
|
|
591
|
+
* The drive's OVERSAMPLING factor: the shaper runs inside the console's one oversampler at 1x, 2x or 4x, and the id is the factor (`omx_drive.h`'s `omx_drive_factor_of` member set, `struct omx_drive.os_factor`). A field of the console's drive row (`DriveState.oversample`, the console's DRIVE_OVERSAMPLE_FACTORS; the set is named for its control), 4 at come-up there and in omx-dsp's drive face (OMX_DRIVE_INSTANCE_FACTOR, the oversampler's largest).
|
|
592
|
+
* @see data/kernels/drive.json
|
|
593
|
+
*/
|
|
594
|
+
export const DRIVE_OVERSAMPLES = [
|
|
595
|
+
1,
|
|
596
|
+
2,
|
|
597
|
+
4
|
|
598
|
+
];
|
|
599
|
+
|
|
590
600
|
/**
|
|
591
601
|
* The bias at `character = +1`, in the SHAPER's own input units — `OMX_DRIVE_BIAS_MAX`. DERIVED, not chosen (§4b). In the saturating limit every knee tends to `sgn`, the output is a rectangular wave of duty `d = ½ + asin(b)/π`, and its `n`th harmonic goes as `sin(nπd)/n` — so `|H2|` is maximal at `d = ¾`, which is `b = sin(π/4) = 1/√2` exactly. Measured too: the H2-maximising bias for a full-scale sine at unity drive is 0.712 (soft), 0.658 (tape), 0.645 (tube), and this one value costs 0.000 / 0.035 / 0.088 dB of H2 against each curve's own optimum. ONE normalised bias for all three knees, not three.
|
|
592
602
|
* @see data/kernels/drive.json
|
|
@@ -667,7 +677,7 @@ export const EQ_FREQ_RANGE = {
|
|
|
667
677
|
};
|
|
668
678
|
|
|
669
679
|
/**
|
|
670
|
-
* The parametric-band gain travel, in dB. The ± scalar `clampEqGain` enforces is READ off this (
|
|
680
|
+
* The parametric-band gain travel, in dB. The ± scalar `clampEqGain` enforces is READ off this (the engine derives its gain limit from `max`), so the bound is stated once and a surface cannot draw a wider knob than the clamp will honour.
|
|
671
681
|
* @see data/kernels/eq.json
|
|
672
682
|
*/
|
|
673
683
|
export const EQ_GAIN_RANGE = {
|
|
@@ -709,7 +719,7 @@ export const EQ_BAND_ONS = [
|
|
|
709
719
|
];
|
|
710
720
|
|
|
711
721
|
/**
|
|
712
|
-
* The maximum number of parametric bands a channel EQ may hold — the operator can add up to this many. Generated into `omx_contract_limits.h` as `OMX_EQ_MAX_BANDS`, which `omx_biquad.h` reads (
|
|
722
|
+
* The maximum number of parametric bands a channel EQ may hold — the operator can add up to this many. Generated into `omx_contract_limits.h` as `OMX_EQ_MAX_BANDS`, which `omx_biquad.h` reads (the engine's conformance test reads the header): the native lane allocates exactly this many biquad slots per channel and silently clamps above it, so the model, the wire, and the DSP agree by test, not by memory.
|
|
713
723
|
* @see data/kernels/eq.json
|
|
714
724
|
*/
|
|
715
725
|
export const EQ_MAX_BANDS = 24;
|
|
@@ -1003,7 +1013,7 @@ export const DEFAULT_THRESHOLDS = {
|
|
|
1003
1013
|
};
|
|
1004
1014
|
|
|
1005
1015
|
/**
|
|
1006
|
-
* THE NOTCH DEPTH LAW: the deepest cut any machine planter may propose from one reading, in dB. A number, not a literal at the call site, because two planters now lean on it. FBS derives a candidate's depth from the peak-to-average ratio around its bin and stops here; Room Analysis derives a mode's depth from its height above the median curve and is held to the SAME ceiling (
|
|
1016
|
+
* THE NOTCH DEPTH LAW: the deepest cut any machine planter may propose from one reading, in dB. A number, not a literal at the call site, because two planters now lean on it. FBS derives a candidate's depth from the peak-to-average ratio around its bin and stops here; Room Analysis derives a mode's depth from its height above the median curve and is held to the SAME ceiling (the room-analysis design §4 — "never more than the FBS notch depth law"). Written twice as `18` those two bounds would be equal by coincidence and could drift apart in silence. It is a CEILING ON THE PROPOSAL, not the final gain: a band that lands as a rampable BELL is bounded again by `EQ_GAIN_RANGE`, which is tighter. A planter must honour both and REPORT when either bit, never quietly deliver a shallower cut than it was asked for.
|
|
1007
1017
|
* @see data/kernels/fbs.json
|
|
1008
1018
|
*/
|
|
1009
1019
|
export const FBS_MAX_NOTCH_DEPTH_DB = 18;
|
|
@@ -1172,6 +1182,25 @@ export const GATE_LIMITS = {
|
|
|
1172
1182
|
}
|
|
1173
1183
|
};
|
|
1174
1184
|
|
|
1185
|
+
/**
|
|
1186
|
+
* The travel of each edge of the keyed gate's detector filter, 0 (off) up to 20 kHz in whole Hz, as the console's `/channel/{kind}/{index}/gate/key` row serves them (the console's GATE_KEY_LIMITS). A property of the detector filter, not of any desk: no come-up value is declared.
|
|
1187
|
+
* @see data/kernels/gate.json
|
|
1188
|
+
*/
|
|
1189
|
+
export const GATE_KEY_LIMITS = {
|
|
1190
|
+
"hpHz": {
|
|
1191
|
+
"min": 0,
|
|
1192
|
+
"max": 20000,
|
|
1193
|
+
"step": 1,
|
|
1194
|
+
"unit": "Hz"
|
|
1195
|
+
},
|
|
1196
|
+
"lpHz": {
|
|
1197
|
+
"min": 0,
|
|
1198
|
+
"max": 20000,
|
|
1199
|
+
"step": 1,
|
|
1200
|
+
"unit": "Hz"
|
|
1201
|
+
}
|
|
1202
|
+
};
|
|
1203
|
+
|
|
1175
1204
|
/**
|
|
1176
1205
|
* The generator kinds, in surface order: its position is the integer omx-dsp's omx_gen_fill takes as its kind (OMX_GEN_OSC, OMX_GEN_WHITE, OMX_GEN_PINK).
|
|
1177
1206
|
* @see data/kernels/generator.json
|
|
@@ -1244,7 +1273,7 @@ export const HRP_AMOUNT_RANGE = {
|
|
|
1244
1273
|
export const HRP_MAX_CUT_DB = 6;
|
|
1245
1274
|
|
|
1246
1275
|
/**
|
|
1247
|
-
* How many simultaneous musical voices the detector may report on one channel. PINNED to `OMX_HRP_MAX_VOICES` in `pipewire-native/src/hrp_pitch.h` — the C voice set is a FIXED-SIZE array, so a TS number above the macro promises voices the analyser structurally cannot return, and one below it silently drops notes the C already found.
|
|
1276
|
+
* How many simultaneous musical voices the detector may report on one channel. PINNED to `OMX_HRP_MAX_VOICES` in `pipewire-native/src/hrp_pitch.h` — the C voice set is a FIXED-SIZE array, so a TS number above the macro promises voices the analyser structurally cannot return, and one below it silently drops notes the C already found. the engine's conformance test reads the header and holds the pair equal. EIGHT (operator sizing, 2026-09-01): a guitar sounds six strings, a piano or string-section voicing sits at eight. It is a SEARCH ceiling, not a cost — the detector abandons a round as soon as no credible candidate remains, so monophonic material costs what it always did.
|
|
1248
1277
|
* @see data/kernels/hrp.json
|
|
1249
1278
|
*/
|
|
1250
1279
|
export const HRP_MAX_VOICES = 8;
|
|
@@ -1280,13 +1309,13 @@ export const HRP_COLLISION_CENTS = 100;
|
|
|
1280
1309
|
export const HRP_ATTRIBUTION_CENTS = 60;
|
|
1281
1310
|
|
|
1282
1311
|
/**
|
|
1283
|
-
* How many bands HRP may plant on ONE channel — its half of the machine budget, and the number that makes the budget FORECASTABLE rather than emergent. Without it the count is whatever the material happens to provoke: the placement law is sparse, so a clean note plants two bands and a resonant room plants nine, and nobody can answer "will this fit?" until it does not. With FBS senior (§9.3(b)) that discovery would happen at showtime, to the junior planter, silently. Declared instead, the whole sum is arithmetic an operator can read before a note is played: operator bands + FBS maxAutoBands + HRP maxAutoBands <= EQ_MAX_BANDS EIGHT — ONE CORRECTION PER VOICE at full polyphony (operator sizing, 2026-09-01). The detector's ceiling is HRP_MAX_VOICES voices, a guitar's six strings and a piano/string voicing's eight, and a budget below the voice count would decide by arithmetic which of the notes actually sounding may be corrected — a limit nobody could read off the desk. Scarcity is handled where it belongs instead: the candidates from every voice meet in ONE globally ranked list (spec §29) and the head of it is what gets planted. It is NOT a claim to seniority, and it is larger than FBS's six. Seniority is the ALLOCATION ORDER — `HrpPlanter` takes only `EQ_MAX_BANDS − others.length`, the remainder after the operator and every other machine — so a bigger junior default cannot reach a senior slot; it only means HRP asks for more of what is left.
|
|
1312
|
+
* How many bands HRP may plant on ONE channel — its half of the machine budget, and the number that makes the budget FORECASTABLE rather than emergent. Without it the count is whatever the material happens to provoke: the placement law is sparse, so a clean note plants two bands and a resonant room plants nine, and nobody can answer "will this fit?" until it does not. With FBS senior (§9.3(b)) that discovery would happen at showtime, to the junior planter, silently. Declared instead, the whole sum is arithmetic an operator can read before a note is played: operator bands + FBS maxAutoBands + HRP maxAutoBands <= EQ_MAX_BANDS EIGHT — ONE CORRECTION PER VOICE at full polyphony (operator sizing, 2026-09-01). The detector's ceiling is HRP_MAX_VOICES voices, a guitar's six strings and a piano/string voicing's eight, and a budget below the voice count would decide by arithmetic which of the notes actually sounding may be corrected — a limit nobody could read off the desk. Scarcity is handled where it belongs instead: the candidates from every voice meet in ONE globally ranked list (spec §29) and the head of it is what gets planted. It is NOT a claim to seniority, and it is larger than FBS's six. Seniority is the ALLOCATION ORDER — `HrpPlanter` takes only `EQ_MAX_BANDS − others.length`, the remainder after the operator and every other machine — so a bigger junior default cannot reach a senior slot; it only means HRP asks for more of what is left. the engine's conformance test asserts both halves. The per-channel DEFAULT; the row's travel is HRP_AUTO_BANDS_RANGE, so a channel that needs more can have more, as an explicit decision with a visible cost.
|
|
1284
1313
|
* @see data/kernels/hrp.json
|
|
1285
1314
|
*/
|
|
1286
1315
|
export const HRP_DEFAULT_MAX_AUTO_BANDS = 8;
|
|
1287
1316
|
|
|
1288
1317
|
/**
|
|
1289
|
-
* The precision limiter's travels
|
|
1318
|
+
* The precision limiter's travels, rendered into `omx_contract_limits.h` as `OMX_LIMITER_*` by the engine's limits generator, so `mix_limiter.h` reads them and never restates one (R-094). The ceiling is a TRUE peak in dBFS (the ×4 detector); the look-ahead sets the declared latency; the release is the envelope's time constant on the gain depth.
|
|
1290
1319
|
* @see data/kernels/limiter.json
|
|
1291
1320
|
*/
|
|
1292
1321
|
export const LIMITER_LIMITS = {
|
|
@@ -1317,7 +1346,7 @@ export const LIMITER_LIMITS = {
|
|
|
1317
1346
|
};
|
|
1318
1347
|
|
|
1319
1348
|
/**
|
|
1320
|
-
* The input cap a summing bus can be sized to — **the engine's declared input ceiling**, read from `@freemixer/declarations` rather than re-typed here. A gig with more than this many inputs needs more than one engine node; below it a bus is sized to `min(N, BUS_INPUT_CAP)`. It was a literal 64 until 2026-09-15, said to mirror the engine's `MAX_BUS_INPUTS` — and it did, but that 64 was the PipeWire builtin mixer's single-tier fan-in (8 × 8), never the engine's bound: the native node has allocated `OMX_MAX_STRIPS` (128) strips all along. Two literals agreeing by hand is how the console came to refuse a 96-channel desk it could carry.
|
|
1349
|
+
* The input cap a summing bus can be sized to — **the engine's declared input ceiling**, read from `@freemixer/declarations` rather than re-typed here. A gig with more than this many inputs needs more than one engine node; below it a bus is sized to `min(N, BUS_INPUT_CAP)`. It was a literal 64 until 2026-09-15, said to mirror the engine's `MAX_BUS_INPUTS` — and it did, but that 64 was the PipeWire builtin mixer's single-tier fan-in (8 × 8), never the engine's bound: the native node has allocated `OMX_MAX_STRIPS` (128) strips all along. Two literals agreeing by hand is how the console came to refuse a 96-channel desk it could carry. the engine's conformance test holds this to the C header; the console allocation design §9 carries the ruling and the measured cost of width.
|
|
1321
1350
|
* @see data/kernels/mixmatrix.json
|
|
1322
1351
|
*/
|
|
1323
1352
|
export const BUS_INPUT_CAP = 128;
|
|
@@ -1499,7 +1528,7 @@ export const PITCH_KERNEL = {
|
|
|
1499
1528
|
};
|
|
1500
1529
|
|
|
1501
1530
|
/**
|
|
1502
|
-
* PLATE's tank MODULATION DEPTH, in percent of Dattorro's own excursion (±8 samples at his 29 761 Hz tuning rate, scaled to the live rate the way the tank lengths are). 100 is the depth the plate has always run at, so the come-up is bit-identical to the plate before the field; 0 brings back the unmodulated tank's ring; 400 is the wide, chorused EMT-style swing. The rate stays 1 Hz. Only PLATE reads it
|
|
1531
|
+
* PLATE's tank MODULATION DEPTH, in percent of Dattorro's own excursion (±8 samples at his 29 761 Hz tuning rate, scaled to the live rate the way the tank lengths are). 100 is the depth the plate has always run at, so the come-up is bit-identical to the plate before the field; 0 brings back the unmodulated tank's ring; 400 is the wide, chorused EMT-style swing. The rate stays 1 Hz. Only PLATE reads it.
|
|
1503
1532
|
* @see data/kernels/reverb.json
|
|
1504
1533
|
*/
|
|
1505
1534
|
export const REVERB_PLATE_MOD_DEPTH_RANGE = {
|
|
@@ -1606,7 +1635,7 @@ export const REVERB_HIGHCUT_RANGE = {
|
|
|
1606
1635
|
};
|
|
1607
1636
|
|
|
1608
1637
|
/**
|
|
1609
|
-
* REVERSE's MIRROR WINDOW — how long a slice of the wet is played backward, in milliseconds
|
|
1638
|
+
* REVERSE's MIRROR WINDOW — how long a slice of the wet is played backward, in milliseconds. A DECLARED travel and never derived from `size`'s RT60: an RT60 of seconds cannot be buffered at 192 kHz, and a window silently clamped to fit is the silent-clamp defect. The ceiling is what `mix_reverb.h`'s pool budgets a ring for (`OMX_REVERB_REVERSE_MAX_MS`), so the console offers exactly the travel the kernel accepts — nothing wider, nothing narrower.
|
|
1610
1639
|
* @see data/kernels/reverb.json
|
|
1611
1640
|
*/
|
|
1612
1641
|
export const REVERB_REVERSE_RANGE = {
|
|
@@ -1912,7 +1941,7 @@ export const ROTARY_STOP_EPS = 0.0001;
|
|
|
1912
1941
|
export const ROTARY_RING_FLOATS = 256;
|
|
1913
1942
|
|
|
1914
1943
|
/**
|
|
1915
|
-
* The RTA's target bin resolution — generated into `omx_contract_limits.h` as `OMX_RTA_TARGET_BIN_HZ`, which `mix_dsp.h` reads;
|
|
1944
|
+
* The RTA's target bin resolution — generated into `omx_contract_limits.h` as `OMX_RTA_TARGET_BIN_HZ`, which `mix_dsp.h` reads; the engine's conformance test reads it back from the header.
|
|
1916
1945
|
* @see data/kernels/rta.json
|
|
1917
1946
|
*/
|
|
1918
1947
|
export const RTA_TARGET_BIN_HZ = 5.9;
|
|
@@ -1948,7 +1977,7 @@ export const SRC_ROLLOFF = 0.92;
|
|
|
1948
1977
|
export const SRC_MAX_L = 1024;
|
|
1949
1978
|
|
|
1950
1979
|
/**
|
|
1951
|
-
* The legal range of each transient-designer field (engineering units), transient spec §3. Every kind comes up flat: no per-kind default differs.
|
|
1980
|
+
* The legal range of each transient-designer field (engineering units), transient spec §3. Every kind comes up flat: no per-kind default differs. the engine's limits generator emits each as `OMX_TRANSIENT_<FIELD>_{MIN,MAX,DEFAULT}` for `mix_transient.h`'s resolve; the row publishes them on OPTIONS when it lands (issue #921).
|
|
1952
1981
|
* @see data/kernels/transient.json
|
|
1953
1982
|
*/
|
|
1954
1983
|
export const TRANSIENT_LIMITS = {
|
|
@@ -2098,7 +2127,7 @@ export const TREMOLO_TRAVELS = {
|
|
|
2098
2127
|
};
|
|
2099
2128
|
|
|
2100
2129
|
/**
|
|
2101
|
-
* The digital input trim, in dB: the console's fine head gain, applied first in a channel's lane as a click-free ramp from the last block's gain to this one (
|
|
2130
|
+
* The digital input trim, in dB: the console's fine head gain, applied first in a channel's lane as a click-free ramp from the last block's gain to this one (the console's trim range, -24..+24 dB in 0.1 dB steps, spelled minDb/maxDb/stepDb there). It comes up at 0 dB, the trim a channel has when none is set. omx-dsp's trim face takes it as `trim_db`.
|
|
2102
2131
|
* @see data/kernels/trim.json
|
|
2103
2132
|
*/
|
|
2104
2133
|
export const TRIM_RANGE = {
|
|
@@ -2268,7 +2297,7 @@ export const EQ_CONTINUOUS_TRAVELS = {
|
|
|
2268
2297
|
export const READOUT_RATE_HZ = 50;
|
|
2269
2298
|
|
|
2270
2299
|
/**
|
|
2271
|
-
* The standard sample rates (Hz) the desk recognises — the pro-audio superset. One source of truth for the clock controller's `clock.allowed-rates` seed, the force row's validation ceiling and the device-rate probe fallback. What the operator is OFFERED is always the DEVICE's own `supportedRates`
|
|
2300
|
+
* The standard sample rates (Hz) the desk recognises — the pro-audio superset. One source of truth for the clock controller's `clock.allowed-rates` seed, the force row's validation ceiling and the device-rate probe fallback. What the operator is OFFERED is always the DEVICE's own `supportedRates` — this is the ceiling a write is refused by, never a menu.
|
|
2272
2301
|
* @see data/rates.json
|
|
2273
2302
|
*/
|
|
2274
2303
|
export const STANDARD_SAMPLE_RATES = [
|
|
@@ -64,6 +64,11 @@
|
|
|
64
64
|
#define OMX_GATE_RATIO_MAX 100.0f
|
|
65
65
|
#define OMX_GATE_RATIO_DEFAULT 16.0f
|
|
66
66
|
|
|
67
|
+
#define OMX_GATE_KEY_HP_HZ_MIN 0.0f
|
|
68
|
+
#define OMX_GATE_KEY_HP_HZ_MAX 20000.0f
|
|
69
|
+
#define OMX_GATE_KEY_LP_HZ_MIN 0.0f
|
|
70
|
+
#define OMX_GATE_KEY_LP_HZ_MAX 20000.0f
|
|
71
|
+
|
|
67
72
|
#define OMX_LIMITER_CEILING_DB_MIN -12.0f
|
|
68
73
|
#define OMX_LIMITER_CEILING_DB_MAX 0.0f
|
|
69
74
|
#define OMX_LIMITER_CEILING_DB_DEFAULT -1.0f
|
|
@@ -691,6 +696,13 @@ enum omx_drive_hf_rolloffs {
|
|
|
691
696
|
};
|
|
692
697
|
#define OMX_DRIVE_HF_ROLLOFFS_COUNT 3u
|
|
693
698
|
#define OMX_DRIVE_HF_ROLLOFFS_DEFAULT OMX_DRIVE_HF_ROLLOFFS_0
|
|
699
|
+
enum omx_drive_oversamples {
|
|
700
|
+
OMX_DRIVE_OVERSAMPLES_1 = 1,
|
|
701
|
+
OMX_DRIVE_OVERSAMPLES_2 = 2,
|
|
702
|
+
OMX_DRIVE_OVERSAMPLES_4 = 4,
|
|
703
|
+
};
|
|
704
|
+
#define OMX_DRIVE_OVERSAMPLES_COUNT 3u
|
|
705
|
+
#define OMX_DRIVE_OVERSAMPLES_DEFAULT OMX_DRIVE_OVERSAMPLES_4
|
|
694
706
|
enum omx_drive_stereo_links {
|
|
695
707
|
OMX_DRIVE_STEREO_LINKS_OFF = 0,
|
|
696
708
|
OMX_DRIVE_STEREO_LINKS_ON = 1,
|
package/lib/semver.mjs
CHANGED
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
const RANK = { none: 0, patch: 1, minor: 2, major: 3 };
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
|
-
* The development-phase rule (
|
|
23
|
+
* The development-phase rule (omx-contract spec §3.6): while every consumer of
|
|
24
24
|
* omx-contract is a FreeMixer repository named here, removing an item is MINOR. The rule ends, and
|
|
25
25
|
* this becomes null so a removal is MAJOR again, in the release that names the first consumer
|
|
26
26
|
* outside the list.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openmixer/omx-contract",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.8.0",
|
|
4
4
|
"description": "The FreeMixer declarations as data: a JSON Schema, the data, and one CLI that renders them into C, TypeScript and JSON",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "GPL-3.0-or-later",
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
2
2
|
// Copyright (C) 2026 Pau Aliagas <linuxnow@gmail.com>
|
|
3
|
-
// Moved unchanged from
|
|
4
|
-
// §3.4): a frozen export of
|
|
3
|
+
// Moved unchanged from the console engine's contract-limits renderer at 6c6e709f4429 (omx-contract spec
|
|
4
|
+
// §3.4): a frozen export of the engine's whole sheet renders through it byte for byte (test/round-trip.test.mjs).
|
|
5
5
|
/**
|
|
6
6
|
* The RENDER half of `contract-limits-gen.mjs`: the header text as a pure function of the
|
|
7
|
-
* declaration sheet it is handed. Split out so the declaration-perturbation
|
|
8
|
-
* `packages/server/src/declaration-perturbation-conformance.test.ts`) can render the header over
|
|
7
|
+
* declaration sheet it is handed. Split out so the engine's declaration-perturbation test can render the header over
|
|
9
8
|
* a PERTURBED sheet and see whether every define follows it — the generator itself imports the
|
|
10
9
|
* built modules and calls this, so there is one renderer and no second copy.
|
|
11
10
|
*/
|
|
@@ -41,7 +40,10 @@ function genLimitBlock(prefix, table) {
|
|
|
41
40
|
const c = fieldConstName(field);
|
|
42
41
|
lines.push(`#define OMX_${prefix}_${c}_MIN ${numLiteral(limit.min)}f`);
|
|
43
42
|
lines.push(`#define OMX_${prefix}_${c}_MAX ${numLiteral(limit.max)}f`);
|
|
44
|
-
|
|
43
|
+
// a field with no come-up value (the gate key filter's edges) has no DEFAULT, as in genCoreLimitBlock
|
|
44
|
+
if (limit.default !== undefined) {
|
|
45
|
+
lines.push(`#define OMX_${prefix}_${c}_DEFAULT ${numLiteral(limit.default)}f`);
|
|
46
|
+
}
|
|
45
47
|
}
|
|
46
48
|
return lines.join('\n');
|
|
47
49
|
}
|
|
@@ -217,7 +219,7 @@ function genDeclaredListsBlock(DECLARED_LISTS, definedElsewhere) {
|
|
|
217
219
|
* over `<PREFIX>_LIMITS`, `declaredScalars`, `declaredSets`, `declaredLists`), then `extra` — the
|
|
218
220
|
* names that are not in the core barrel (`OMX_CLAP_HOST_EXTENSIONS`) or a test's override of one
|
|
219
221
|
* door. The generator and every render test build the sheet here, so a new door is added once,
|
|
220
|
-
* never appended to a hand list per caller
|
|
222
|
+
* never appended to a hand list per caller.
|
|
221
223
|
*/
|
|
222
224
|
export function contractLimitsSheet(coreNs, declarations, extra = {}) {
|
|
223
225
|
return {
|
package/render/doors.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
2
2
|
// Copyright (C) 2026 Pau Aliagas <linuxnow@gmail.com>
|
|
3
3
|
/**
|
|
4
|
-
* The resolved data cut into the C renderer's doors, as
|
|
5
|
-
* (
|
|
4
|
+
* The resolved data cut into the C renderer's doors, as the engine's discovery cut its barrels
|
|
5
|
+
* (its native limit tables, declared scalars and declared lists): a `travels`
|
|
6
6
|
* table named <PREFIX>_LIMITS is a native table; every scalar, sheet and single travel is scalars
|
|
7
7
|
* (its finite-number leaves, a travel's `unit`/`defaultFrom` labels skipped); a list is a declared
|
|
8
8
|
* list unless its item says `"c": { "render": false }`; a set is an enum; a `c.alias` is the core-limit spelling.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openmixer/omx-contract",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.8.0",
|
|
4
4
|
"items": {
|
|
5
5
|
"PAN_RANGE": {
|
|
6
6
|
"rel": "data/kernels/balance.json",
|
|
@@ -302,7 +302,7 @@
|
|
|
302
302
|
"DETECTOR_TOPOLOGY": {
|
|
303
303
|
"rel": "data/kernels/comp.json",
|
|
304
304
|
"kind": "set",
|
|
305
|
-
"doc": "Where the compressor's detector listens: `feedforward` hears the slot's input (or its key), `feedback` hears the slot's own pre-make-up output DYN_FB_LOOP_DELAY_SAMPLES late, through one envelope stage, and a keyed slot stays feed-forward (omx-dsp's OMX_DYN_TOPOLOGY_FEEDFORWARD 0 and _FEEDBACK 1, in that order; the set is named for its control, so C spells them OMX_DETECTOR_TOPOLOGY_*). The console's comp row carries it (`detectorTopology`,
|
|
305
|
+
"doc": "Where the compressor's detector listens: `feedforward` hears the slot's input (or its key), `feedback` hears the slot's own pre-make-up output DYN_FB_LOOP_DELAY_SAMPLES late, through one envelope stage, and a keyed slot stays feed-forward (omx-dsp's OMX_DYN_TOPOLOGY_FEEDFORWARD 0 and _FEEDBACK 1, in that order; the set is named for its control, so C spells them OMX_DETECTOR_TOPOLOGY_*). The console's comp row carries it (`detectorTopology`, the SSL bus compressor design §3a) and comes up `feedforward`, so a zeroed atom is the compressor every slot runs.",
|
|
306
306
|
"default": "feedforward",
|
|
307
307
|
"value": [
|
|
308
308
|
"feedforward",
|
|
@@ -312,7 +312,7 @@
|
|
|
312
312
|
"PROGRAM_RELEASE": {
|
|
313
313
|
"rel": "data/kernels/comp.json",
|
|
314
314
|
"kind": "sheet",
|
|
315
|
-
"doc": "The program-dependent release's model constants — the LA-2A's opto cell as DATA (
|
|
315
|
+
"doc": "The program-dependent release's model constants — the LA-2A's opto cell as DATA (compressor models design §3b). `chargeMs`/`dischargeMs` are the word's memory constants, shared by every profile; each profile's `fastMs`, `slowMinMs`, `slowMaxMs` and `share` fit the unit's published two-stage recovery. Not operator controls: generated into `omx_contract_limits.h` as `OMX_PROGRAM_RELEASE_*`, which libomxdsp's `omx_env_program_release` reads.",
|
|
316
316
|
"value": {
|
|
317
317
|
"chargeMs": 1000,
|
|
318
318
|
"dischargeMs": 5000,
|
|
@@ -443,14 +443,14 @@
|
|
|
443
443
|
"DEESS_KNEE_DB": {
|
|
444
444
|
"rel": "data/kernels/deesser.json",
|
|
445
445
|
"kind": "scalar",
|
|
446
|
-
"doc": "The knee, in dB — a CONSTANT of the stage and not a row field
|
|
446
|
+
"doc": "The knee, in dB — a CONSTANT of the stage and not a row field: a de-esser without a soft knee latches audibly on the first sibilant of a phrase, and no other value of this number is a de-esser anyone would dial. The controller pushes it to the node and this is the same number; a second spelling would be a picture that disagrees with the audio about where the reduction starts.",
|
|
447
447
|
"unit": "dB",
|
|
448
448
|
"value": 6
|
|
449
449
|
},
|
|
450
450
|
"FX_DELAY_TIME_RANGE": {
|
|
451
451
|
"rel": "data/kernels/delay.json",
|
|
452
452
|
"kind": "travels",
|
|
453
|
-
"doc": "The FX delay's time travel. `max` is the NATIVE ring's ceiling — the same number as `OMX_FXDELAY_MAX_MS` in `omx_delay.h`, pinned to it by
|
|
453
|
+
"doc": "The FX delay's time travel. `max` is the NATIVE ring's ceiling — the same number as `OMX_FXDELAY_MAX_MS` in `omx_delay.h`, pinned to it by the engine's conformance test. Distinct from the per-route ALIGNMENT delay (`OUTPUT_DELAY_RANGE`, 1 s, `OMX_DELAY_MAX_MS`): one is a musical echo with feedback and mix, the other is a pure latency. Two facts, two rings, two ceilings — sharing the word \"delay\" is why they keep being confused for each other.",
|
|
454
454
|
"c": {
|
|
455
455
|
"alias": {
|
|
456
456
|
"fact": "delay",
|
|
@@ -484,7 +484,7 @@
|
|
|
484
484
|
"DELAY_TONE_RANGE": {
|
|
485
485
|
"rel": "data/kernels/delay.json",
|
|
486
486
|
"kind": "travels",
|
|
487
|
-
"doc": "The FX delay's TONE — a NORMALIZED_RANGE instance with its own come-up value, matching
|
|
487
|
+
"doc": "The FX delay's TONE — a NORMALIZED_RANGE instance with its own come-up value, matching the console's delay default tone. See REVERB_SIZE_RANGE for why this is a named constant rather than a default on the shared shape.",
|
|
488
488
|
"shape": "travel",
|
|
489
489
|
"value": {
|
|
490
490
|
"min": 0,
|
|
@@ -529,7 +529,7 @@
|
|
|
529
529
|
"FX_DELAY_PINGPONG_DEFAULT": {
|
|
530
530
|
"rel": "data/kernels/delay.json",
|
|
531
531
|
"kind": "scalar",
|
|
532
|
-
"doc": "The FX delay's PING-PONG come-up value — a toggle, so it has no travel, only this. Declared here rather than as a literal in the
|
|
532
|
+
"doc": "The FX delay's PING-PONG come-up value — a toggle, so it has no travel, only this. Declared here rather than as a literal in the console's delay default state (which now reads it) so the DPF plugin generator (omx-plugins, DPF plugin design §3a) reads the same fact the desk seeds a fresh strip with.",
|
|
533
533
|
"unit": "",
|
|
534
534
|
"value": false
|
|
535
535
|
},
|
|
@@ -699,6 +699,22 @@
|
|
|
699
699
|
16000
|
|
700
700
|
]
|
|
701
701
|
},
|
|
702
|
+
"DRIVE_OVERSAMPLES": {
|
|
703
|
+
"rel": "data/kernels/drive.json",
|
|
704
|
+
"kind": "set",
|
|
705
|
+
"doc": "The drive's OVERSAMPLING factor: the shaper runs inside the console's one oversampler at 1x, 2x or 4x, and the id is the factor (`omx_drive.h`'s `omx_drive_factor_of` member set, `struct omx_drive.os_factor`). A field of the console's drive row (`DriveState.oversample`, the console's DRIVE_OVERSAMPLE_FACTORS; the set is named for its control), 4 at come-up there and in omx-dsp's drive face (OMX_DRIVE_INSTANCE_FACTOR, the oversampler's largest).",
|
|
706
|
+
"default": 4,
|
|
707
|
+
"labels": [
|
|
708
|
+
"1x",
|
|
709
|
+
"2x",
|
|
710
|
+
"4x"
|
|
711
|
+
],
|
|
712
|
+
"value": [
|
|
713
|
+
1,
|
|
714
|
+
2,
|
|
715
|
+
4
|
|
716
|
+
]
|
|
717
|
+
},
|
|
702
718
|
"DRIVE_BIAS_MAX": {
|
|
703
719
|
"rel": "data/kernels/drive.json",
|
|
704
720
|
"kind": "scalar",
|
|
@@ -805,7 +821,7 @@
|
|
|
805
821
|
"EQ_GAIN_RANGE": {
|
|
806
822
|
"rel": "data/kernels/eq.json",
|
|
807
823
|
"kind": "travels",
|
|
808
|
-
"doc": "The parametric-band gain travel, in dB. The ± scalar `clampEqGain` enforces is READ off this (
|
|
824
|
+
"doc": "The parametric-band gain travel, in dB. The ± scalar `clampEqGain` enforces is READ off this (the engine derives its gain limit from `max`), so the bound is stated once and a surface cannot draw a wider knob than the clamp will honour.",
|
|
809
825
|
"shape": "travel",
|
|
810
826
|
"value": {
|
|
811
827
|
"min": -15,
|
|
@@ -854,7 +870,7 @@
|
|
|
854
870
|
"EQ_MAX_BANDS": {
|
|
855
871
|
"rel": "data/kernels/eq.json",
|
|
856
872
|
"kind": "scalar",
|
|
857
|
-
"doc": "The maximum number of parametric bands a channel EQ may hold — the operator can add up to this many. Generated into `omx_contract_limits.h` as `OMX_EQ_MAX_BANDS`, which `omx_biquad.h` reads (
|
|
873
|
+
"doc": "The maximum number of parametric bands a channel EQ may hold — the operator can add up to this many. Generated into `omx_contract_limits.h` as `OMX_EQ_MAX_BANDS`, which `omx_biquad.h` reads (the engine's conformance test reads the header): the native lane allocates exactly this many biquad slots per channel and silently clamps above it, so the model, the wire, and the DSP agree by test, not by memory.",
|
|
858
874
|
"unit": "",
|
|
859
875
|
"value": 24
|
|
860
876
|
},
|
|
@@ -1170,7 +1186,7 @@
|
|
|
1170
1186
|
"FBS_MAX_NOTCH_DEPTH_DB": {
|
|
1171
1187
|
"rel": "data/kernels/fbs.json",
|
|
1172
1188
|
"kind": "scalar",
|
|
1173
|
-
"doc": "THE NOTCH DEPTH LAW: the deepest cut any machine planter may propose from one reading, in dB. A number, not a literal at the call site, because two planters now lean on it. FBS derives a candidate's depth from the peak-to-average ratio around its bin and stops here; Room Analysis derives a mode's depth from its height above the median curve and is held to the SAME ceiling (
|
|
1189
|
+
"doc": "THE NOTCH DEPTH LAW: the deepest cut any machine planter may propose from one reading, in dB. A number, not a literal at the call site, because two planters now lean on it. FBS derives a candidate's depth from the peak-to-average ratio around its bin and stops here; Room Analysis derives a mode's depth from its height above the median curve and is held to the SAME ceiling (the room-analysis design §4 — \"never more than the FBS notch depth law\"). Written twice as `18` those two bounds would be equal by coincidence and could drift apart in silence. It is a CEILING ON THE PROPOSAL, not the final gain: a band that lands as a rampable BELL is bounded again by `EQ_GAIN_RANGE`, which is tighter. A planter must honour both and REPORT when either bit, never quietly deliver a shallower cut than it was asked for.",
|
|
1174
1190
|
"unit": "dB",
|
|
1175
1191
|
"value": 18
|
|
1176
1192
|
},
|
|
@@ -1347,6 +1363,26 @@
|
|
|
1347
1363
|
}
|
|
1348
1364
|
}
|
|
1349
1365
|
},
|
|
1366
|
+
"GATE_KEY_LIMITS": {
|
|
1367
|
+
"rel": "data/kernels/gate.json",
|
|
1368
|
+
"kind": "travels",
|
|
1369
|
+
"doc": "The travel of each edge of the keyed gate's detector filter, 0 (off) up to 20 kHz in whole Hz, as the console's `/channel/{kind}/{index}/gate/key` row serves them (the console's GATE_KEY_LIMITS). A property of the detector filter, not of any desk: no come-up value is declared.",
|
|
1370
|
+
"shape": "table",
|
|
1371
|
+
"value": {
|
|
1372
|
+
"hpHz": {
|
|
1373
|
+
"min": 0,
|
|
1374
|
+
"max": 20000,
|
|
1375
|
+
"step": 1,
|
|
1376
|
+
"unit": "Hz"
|
|
1377
|
+
},
|
|
1378
|
+
"lpHz": {
|
|
1379
|
+
"min": 0,
|
|
1380
|
+
"max": 20000,
|
|
1381
|
+
"step": 1,
|
|
1382
|
+
"unit": "Hz"
|
|
1383
|
+
}
|
|
1384
|
+
}
|
|
1385
|
+
},
|
|
1350
1386
|
"GENERATOR_KINDS": {
|
|
1351
1387
|
"rel": "data/kernels/generator.json",
|
|
1352
1388
|
"kind": "set",
|
|
@@ -1427,7 +1463,7 @@
|
|
|
1427
1463
|
"HRP_MAX_VOICES": {
|
|
1428
1464
|
"rel": "data/kernels/hrp.json",
|
|
1429
1465
|
"kind": "scalar",
|
|
1430
|
-
"doc": "How many simultaneous musical voices the detector may report on one channel. PINNED to `OMX_HRP_MAX_VOICES` in `pipewire-native/src/hrp_pitch.h` — the C voice set is a FIXED-SIZE array, so a TS number above the macro promises voices the analyser structurally cannot return, and one below it silently drops notes the C already found.
|
|
1466
|
+
"doc": "How many simultaneous musical voices the detector may report on one channel. PINNED to `OMX_HRP_MAX_VOICES` in `pipewire-native/src/hrp_pitch.h` — the C voice set is a FIXED-SIZE array, so a TS number above the macro promises voices the analyser structurally cannot return, and one below it silently drops notes the C already found. the engine's conformance test reads the header and holds the pair equal. EIGHT (operator sizing, 2026-09-01): a guitar sounds six strings, a piano or string-section voicing sits at eight. It is a SEARCH ceiling, not a cost — the detector abandons a round as soon as no credible candidate remains, so monophonic material costs what it always did.",
|
|
1431
1467
|
"unit": "",
|
|
1432
1468
|
"value": 8
|
|
1433
1469
|
},
|
|
@@ -1469,14 +1505,14 @@
|
|
|
1469
1505
|
"HRP_DEFAULT_MAX_AUTO_BANDS": {
|
|
1470
1506
|
"rel": "data/kernels/hrp.json",
|
|
1471
1507
|
"kind": "scalar",
|
|
1472
|
-
"doc": "How many bands HRP may plant on ONE channel — its half of the machine budget, and the number that makes the budget FORECASTABLE rather than emergent. Without it the count is whatever the material happens to provoke: the placement law is sparse, so a clean note plants two bands and a resonant room plants nine, and nobody can answer \"will this fit?\" until it does not. With FBS senior (§9.3(b)) that discovery would happen at showtime, to the junior planter, silently. Declared instead, the whole sum is arithmetic an operator can read before a note is played: operator bands + FBS maxAutoBands + HRP maxAutoBands <= EQ_MAX_BANDS EIGHT — ONE CORRECTION PER VOICE at full polyphony (operator sizing, 2026-09-01). The detector's ceiling is HRP_MAX_VOICES voices, a guitar's six strings and a piano/string voicing's eight, and a budget below the voice count would decide by arithmetic which of the notes actually sounding may be corrected — a limit nobody could read off the desk. Scarcity is handled where it belongs instead: the candidates from every voice meet in ONE globally ranked list (spec §29) and the head of it is what gets planted. It is NOT a claim to seniority, and it is larger than FBS's six. Seniority is the ALLOCATION ORDER — `HrpPlanter` takes only `EQ_MAX_BANDS − others.length`, the remainder after the operator and every other machine — so a bigger junior default cannot reach a senior slot; it only means HRP asks for more of what is left.
|
|
1508
|
+
"doc": "How many bands HRP may plant on ONE channel — its half of the machine budget, and the number that makes the budget FORECASTABLE rather than emergent. Without it the count is whatever the material happens to provoke: the placement law is sparse, so a clean note plants two bands and a resonant room plants nine, and nobody can answer \"will this fit?\" until it does not. With FBS senior (§9.3(b)) that discovery would happen at showtime, to the junior planter, silently. Declared instead, the whole sum is arithmetic an operator can read before a note is played: operator bands + FBS maxAutoBands + HRP maxAutoBands <= EQ_MAX_BANDS EIGHT — ONE CORRECTION PER VOICE at full polyphony (operator sizing, 2026-09-01). The detector's ceiling is HRP_MAX_VOICES voices, a guitar's six strings and a piano/string voicing's eight, and a budget below the voice count would decide by arithmetic which of the notes actually sounding may be corrected — a limit nobody could read off the desk. Scarcity is handled where it belongs instead: the candidates from every voice meet in ONE globally ranked list (spec §29) and the head of it is what gets planted. It is NOT a claim to seniority, and it is larger than FBS's six. Seniority is the ALLOCATION ORDER — `HrpPlanter` takes only `EQ_MAX_BANDS − others.length`, the remainder after the operator and every other machine — so a bigger junior default cannot reach a senior slot; it only means HRP asks for more of what is left. the engine's conformance test asserts both halves. The per-channel DEFAULT; the row's travel is HRP_AUTO_BANDS_RANGE, so a channel that needs more can have more, as an explicit decision with a visible cost.",
|
|
1473
1509
|
"unit": "",
|
|
1474
1510
|
"value": 8
|
|
1475
1511
|
},
|
|
1476
1512
|
"LIMITER_LIMITS": {
|
|
1477
1513
|
"rel": "data/kernels/limiter.json",
|
|
1478
1514
|
"kind": "travels",
|
|
1479
|
-
"doc": "The precision limiter's travels
|
|
1515
|
+
"doc": "The precision limiter's travels, rendered into `omx_contract_limits.h` as `OMX_LIMITER_*` by the engine's limits generator, so `mix_limiter.h` reads them and never restates one (R-094). The ceiling is a TRUE peak in dBFS (the ×4 detector); the look-ahead sets the declared latency; the release is the envelope's time constant on the gain depth.",
|
|
1480
1516
|
"shape": "table",
|
|
1481
1517
|
"value": {
|
|
1482
1518
|
"ceilingDb": {
|
|
@@ -1508,7 +1544,7 @@
|
|
|
1508
1544
|
"BUS_INPUT_CAP": {
|
|
1509
1545
|
"rel": "data/kernels/mixmatrix.json",
|
|
1510
1546
|
"kind": "scalar",
|
|
1511
|
-
"doc": "The input cap a summing bus can be sized to — **the engine's declared input ceiling**, read from `@freemixer/declarations` rather than re-typed here. A gig with more than this many inputs needs more than one engine node; below it a bus is sized to `min(N, BUS_INPUT_CAP)`. It was a literal 64 until 2026-09-15, said to mirror the engine's `MAX_BUS_INPUTS` — and it did, but that 64 was the PipeWire builtin mixer's single-tier fan-in (8 × 8), never the engine's bound: the native node has allocated `OMX_MAX_STRIPS` (128) strips all along. Two literals agreeing by hand is how the console came to refuse a 96-channel desk it could carry.
|
|
1547
|
+
"doc": "The input cap a summing bus can be sized to — **the engine's declared input ceiling**, read from `@freemixer/declarations` rather than re-typed here. A gig with more than this many inputs needs more than one engine node; below it a bus is sized to `min(N, BUS_INPUT_CAP)`. It was a literal 64 until 2026-09-15, said to mirror the engine's `MAX_BUS_INPUTS` — and it did, but that 64 was the PipeWire builtin mixer's single-tier fan-in (8 × 8), never the engine's bound: the native node has allocated `OMX_MAX_STRIPS` (128) strips all along. Two literals agreeing by hand is how the console came to refuse a 96-channel desk it could carry. the engine's conformance test holds this to the C header; the console allocation design §9 carries the ruling and the measured cost of width.",
|
|
1512
1548
|
"unit": "",
|
|
1513
1549
|
"value": 128
|
|
1514
1550
|
},
|
|
@@ -1701,7 +1737,7 @@
|
|
|
1701
1737
|
"REVERB_PLATE_MOD_DEPTH_RANGE": {
|
|
1702
1738
|
"rel": "data/kernels/reverb.json",
|
|
1703
1739
|
"kind": "travels",
|
|
1704
|
-
"doc": "PLATE's tank MODULATION DEPTH, in percent of Dattorro's own excursion (±8 samples at his 29 761 Hz tuning rate, scaled to the live rate the way the tank lengths are). 100 is the depth the plate has always run at, so the come-up is bit-identical to the plate before the field; 0 brings back the unmodulated tank's ring; 400 is the wide, chorused EMT-style swing. The rate stays 1 Hz. Only PLATE reads it
|
|
1740
|
+
"doc": "PLATE's tank MODULATION DEPTH, in percent of Dattorro's own excursion (±8 samples at his 29 761 Hz tuning rate, scaled to the live rate the way the tank lengths are). 100 is the depth the plate has always run at, so the come-up is bit-identical to the plate before the field; 0 brings back the unmodulated tank's ring; 400 is the wide, chorused EMT-style swing. The rate stays 1 Hz. Only PLATE reads it.",
|
|
1705
1741
|
"shape": "travel",
|
|
1706
1742
|
"value": {
|
|
1707
1743
|
"min": 0,
|
|
@@ -1816,7 +1852,7 @@
|
|
|
1816
1852
|
"REVERB_REVERSE_RANGE": {
|
|
1817
1853
|
"rel": "data/kernels/reverb.json",
|
|
1818
1854
|
"kind": "travels",
|
|
1819
|
-
"doc": "REVERSE's MIRROR WINDOW — how long a slice of the wet is played backward, in milliseconds
|
|
1855
|
+
"doc": "REVERSE's MIRROR WINDOW — how long a slice of the wet is played backward, in milliseconds. A DECLARED travel and never derived from `size`'s RT60: an RT60 of seconds cannot be buffered at 192 kHz, and a window silently clamped to fit is the silent-clamp defect. The ceiling is what `mix_reverb.h`'s pool budgets a ring for (`OMX_REVERB_REVERSE_MAX_MS`), so the console offers exactly the travel the kernel accepts — nothing wider, nothing narrower.",
|
|
1820
1856
|
"shape": "travel",
|
|
1821
1857
|
"value": {
|
|
1822
1858
|
"min": 50,
|
|
@@ -2147,7 +2183,7 @@
|
|
|
2147
2183
|
"RTA_TARGET_BIN_HZ": {
|
|
2148
2184
|
"rel": "data/kernels/rta.json",
|
|
2149
2185
|
"kind": "scalar",
|
|
2150
|
-
"doc": "The RTA's target bin resolution — generated into `omx_contract_limits.h` as `OMX_RTA_TARGET_BIN_HZ`, which `mix_dsp.h` reads;
|
|
2186
|
+
"doc": "The RTA's target bin resolution — generated into `omx_contract_limits.h` as `OMX_RTA_TARGET_BIN_HZ`, which `mix_dsp.h` reads; the engine's conformance test reads it back from the header.",
|
|
2151
2187
|
"unit": "Hz",
|
|
2152
2188
|
"value": 5.9
|
|
2153
2189
|
},
|
|
@@ -2189,7 +2225,7 @@
|
|
|
2189
2225
|
"TRANSIENT_LIMITS": {
|
|
2190
2226
|
"rel": "data/kernels/transient.json",
|
|
2191
2227
|
"kind": "travels",
|
|
2192
|
-
"doc": "The legal range of each transient-designer field (engineering units), transient spec §3. Every kind comes up flat: no per-kind default differs.
|
|
2228
|
+
"doc": "The legal range of each transient-designer field (engineering units), transient spec §3. Every kind comes up flat: no per-kind default differs. the engine's limits generator emits each as `OMX_TRANSIENT_<FIELD>_{MIN,MAX,DEFAULT}` for `mix_transient.h`'s resolve; the row publishes them on OPTIONS when it lands (issue #921).",
|
|
2193
2229
|
"shape": "table",
|
|
2194
2230
|
"value": {
|
|
2195
2231
|
"attackDb": {
|
|
@@ -2349,7 +2385,7 @@
|
|
|
2349
2385
|
"TRIM_RANGE": {
|
|
2350
2386
|
"rel": "data/kernels/trim.json",
|
|
2351
2387
|
"kind": "travels",
|
|
2352
|
-
"doc": "The digital input trim, in dB: the console's fine head gain, applied first in a channel's lane as a click-free ramp from the last block's gain to this one (
|
|
2388
|
+
"doc": "The digital input trim, in dB: the console's fine head gain, applied first in a channel's lane as a click-free ramp from the last block's gain to this one (the console's trim range, -24..+24 dB in 0.1 dB steps, spelled minDb/maxDb/stepDb there). It comes up at 0 dB, the trim a channel has when none is set. omx-dsp's trim face takes it as `trim_db`.",
|
|
2353
2389
|
"shape": "travel",
|
|
2354
2390
|
"value": {
|
|
2355
2391
|
"min": -24,
|
|
@@ -2529,7 +2565,7 @@
|
|
|
2529
2565
|
"STANDARD_SAMPLE_RATES": {
|
|
2530
2566
|
"rel": "data/rates.json",
|
|
2531
2567
|
"kind": "list",
|
|
2532
|
-
"doc": "The standard sample rates (Hz) the desk recognises — the pro-audio superset. One source of truth for the clock controller's `clock.allowed-rates` seed, the force row's validation ceiling and the device-rate probe fallback. What the operator is OFFERED is always the DEVICE's own `supportedRates`
|
|
2568
|
+
"doc": "The standard sample rates (Hz) the desk recognises — the pro-audio superset. One source of truth for the clock controller's `clock.allowed-rates` seed, the force row's validation ceiling and the device-rate probe fallback. What the operator is OFFERED is always the DEVICE's own `supportedRates` — this is the ceiling a write is refused by, never a menu.",
|
|
2533
2569
|
"unit": "Hz",
|
|
2534
2570
|
"value": [
|
|
2535
2571
|
44100,
|
|
@@ -2866,6 +2902,11 @@
|
|
|
2866
2902
|
"name": "hfRolloff",
|
|
2867
2903
|
"kind": "choice",
|
|
2868
2904
|
"global": "DRIVE_HF_ROLLOFFS"
|
|
2905
|
+
},
|
|
2906
|
+
{
|
|
2907
|
+
"name": "oversample",
|
|
2908
|
+
"kind": "choice",
|
|
2909
|
+
"global": "DRIVE_OVERSAMPLES"
|
|
2869
2910
|
}
|
|
2870
2911
|
]
|
|
2871
2912
|
},
|
|
@@ -3027,6 +3068,18 @@
|
|
|
3027
3068
|
"kind": "travel",
|
|
3028
3069
|
"global": "GATE_LIMITS",
|
|
3029
3070
|
"table": "GATE_LIMITS"
|
|
3071
|
+
},
|
|
3072
|
+
{
|
|
3073
|
+
"name": "hpHz",
|
|
3074
|
+
"kind": "travel",
|
|
3075
|
+
"global": "GATE_KEY_LIMITS",
|
|
3076
|
+
"table": "GATE_KEY_LIMITS"
|
|
3077
|
+
},
|
|
3078
|
+
{
|
|
3079
|
+
"name": "lpHz",
|
|
3080
|
+
"kind": "travel",
|
|
3081
|
+
"global": "GATE_KEY_LIMITS",
|
|
3082
|
+
"table": "GATE_KEY_LIMITS"
|
|
3030
3083
|
}
|
|
3031
3084
|
],
|
|
3032
3085
|
"readouts": [
|