@openmixer/omx-contract 0.0.0 → 1.0.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/LICENSE +674 -0
- package/README.md +50 -5
- package/bin/omx-contract.mjs +175 -0
- package/data/kernels/chorus.json +15 -0
- package/data/kernels/comp.json +81 -0
- package/data/kernels/delay.json +66 -0
- package/data/kernels/drive.json +12 -0
- package/data/kernels/eq.json +59 -0
- package/data/kernels/gate.json +81 -0
- package/data/kernels/limiter.json +33 -0
- package/data/kernels/pitch.json +35 -0
- package/data/kernels/reverb.json +15 -0
- package/data/kernels/transient.json +73 -0
- package/data/plugins/delay.json +48 -0
- package/data/primitives.json +47 -0
- package/data/rates.json +30 -0
- package/dist/ts/omx-contract.d.ts +517 -0
- package/dist/ts/omx-contract.js +562 -0
- package/include/omxcontract/omx_contract_limits.h +201 -0
- package/include/omxcontract/params/omx_delay_params.h +47 -0
- package/include/omxcontract/params/omx_plugin_param.h +25 -0
- package/lib/data.mjs +182 -0
- package/lib/fmt.mjs +63 -0
- package/lib/semver.mjs +124 -0
- package/lib/validate.mjs +107 -0
- package/package.json +44 -4
- package/render/c/contract-limits-render.mjs +370 -0
- package/render/c/omx_plugin_param.h +25 -0
- package/render/c/params-generate.mjs +83 -0
- package/render/c.mjs +104 -0
- package/render/doors.mjs +64 -0
- package/render/json.mjs +16 -0
- package/render/ts.mjs +42 -0
- package/schema/omx-contract.schema.json +194 -0
- package/share/omx-contract/omx-contract.json +597 -0
|
@@ -0,0 +1,562 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
2
|
+
// Copyright (C) 2026 Pau Aliagas <linuxnow@gmail.com>
|
|
3
|
+
// GENERATED by `omx-contract render --target ts` from FreeMixer/omx-contract's data/ — do not edit.
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The chorus's right-leg phase offset, in TURNS of its one oscillator (§2, §3a; the native-FX catalogue's M32 Dimension row). The right leg's voice k reads the LFO at k/N + spread: 0 is both legs one phase (the stage without the field, bit for bit), 0.25 quadrature, 0.5 the Dimension's opposed sweep. A fraction of a cycle carries no engineering symbol, so the unit is ''.
|
|
7
|
+
* @see data/kernels/chorus.json
|
|
8
|
+
*/
|
|
9
|
+
export const CHORUS_SPREAD_RANGE = {
|
|
10
|
+
"min": 0,
|
|
11
|
+
"max": 0.5,
|
|
12
|
+
"step": 0.01,
|
|
13
|
+
"unit": "",
|
|
14
|
+
"default": 0,
|
|
15
|
+
"defaultFrom": "desk"
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* The legal range of each compressor field (engineering units). The widget clamps drags to these, `normalizeComp` enforces them, the row's codec refuses by them and the travel sheet publishes them. `default`/`defaultFrom` are the come-up values `defaultCompState` seeds a fresh strip with, read BACK from here rather than restated there.
|
|
20
|
+
* @see data/kernels/comp.json
|
|
21
|
+
*/
|
|
22
|
+
export const COMP_LIMITS = {
|
|
23
|
+
"thresholdDb": {
|
|
24
|
+
"min": -60,
|
|
25
|
+
"max": 0,
|
|
26
|
+
"step": 1,
|
|
27
|
+
"unit": "dB",
|
|
28
|
+
"default": -18,
|
|
29
|
+
"defaultFrom": "desk"
|
|
30
|
+
},
|
|
31
|
+
"ratio": {
|
|
32
|
+
"min": 1,
|
|
33
|
+
"max": 20,
|
|
34
|
+
"step": 0.5,
|
|
35
|
+
"unit": "",
|
|
36
|
+
"default": 4,
|
|
37
|
+
"defaultFrom": "desk"
|
|
38
|
+
},
|
|
39
|
+
"kneeDb": {
|
|
40
|
+
"min": 0,
|
|
41
|
+
"max": 24,
|
|
42
|
+
"step": 0.5,
|
|
43
|
+
"unit": "dB",
|
|
44
|
+
"default": 6,
|
|
45
|
+
"defaultFrom": "desk"
|
|
46
|
+
},
|
|
47
|
+
"attackMs": {
|
|
48
|
+
"min": 0.1,
|
|
49
|
+
"max": 100,
|
|
50
|
+
"step": 1,
|
|
51
|
+
"unit": "ms",
|
|
52
|
+
"default": 5,
|
|
53
|
+
"defaultFrom": "desk"
|
|
54
|
+
},
|
|
55
|
+
"releaseMs": {
|
|
56
|
+
"min": 5,
|
|
57
|
+
"max": 3000,
|
|
58
|
+
"step": 10,
|
|
59
|
+
"unit": "ms",
|
|
60
|
+
"default": 200,
|
|
61
|
+
"defaultFrom": "desk"
|
|
62
|
+
},
|
|
63
|
+
"makeupDb": {
|
|
64
|
+
"min": 0,
|
|
65
|
+
"max": 24,
|
|
66
|
+
"step": 0.5,
|
|
67
|
+
"unit": "dB",
|
|
68
|
+
"default": 0,
|
|
69
|
+
"defaultFrom": "desk"
|
|
70
|
+
},
|
|
71
|
+
"mixPct": {
|
|
72
|
+
"min": 0,
|
|
73
|
+
"max": 100,
|
|
74
|
+
"step": 5,
|
|
75
|
+
"unit": "%",
|
|
76
|
+
"default": 100,
|
|
77
|
+
"defaultFrom": "desk"
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* The program-dependent release's model constants — the LA-2A's opto cell as DATA (`docs/design/specs/2026-09-26-compressor-models.md` §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.
|
|
83
|
+
* @see data/kernels/comp.json
|
|
84
|
+
*/
|
|
85
|
+
export const PROGRAM_RELEASE = {
|
|
86
|
+
"chargeMs": 1000,
|
|
87
|
+
"dischargeMs": 5000,
|
|
88
|
+
"profiles": {
|
|
89
|
+
"opto": {
|
|
90
|
+
"fastMs": 70,
|
|
91
|
+
"slowMinMs": 110,
|
|
92
|
+
"slowMaxMs": 1100,
|
|
93
|
+
"share": 0.5
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* 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 `output-delay-ceiling.test.ts`. 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.
|
|
100
|
+
* @see data/kernels/delay.json
|
|
101
|
+
*/
|
|
102
|
+
export const FX_DELAY_TIME_RANGE = {
|
|
103
|
+
"min": 0,
|
|
104
|
+
"max": 2000,
|
|
105
|
+
"step": 1,
|
|
106
|
+
"unit": "ms",
|
|
107
|
+
"default": 300,
|
|
108
|
+
"defaultFrom": "desk"
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* The FX delay's REGENERATION travel — how much of the wet tail feeds back in. Stops short of 1: unity feedback is a runaway the kernel hard-clamps anyway, so offering it would draw travel the DSP refuses. Not NORMALIZED_RANGE for exactly that reason — it is a 0..1 quantity whose top the DSP does not accept, and a control must not offer a value its actuator will eat.
|
|
113
|
+
* @see data/kernels/delay.json
|
|
114
|
+
*/
|
|
115
|
+
export const FX_DELAY_FEEDBACK_RANGE = {
|
|
116
|
+
"min": 0,
|
|
117
|
+
"max": 0.99,
|
|
118
|
+
"step": 0,
|
|
119
|
+
"unit": "",
|
|
120
|
+
"default": 0.3,
|
|
121
|
+
"defaultFrom": "desk"
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* The FX delay's TONE — a NORMALIZED_RANGE instance with its own come-up value, matching `DEFAULT_DELAY_STATE.tone`. See REVERB_SIZE_RANGE for why this is a named constant rather than a default on the shared shape.
|
|
126
|
+
* @see data/kernels/delay.json
|
|
127
|
+
*/
|
|
128
|
+
export const DELAY_TONE_RANGE = {
|
|
129
|
+
"min": 0,
|
|
130
|
+
"max": 1,
|
|
131
|
+
"step": 0,
|
|
132
|
+
"unit": "",
|
|
133
|
+
"default": 0.3,
|
|
134
|
+
"defaultFrom": "desk"
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* The FX DELAY's wet/dry — the same split as REVERB_MIX_RANGE, its own declaration.
|
|
139
|
+
* @see data/kernels/delay.json
|
|
140
|
+
*/
|
|
141
|
+
export const DELAY_MIX_RANGE = {
|
|
142
|
+
"min": 0,
|
|
143
|
+
"max": 1,
|
|
144
|
+
"step": 0,
|
|
145
|
+
"unit": "",
|
|
146
|
+
"default": 0.3,
|
|
147
|
+
"defaultFrom": "desk",
|
|
148
|
+
"byKind": {
|
|
149
|
+
"fxReturn": 1
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* 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 server's `DEFAULT_DELAY_STATE` (which now reads it) so the DPF plugin generator (`packages/omx-plugins/tools/params-gen.mjs`, `2026-09-25-omx-plugins-dpf.md` §3a) reads the same fact the desk seeds a fresh strip with.
|
|
155
|
+
* @see data/kernels/delay.json
|
|
156
|
+
*/
|
|
157
|
+
export const FX_DELAY_PINGPONG_DEFAULT = false;
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* 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.
|
|
161
|
+
* @see data/kernels/drive.json
|
|
162
|
+
*/
|
|
163
|
+
export const DRIVE_BIAS_MAX = 0.7071067811865476;
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* 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 (`output-delay-ceiling.test.ts` 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.
|
|
167
|
+
* @see data/kernels/eq.json
|
|
168
|
+
*/
|
|
169
|
+
export const EQ_MAX_BANDS = 24;
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* The standard ISO 266 one-third-octave centre frequencies, 20 Hz–20 kHz (31 bands) — the classic 31-band graphic-EQ layout's centres.
|
|
173
|
+
* @see data/kernels/eq.json
|
|
174
|
+
*/
|
|
175
|
+
export const ISO_THIRD_OCTAVE_CENTRES_HZ = [
|
|
176
|
+
20,
|
|
177
|
+
25,
|
|
178
|
+
31.5,
|
|
179
|
+
40,
|
|
180
|
+
50,
|
|
181
|
+
63,
|
|
182
|
+
80,
|
|
183
|
+
100,
|
|
184
|
+
125,
|
|
185
|
+
160,
|
|
186
|
+
200,
|
|
187
|
+
250,
|
|
188
|
+
315,
|
|
189
|
+
400,
|
|
190
|
+
500,
|
|
191
|
+
630,
|
|
192
|
+
800,
|
|
193
|
+
1000,
|
|
194
|
+
1250,
|
|
195
|
+
1600,
|
|
196
|
+
2000,
|
|
197
|
+
2500,
|
|
198
|
+
3150,
|
|
199
|
+
4000,
|
|
200
|
+
5000,
|
|
201
|
+
6300,
|
|
202
|
+
8000,
|
|
203
|
+
10000,
|
|
204
|
+
12500,
|
|
205
|
+
16000,
|
|
206
|
+
20000
|
|
207
|
+
];
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* The graphic EQ's section count: DERIVED from ISO_THIRD_OCTAVE_CENTRES_HZ, never a second literal. Generated into `omx_contract_limits.h` as `OMX_GEQ_BANDS`, which sizes `mix_geq.h`'s section array — its OWN budget, never a claimant on EQ_MAX_BANDS (graphic-eq-31 spec §3, roster ruling 3).
|
|
211
|
+
* @see data/kernels/eq.json
|
|
212
|
+
*/
|
|
213
|
+
export const GEQ_BANDS = 31;
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* 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).
|
|
217
|
+
* @see data/kernels/gate.json
|
|
218
|
+
*/
|
|
219
|
+
export const GATE_LIMITS = {
|
|
220
|
+
"thresholdDb": {
|
|
221
|
+
"min": -80,
|
|
222
|
+
"max": 0,
|
|
223
|
+
"step": 1,
|
|
224
|
+
"unit": "dB",
|
|
225
|
+
"default": -40,
|
|
226
|
+
"defaultFrom": "desk"
|
|
227
|
+
},
|
|
228
|
+
"rangeDb": {
|
|
229
|
+
"min": -90,
|
|
230
|
+
"max": 0,
|
|
231
|
+
"step": 1,
|
|
232
|
+
"unit": "dB",
|
|
233
|
+
"default": -90,
|
|
234
|
+
"defaultFrom": "desk"
|
|
235
|
+
},
|
|
236
|
+
"kneeStartDb": {
|
|
237
|
+
"min": -80,
|
|
238
|
+
"max": 0,
|
|
239
|
+
"step": 1,
|
|
240
|
+
"unit": "dB",
|
|
241
|
+
"default": -43,
|
|
242
|
+
"defaultFrom": "desk"
|
|
243
|
+
},
|
|
244
|
+
"kneeEndDb": {
|
|
245
|
+
"min": -80,
|
|
246
|
+
"max": 0,
|
|
247
|
+
"step": 1,
|
|
248
|
+
"unit": "dB",
|
|
249
|
+
"default": -37,
|
|
250
|
+
"defaultFrom": "desk"
|
|
251
|
+
},
|
|
252
|
+
"attackMs": {
|
|
253
|
+
"min": 0,
|
|
254
|
+
"max": 500,
|
|
255
|
+
"step": 0.5,
|
|
256
|
+
"unit": "ms",
|
|
257
|
+
"default": 1,
|
|
258
|
+
"defaultFrom": "desk"
|
|
259
|
+
},
|
|
260
|
+
"holdMs": {
|
|
261
|
+
"min": 0,
|
|
262
|
+
"max": 2000,
|
|
263
|
+
"step": 5,
|
|
264
|
+
"unit": "ms",
|
|
265
|
+
"default": 10,
|
|
266
|
+
"defaultFrom": "desk"
|
|
267
|
+
},
|
|
268
|
+
"releaseMs": {
|
|
269
|
+
"min": 0,
|
|
270
|
+
"max": 5000,
|
|
271
|
+
"step": 10,
|
|
272
|
+
"unit": "ms",
|
|
273
|
+
"default": 100,
|
|
274
|
+
"defaultFrom": "desk"
|
|
275
|
+
},
|
|
276
|
+
"hysteresisDb": {
|
|
277
|
+
"min": 0,
|
|
278
|
+
"max": 24,
|
|
279
|
+
"step": 0.5,
|
|
280
|
+
"unit": "dB",
|
|
281
|
+
"default": 3,
|
|
282
|
+
"defaultFrom": "desk"
|
|
283
|
+
},
|
|
284
|
+
"ratio": {
|
|
285
|
+
"min": 1,
|
|
286
|
+
"max": 100,
|
|
287
|
+
"step": 1,
|
|
288
|
+
"unit": "",
|
|
289
|
+
"default": 16,
|
|
290
|
+
"defaultFrom": "desk"
|
|
291
|
+
}
|
|
292
|
+
};
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* The precision limiter's travels (`2026-09-27-precision-limiter.md` §2), rendered into `omx_contract_limits.h` as `OMX_LIMITER_*` by `harness/contract-limits-gen.mjs`, 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.
|
|
296
|
+
* @see data/kernels/limiter.json
|
|
297
|
+
*/
|
|
298
|
+
export const LIMITER_LIMITS = {
|
|
299
|
+
"ceilingDb": {
|
|
300
|
+
"min": -12,
|
|
301
|
+
"max": 0,
|
|
302
|
+
"step": 0.1,
|
|
303
|
+
"unit": "dBFS",
|
|
304
|
+
"default": -1,
|
|
305
|
+
"defaultFrom": "desk"
|
|
306
|
+
},
|
|
307
|
+
"lookaheadMs": {
|
|
308
|
+
"min": 0.5,
|
|
309
|
+
"max": 5,
|
|
310
|
+
"step": 0.1,
|
|
311
|
+
"unit": "ms",
|
|
312
|
+
"default": 1.5,
|
|
313
|
+
"defaultFrom": "desk"
|
|
314
|
+
},
|
|
315
|
+
"releaseMs": {
|
|
316
|
+
"min": 1,
|
|
317
|
+
"max": 1000,
|
|
318
|
+
"step": 1,
|
|
319
|
+
"unit": "ms",
|
|
320
|
+
"default": 50,
|
|
321
|
+
"defaultFrom": "desk"
|
|
322
|
+
}
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* PITCH_LIMITS, moved from openmixer.
|
|
327
|
+
* @see data/kernels/pitch.json
|
|
328
|
+
*/
|
|
329
|
+
export const PITCH_LIMITS = {
|
|
330
|
+
"semitones": {
|
|
331
|
+
"min": -12,
|
|
332
|
+
"max": 12,
|
|
333
|
+
"default": 0
|
|
334
|
+
},
|
|
335
|
+
"cents": {
|
|
336
|
+
"min": -50,
|
|
337
|
+
"max": 50,
|
|
338
|
+
"default": 0
|
|
339
|
+
},
|
|
340
|
+
"mix": {
|
|
341
|
+
"min": 0,
|
|
342
|
+
"max": 100,
|
|
343
|
+
"default": 100
|
|
344
|
+
}
|
|
345
|
+
};
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* PITCH_KERNEL, moved from openmixer.
|
|
349
|
+
* @see data/kernels/pitch.json
|
|
350
|
+
*/
|
|
351
|
+
export const PITCH_KERNEL = {
|
|
352
|
+
"windowMs": 40,
|
|
353
|
+
"prefilterCeilingHz": 20000,
|
|
354
|
+
"prefilterQ": 0.7071067811865476
|
|
355
|
+
};
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* 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 (`2026-09-26-native-fx-catalogue.md` §2, Reverb).
|
|
359
|
+
* @see data/kernels/reverb.json
|
|
360
|
+
*/
|
|
361
|
+
export const REVERB_PLATE_MOD_DEPTH_RANGE = {
|
|
362
|
+
"min": 0,
|
|
363
|
+
"max": 400,
|
|
364
|
+
"step": 1,
|
|
365
|
+
"unit": "%",
|
|
366
|
+
"default": 100,
|
|
367
|
+
"defaultFrom": "desk"
|
|
368
|
+
};
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* The legal range of each transient-designer field (engineering units), transient spec §3. Every kind comes up flat: no per-kind default differs. `harness/contract-limits-gen.mjs` 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).
|
|
372
|
+
* @see data/kernels/transient.json
|
|
373
|
+
*/
|
|
374
|
+
export const TRANSIENT_LIMITS = {
|
|
375
|
+
"attackDb": {
|
|
376
|
+
"min": -24,
|
|
377
|
+
"max": 24,
|
|
378
|
+
"step": 0.1,
|
|
379
|
+
"unit": "dB",
|
|
380
|
+
"default": 0,
|
|
381
|
+
"defaultFrom": "desk"
|
|
382
|
+
},
|
|
383
|
+
"sustainDb": {
|
|
384
|
+
"min": -24,
|
|
385
|
+
"max": 24,
|
|
386
|
+
"step": 0.1,
|
|
387
|
+
"unit": "dB",
|
|
388
|
+
"default": 0,
|
|
389
|
+
"defaultFrom": "desk"
|
|
390
|
+
},
|
|
391
|
+
"attackTimeMs": {
|
|
392
|
+
"min": 2,
|
|
393
|
+
"max": 50,
|
|
394
|
+
"step": 0.1,
|
|
395
|
+
"unit": "ms",
|
|
396
|
+
"default": 10,
|
|
397
|
+
"defaultFrom": "desk"
|
|
398
|
+
},
|
|
399
|
+
"sustainTimeMs": {
|
|
400
|
+
"min": 50,
|
|
401
|
+
"max": 2000,
|
|
402
|
+
"step": 1,
|
|
403
|
+
"unit": "ms",
|
|
404
|
+
"default": 250,
|
|
405
|
+
"defaultFrom": "desk"
|
|
406
|
+
},
|
|
407
|
+
"outputDb": {
|
|
408
|
+
"min": -24,
|
|
409
|
+
"max": 12,
|
|
410
|
+
"step": 0.1,
|
|
411
|
+
"unit": "dB",
|
|
412
|
+
"default": 0,
|
|
413
|
+
"defaultFrom": "desk"
|
|
414
|
+
}
|
|
415
|
+
};
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
* The fast follower's attack, ms: exactly the dynamics detector's no-oversampling line (transient spec §3, L7).
|
|
419
|
+
* @see data/kernels/transient.json
|
|
420
|
+
*/
|
|
421
|
+
export const TRANSIENT_FAST_ATTACK_MS = 0.5;
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* The fast follower's release, ms: one 50 Hz cycle held, a 180 bpm sixteenth forgotten (transient spec §3).
|
|
425
|
+
* @see data/kernels/transient.json
|
|
426
|
+
*/
|
|
427
|
+
export const TRANSIENT_FAST_RELEASE_MS = 20;
|
|
428
|
+
|
|
429
|
+
/**
|
|
430
|
+
* The contrast, dB, at which a knob reaches its full value (transient spec §2, §3).
|
|
431
|
+
* @see data/kernels/transient.json
|
|
432
|
+
*/
|
|
433
|
+
export const TRANSIENT_REF_DB = 6;
|
|
434
|
+
|
|
435
|
+
/**
|
|
436
|
+
* The detector floor, linear (−100 dBFS): below it both envelopes read the floor and the stage is unity (transient spec §3).
|
|
437
|
+
* @see data/kernels/transient.json
|
|
438
|
+
*/
|
|
439
|
+
export const TRANSIENT_FLOOR_LIN = 0.00001;
|
|
440
|
+
|
|
441
|
+
/**
|
|
442
|
+
* The delay plugin's parameters, in append-only order: DPF's parameter index is the CLAP param id and the LV2 port order (omx-plugins-dpf §3b). Moved from openmixer's packages/omx-plugins/tools/params-gen.mjs PLUGINS.delay.
|
|
443
|
+
*
|
|
444
|
+
* Why: mix is per instance on the desk (insert or fxReturn); a plugin racked in a foreign host is an INSERT, so it reads the input kind's default (omx-plugins-dpf §3a).
|
|
445
|
+
* @see data/plugins/delay.json
|
|
446
|
+
*/
|
|
447
|
+
export const DELAY_PLUGIN = {
|
|
448
|
+
"plugin": "delay",
|
|
449
|
+
"header": "omx_delay_params.h",
|
|
450
|
+
"prefix": "OMX_DELAY",
|
|
451
|
+
"params": [
|
|
452
|
+
{
|
|
453
|
+
"symbol": "timeMs",
|
|
454
|
+
"min": 0,
|
|
455
|
+
"max": 2000,
|
|
456
|
+
"def": 300,
|
|
457
|
+
"step": 1,
|
|
458
|
+
"unit": "ms",
|
|
459
|
+
"toggle": false
|
|
460
|
+
},
|
|
461
|
+
{
|
|
462
|
+
"symbol": "feedback",
|
|
463
|
+
"min": 0,
|
|
464
|
+
"max": 0.99,
|
|
465
|
+
"def": 0.3,
|
|
466
|
+
"step": 0,
|
|
467
|
+
"unit": "",
|
|
468
|
+
"toggle": false
|
|
469
|
+
},
|
|
470
|
+
{
|
|
471
|
+
"symbol": "mix",
|
|
472
|
+
"min": 0,
|
|
473
|
+
"max": 1,
|
|
474
|
+
"def": 0.3,
|
|
475
|
+
"step": 0,
|
|
476
|
+
"unit": "",
|
|
477
|
+
"toggle": false
|
|
478
|
+
},
|
|
479
|
+
{
|
|
480
|
+
"symbol": "tone",
|
|
481
|
+
"min": 0,
|
|
482
|
+
"max": 1,
|
|
483
|
+
"def": 0.3,
|
|
484
|
+
"step": 0,
|
|
485
|
+
"unit": "",
|
|
486
|
+
"toggle": false
|
|
487
|
+
},
|
|
488
|
+
{
|
|
489
|
+
"symbol": "pingpong",
|
|
490
|
+
"min": 0,
|
|
491
|
+
"max": 1,
|
|
492
|
+
"def": 0,
|
|
493
|
+
"step": 1,
|
|
494
|
+
"unit": "",
|
|
495
|
+
"toggle": true
|
|
496
|
+
}
|
|
497
|
+
]
|
|
498
|
+
};
|
|
499
|
+
|
|
500
|
+
/**
|
|
501
|
+
* The Q of a second-order Butterworth section, 1/√2 — maximally flat, the one value every Butterworth biquad in the tree designs at: the LR4 crossover section, the pitch pre-filter and the drive's tilt / band / HF sections, in TS and (as `OMX_BUTTERWORTH_Q`) in C (§7, the scalar door).
|
|
502
|
+
* @see data/primitives.json
|
|
503
|
+
*/
|
|
504
|
+
export const BUTTERWORTH_Q = 0.7071067811865476;
|
|
505
|
+
|
|
506
|
+
/**
|
|
507
|
+
* ALLPASS_LIMITS, moved from openmixer.
|
|
508
|
+
* @see data/primitives.json
|
|
509
|
+
*/
|
|
510
|
+
export const ALLPASS_LIMITS = {
|
|
511
|
+
"unityTolerance": 0.0001
|
|
512
|
+
};
|
|
513
|
+
|
|
514
|
+
/**
|
|
515
|
+
* XOVER_LIMITS, moved from openmixer.
|
|
516
|
+
* @see data/primitives.json
|
|
517
|
+
*/
|
|
518
|
+
export const XOVER_LIMITS = {
|
|
519
|
+
"lr2SectionQ": 0.5,
|
|
520
|
+
"lr4SectionQ": 0.7071067811865476,
|
|
521
|
+
"partitionTolerance": 0.00001
|
|
522
|
+
};
|
|
523
|
+
|
|
524
|
+
/**
|
|
525
|
+
* The order the chorus and flanger construct their lines with (four taps; the fdelay spec §1).
|
|
526
|
+
* @see data/primitives.json
|
|
527
|
+
*/
|
|
528
|
+
export const FDELAY_MOD_READ_ORDER = 3;
|
|
529
|
+
|
|
530
|
+
/**
|
|
531
|
+
* `Λ` for the chorus/flanger read — ONE value; the header and every law read this.
|
|
532
|
+
* @see data/primitives.json
|
|
533
|
+
*/
|
|
534
|
+
export const FDELAY_READ_L1_NORM = 1.25;
|
|
535
|
+
|
|
536
|
+
/**
|
|
537
|
+
* 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` (`2026-07-15-clock-rate-honest-force-rate.md`) — this is the ceiling a write is refused by, never a menu.
|
|
538
|
+
* @see data/rates.json
|
|
539
|
+
*/
|
|
540
|
+
export const STANDARD_SAMPLE_RATES = [
|
|
541
|
+
44100,
|
|
542
|
+
48000,
|
|
543
|
+
88200,
|
|
544
|
+
96000,
|
|
545
|
+
176400,
|
|
546
|
+
192000
|
|
547
|
+
];
|
|
548
|
+
|
|
549
|
+
/**
|
|
550
|
+
* THE declaration: 192 kHz at quantum 128.
|
|
551
|
+
* @see data/rates.json
|
|
552
|
+
*/
|
|
553
|
+
export const RT_HARD_TARGET = {
|
|
554
|
+
"rate": 192000,
|
|
555
|
+
"quantum": 128
|
|
556
|
+
};
|
|
557
|
+
|
|
558
|
+
/**
|
|
559
|
+
* The rate a unit-range DSP knob is quoted at (R-058): the rate this desk runs (ruling 2026-09-14). A kernel raises the knob to `REF / sr`, so at this rate the exponent is exactly 1 and the response is bit-for-bit the one cut before the law. Emitted to C as `OMX_DSP_KNOB_REFERENCE_RATE`; the reverb damping and FX-delay tone references `#define` from it.
|
|
560
|
+
* @see data/rates.json
|
|
561
|
+
*/
|
|
562
|
+
export const DSP_KNOB_REFERENCE_RATE = 96000;
|