@openmixer/omx-contract 1.2.1 → 2.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/README.md +41 -4
- package/bin/omx-contract.mjs +14 -3
- package/data/kernels/balance.json +18 -14
- package/data/kernels/band_dyn.json +132 -0
- package/data/kernels/chorus.json +87 -56
- package/data/kernels/comp.json +67 -29
- package/data/kernels/deesser.json +114 -86
- package/data/kernels/delay.json +67 -57
- package/data/kernels/drive.json +118 -87
- package/data/kernels/eq.json +284 -113
- package/data/kernels/fbs.json +150 -0
- package/data/kernels/flanger.json +74 -44
- package/data/kernels/gate.json +76 -21
- package/data/kernels/geq.json +32 -27
- package/data/kernels/hrp.json +68 -0
- package/data/kernels/limiter.json +25 -9
- package/data/kernels/mixmatrix.json +11 -0
- package/data/kernels/phaser.json +110 -100
- package/data/kernels/pitch.json +35 -17
- package/data/kernels/reverb.json +176 -142
- package/data/kernels/rotary.json +189 -177
- package/data/kernels/rta.json +17 -0
- package/data/kernels/transient.json +64 -36
- package/data/kernels/tremolo.json +59 -48
- package/data/primitives.json +51 -0
- package/data/rates.json +29 -0
- package/dist/ts/omx-contract.d.ts +527 -21
- package/dist/ts/omx-contract.js +832 -57
- package/include/omxcontract/omx_contract_limits.h +233 -0
- package/lib/data.mjs +115 -3
- package/lib/eq-defaults.mjs +87 -0
- package/lib/fmt.mjs +24 -4
- package/lib/semver.mjs +12 -2
- package/lib/validate.mjs +99 -3
- package/package.json +1 -1
- package/render/c.mjs +76 -10
- package/render/doors.mjs +6 -3
- package/render/ts.mjs +40 -2
- package/schema/omx-contract.schema.json +39 -3
- package/share/omx-contract/omx-contract.json +759 -71
- package/render/c/omx_plugin_param.h +0 -25
- package/render/c/params-generate.mjs +0 -83
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
// Copyright (C) 2026 Pau Aliagas <linuxnow@gmail.com>
|
|
3
3
|
#ifndef OMX_CONTRACT_LIMITS_H
|
|
4
4
|
#define OMX_CONTRACT_LIMITS_H
|
|
5
|
+
#include <math.h>
|
|
5
6
|
/*
|
|
6
7
|
* GENERATED — DO NOT EDIT BY HAND.
|
|
7
8
|
* Produced by `omx-contract render --target c` from FreeMixer/omx-contract's data/, the declaration
|
|
@@ -128,13 +129,43 @@
|
|
|
128
129
|
* is an integer literal, any other a float literal AND its OMX_<macro>_DOUBLE spelling. */
|
|
129
130
|
#define OMX_ALLPASS_UNITY_TOLERANCE 0.0001f
|
|
130
131
|
#define OMX_ALLPASS_UNITY_TOLERANCE_DOUBLE 0.0001
|
|
132
|
+
#define OMX_BAND_DYN_ATTACK_RANGE_DEFAULT 5
|
|
133
|
+
#define OMX_BAND_DYN_ATTACK_RANGE_MAX 100
|
|
134
|
+
#define OMX_BAND_DYN_ATTACK_RANGE_MIN 0.5f
|
|
135
|
+
#define OMX_BAND_DYN_ATTACK_RANGE_MIN_DOUBLE 0.5
|
|
136
|
+
#define OMX_BAND_DYN_ATTACK_RANGE_STEP 0.1f
|
|
137
|
+
#define OMX_BAND_DYN_ATTACK_RANGE_STEP_DOUBLE 0.1
|
|
138
|
+
#define OMX_BAND_DYN_KNEE_DB 6
|
|
139
|
+
#define OMX_BAND_DYN_MAX_BANDS 9
|
|
140
|
+
#define OMX_BAND_DYN_RANGE_RANGE_DEFAULT -6
|
|
141
|
+
#define OMX_BAND_DYN_RANGE_RANGE_MAX 12
|
|
142
|
+
#define OMX_BAND_DYN_RANGE_RANGE_MIN -24
|
|
143
|
+
#define OMX_BAND_DYN_RANGE_RANGE_STEP 0.5f
|
|
144
|
+
#define OMX_BAND_DYN_RANGE_RANGE_STEP_DOUBLE 0.5
|
|
145
|
+
#define OMX_BAND_DYN_RATIO_RANGE_DEFAULT 2
|
|
146
|
+
#define OMX_BAND_DYN_RATIO_RANGE_MAX 20
|
|
147
|
+
#define OMX_BAND_DYN_RATIO_RANGE_MIN 1
|
|
148
|
+
#define OMX_BAND_DYN_RATIO_RANGE_STEP 0.1f
|
|
149
|
+
#define OMX_BAND_DYN_RATIO_RANGE_STEP_DOUBLE 0.1
|
|
150
|
+
#define OMX_BAND_DYN_RELEASE_RANGE_DEFAULT 100
|
|
151
|
+
#define OMX_BAND_DYN_RELEASE_RANGE_MAX 3000
|
|
152
|
+
#define OMX_BAND_DYN_RELEASE_RANGE_MIN 5
|
|
153
|
+
#define OMX_BAND_DYN_RELEASE_RANGE_STEP 1
|
|
154
|
+
#define OMX_BAND_DYN_THRESHOLD_RANGE_DEFAULT -30
|
|
155
|
+
#define OMX_BAND_DYN_THRESHOLD_RANGE_MAX 0
|
|
156
|
+
#define OMX_BAND_DYN_THRESHOLD_RANGE_MIN -60
|
|
157
|
+
#define OMX_BAND_DYN_THRESHOLD_RANGE_STEP 0.5f
|
|
158
|
+
#define OMX_BAND_DYN_THRESHOLD_RANGE_STEP_DOUBLE 0.5
|
|
159
|
+
#define OMX_BUS_INPUT_CAP 128
|
|
131
160
|
#define OMX_BUTTERWORTH_Q 0.7071067811865476f
|
|
132
161
|
#define OMX_BUTTERWORTH_Q_DOUBLE 0.7071067811865476
|
|
162
|
+
#define OMX_CHORUS_BASE_MS 10
|
|
133
163
|
#define OMX_CHORUS_DEPTH_RANGE_DEFAULT 4
|
|
134
164
|
#define OMX_CHORUS_DEPTH_RANGE_MAX 12
|
|
135
165
|
#define OMX_CHORUS_DEPTH_RANGE_MIN 0
|
|
136
166
|
#define OMX_CHORUS_DEPTH_RANGE_STEP 0.1f
|
|
137
167
|
#define OMX_CHORUS_DEPTH_RANGE_STEP_DOUBLE 0.1
|
|
168
|
+
#define OMX_CHORUS_MAX_MS 22
|
|
138
169
|
#define OMX_CHORUS_MIX_RANGE_DEFAULT 35
|
|
139
170
|
#define OMX_CHORUS_MIX_RANGE_MAX 100
|
|
140
171
|
#define OMX_CHORUS_MIX_RANGE_MIN 0
|
|
@@ -157,6 +188,7 @@
|
|
|
157
188
|
#define OMX_CHORUS_VOICES_RANGE_MAX 4
|
|
158
189
|
#define OMX_CHORUS_VOICES_RANGE_MIN 1
|
|
159
190
|
#define OMX_CHORUS_VOICES_RANGE_STEP 1
|
|
191
|
+
#define OMX_DEEP_PLATEAU_FRAMES 20
|
|
160
192
|
#define OMX_DEESS_ATTACK_RANGE_DEFAULT 1
|
|
161
193
|
#define OMX_DEESS_ATTACK_RANGE_MAX 50
|
|
162
194
|
#define OMX_DEESS_ATTACK_RANGE_MIN 0.1f
|
|
@@ -193,6 +225,20 @@
|
|
|
193
225
|
#define OMX_DEESS_WIDTH_RANGE_MIN_DOUBLE 0.25
|
|
194
226
|
#define OMX_DEESS_WIDTH_RANGE_STEP 0.05f
|
|
195
227
|
#define OMX_DEESS_WIDTH_RANGE_STEP_DOUBLE 0.05
|
|
228
|
+
#define OMX_DEFAULT_THRESHOLDS_GROWTH_CONFIRM_FRAMES 2
|
|
229
|
+
#define OMX_DEFAULT_THRESHOLDS_GROWTH_MAX_DIP_DB 0.5f
|
|
230
|
+
#define OMX_DEFAULT_THRESHOLDS_GROWTH_MAX_DIP_DB_DOUBLE 0.5
|
|
231
|
+
#define OMX_DEFAULT_THRESHOLDS_GROWTH_MAX_SINGLE_FRAME_SHARE 0.5f
|
|
232
|
+
#define OMX_DEFAULT_THRESHOLDS_GROWTH_MAX_SINGLE_FRAME_SHARE_DOUBLE 0.5
|
|
233
|
+
#define OMX_DEFAULT_THRESHOLDS_GROWTH_MIN_DB_PER_FRAME 0.8f
|
|
234
|
+
#define OMX_DEFAULT_THRESHOLDS_GROWTH_MIN_DB_PER_FRAME_DOUBLE 0.8
|
|
235
|
+
#define OMX_DEFAULT_THRESHOLDS_GROWTH_MIN_TOTAL_RISE_DB 6
|
|
236
|
+
#define OMX_DEFAULT_THRESHOLDS_PAPR_DB 18
|
|
237
|
+
#define OMX_DEFAULT_THRESHOLDS_PERSIST_FRAMES 5
|
|
238
|
+
#define OMX_DEFAULT_THRESHOLDS_PHPR_DB 9
|
|
239
|
+
#define OMX_DEFAULT_THRESHOLDS_PNPR_DB 12
|
|
240
|
+
#define OMX_DEFAULT_THRESHOLDS_PSHR_MIN_DB 10
|
|
241
|
+
#define OMX_DEFAULT_THRESHOLDS_SUB_CLEAN_FRAMES 5
|
|
196
242
|
#define OMX_DELAY_MIX_RANGE_BY_KIND_FX_RETURN 1
|
|
197
243
|
#define OMX_DELAY_MIX_RANGE_DEFAULT 0.3f
|
|
198
244
|
#define OMX_DELAY_MIX_RANGE_DEFAULT_DOUBLE 0.3
|
|
@@ -204,6 +250,8 @@
|
|
|
204
250
|
#define OMX_DELAY_TONE_RANGE_MAX 1
|
|
205
251
|
#define OMX_DELAY_TONE_RANGE_MIN 0
|
|
206
252
|
#define OMX_DELAY_TONE_RANGE_STEP 0
|
|
253
|
+
#define OMX_DETECTOR_OVERSAMPLE_AUTO_MS 0.5f
|
|
254
|
+
#define OMX_DETECTOR_OVERSAMPLE_AUTO_MS_DOUBLE 0.5
|
|
207
255
|
#define OMX_DRIVE_AMOUNT_RANGE_DEFAULT 0
|
|
208
256
|
#define OMX_DRIVE_AMOUNT_RANGE_MAX 36
|
|
209
257
|
#define OMX_DRIVE_AMOUNT_RANGE_MIN 0
|
|
@@ -231,6 +279,18 @@
|
|
|
231
279
|
#define OMX_DRIVE_TRIM_RANGE_STEP 0.1f
|
|
232
280
|
#define OMX_DRIVE_TRIM_RANGE_STEP_DOUBLE 0.1
|
|
233
281
|
#define OMX_DSP_KNOB_REFERENCE_RATE 96000
|
|
282
|
+
#define OMX_EQ_BAND_COUNTS_CHANNEL_DEFAULT 4
|
|
283
|
+
#define OMX_EQ_BAND_COUNTS_CHANNEL_MAX 24
|
|
284
|
+
#define OMX_EQ_BAND_COUNTS_EQ16_DEFAULT 16
|
|
285
|
+
#define OMX_EQ_BAND_COUNTS_EQ16_MAX 16
|
|
286
|
+
#define OMX_EQ_BAND_COUNTS_EQ32_DEFAULT 32
|
|
287
|
+
#define OMX_EQ_BAND_COUNTS_EQ32_MAX 32
|
|
288
|
+
#define OMX_EQ_BAND_COUNTS_EQ8_DEFAULT 8
|
|
289
|
+
#define OMX_EQ_BAND_COUNTS_EQ8_MAX 8
|
|
290
|
+
#define OMX_EQ_BAND_COUNTS_STRIP_DEFAULT 4
|
|
291
|
+
#define OMX_EQ_BAND_COUNTS_STRIP_MAX 4
|
|
292
|
+
#define OMX_EQ_BAND_DEFAULTS_GAIN_DB 0
|
|
293
|
+
#define OMX_EQ_BAND_DEFAULTS_Q 1
|
|
234
294
|
#define OMX_EQ_FREQ_RANGE_MAX 20000
|
|
235
295
|
#define OMX_EQ_FREQ_RANGE_MIN 20
|
|
236
296
|
#define OMX_EQ_FREQ_RANGE_STEP 10
|
|
@@ -243,14 +303,29 @@
|
|
|
243
303
|
#define OMX_EQ_NOTCH_Q_RANGE_MIN 0.3f
|
|
244
304
|
#define OMX_EQ_NOTCH_Q_RANGE_MIN_DOUBLE 0.3
|
|
245
305
|
#define OMX_EQ_NOTCH_Q_RANGE_STEP 1
|
|
306
|
+
#define OMX_EQ_PASS_FILTER_DEFAULTS_HPF_FREQ_HZ 80
|
|
307
|
+
#define OMX_EQ_PASS_FILTER_DEFAULTS_LPF_FREQ_HZ 18000
|
|
246
308
|
#define OMX_EQ_Q_RANGE_MAX 8
|
|
247
309
|
#define OMX_EQ_Q_RANGE_MIN 0.3f
|
|
248
310
|
#define OMX_EQ_Q_RANGE_MIN_DOUBLE 0.3
|
|
249
311
|
#define OMX_EQ_Q_RANGE_STEP 0.1f
|
|
250
312
|
#define OMX_EQ_Q_RANGE_STEP_DOUBLE 0.1
|
|
313
|
+
#define OMX_FBS_DEFAULT_MAX_AUTO_BANDS 6
|
|
314
|
+
#define OMX_FBS_DEFAULT_NOTCH_Q 116
|
|
315
|
+
#define OMX_FBS_FLOOR_LIN 1e-12f
|
|
316
|
+
#define OMX_FBS_FLOOR_LIN_DOUBLE 1e-12
|
|
317
|
+
#define OMX_FBS_MAX_NOTCH_DEPTH_DB 18
|
|
318
|
+
#define OMX_FBS_PAPR_GUARD_BINS 2
|
|
319
|
+
#define OMX_FBS_PHPR_HARMONICS 3
|
|
320
|
+
#define OMX_FBS_PNPR_GUARD_BINS 1
|
|
321
|
+
#define OMX_FBS_PNPR_RADIUS_BINS 3
|
|
322
|
+
#define OMX_FBS_PSHR_SELF_SKIP_BINS 3
|
|
323
|
+
#define OMX_FBS_TRACK_SLOTS 512
|
|
251
324
|
#define OMX_FDELAY_MOD_READ_ORDER 3
|
|
252
325
|
#define OMX_FDELAY_READ_L1_NORM 1.25f
|
|
253
326
|
#define OMX_FDELAY_READ_L1_NORM_DOUBLE 1.25
|
|
327
|
+
#define OMX_FLANGER_BASE_MS 0.5f
|
|
328
|
+
#define OMX_FLANGER_BASE_MS_DOUBLE 0.5
|
|
254
329
|
#define OMX_FLANGER_DEPTH_RANGE_DEFAULT 2
|
|
255
330
|
#define OMX_FLANGER_DEPTH_RANGE_MAX 5
|
|
256
331
|
#define OMX_FLANGER_DEPTH_RANGE_MIN 0
|
|
@@ -264,6 +339,7 @@
|
|
|
264
339
|
#define OMX_FLANGER_FEEDBACK_RANGE_MIN_DOUBLE -0.95
|
|
265
340
|
#define OMX_FLANGER_FEEDBACK_RANGE_STEP 0.01f
|
|
266
341
|
#define OMX_FLANGER_FEEDBACK_RANGE_STEP_DOUBLE 0.01
|
|
342
|
+
#define OMX_FLANGER_MAX_MS 6
|
|
267
343
|
#define OMX_FLANGER_MIX_RANGE_DEFAULT 50
|
|
268
344
|
#define OMX_FLANGER_MIX_RANGE_MAX 100
|
|
269
345
|
#define OMX_FLANGER_MIX_RANGE_MIN 0
|
|
@@ -296,12 +372,35 @@
|
|
|
296
372
|
#define OMX_GEQ_BAND_RANGE_STEP_DOUBLE 0.5
|
|
297
373
|
#define OMX_GEQ_DESIGN_GAIN_MAX_DB 30
|
|
298
374
|
#define OMX_GEQ_PROTO_DB 12
|
|
375
|
+
#define OMX_GROWTH_CONFIRM_FRAMES 2
|
|
376
|
+
#define OMX_GROWTH_MAX_DIP_DB 0.5f
|
|
377
|
+
#define OMX_GROWTH_MAX_DIP_DB_DOUBLE 0.5
|
|
378
|
+
#define OMX_GROWTH_MAX_SINGLE_FRAME_SHARE 0.5f
|
|
379
|
+
#define OMX_GROWTH_MAX_SINGLE_FRAME_SHARE_DOUBLE 0.5
|
|
380
|
+
#define OMX_GROWTH_MIN_DB_PER_FRAME 0.8f
|
|
381
|
+
#define OMX_GROWTH_MIN_DB_PER_FRAME_DOUBLE 0.8
|
|
382
|
+
#define OMX_GROWTH_MIN_TOTAL_RISE_DB 6
|
|
383
|
+
#define OMX_GROWTH_WINDOW_FRAMES 5
|
|
299
384
|
#define OMX_HPF_FREQ_RANGE_MAX 1000
|
|
300
385
|
#define OMX_HPF_FREQ_RANGE_MIN 20
|
|
301
386
|
#define OMX_HPF_FREQ_RANGE_STEP 10
|
|
387
|
+
#define OMX_HRP_AMOUNT_RANGE_DEFAULT 0.5f
|
|
388
|
+
#define OMX_HRP_AMOUNT_RANGE_DEFAULT_DOUBLE 0.5
|
|
389
|
+
#define OMX_HRP_AMOUNT_RANGE_MAX 1
|
|
390
|
+
#define OMX_HRP_AMOUNT_RANGE_MIN 0
|
|
391
|
+
#define OMX_HRP_AMOUNT_RANGE_STEP 0
|
|
392
|
+
#define OMX_HRP_ATTRIBUTION_CENTS 60
|
|
393
|
+
#define OMX_HRP_BAND_Q 5
|
|
394
|
+
#define OMX_HRP_COLLISION_CENTS 100
|
|
395
|
+
#define OMX_HRP_DEFAULT_MAX_AUTO_BANDS 8
|
|
396
|
+
#define OMX_HRP_EXCESS_THRESHOLD_DB 3
|
|
397
|
+
#define OMX_HRP_GAIN_STEP_DB 2
|
|
398
|
+
#define OMX_HRP_MAX_CUT_DB 6
|
|
399
|
+
#define OMX_HRP_MAX_VOICES 8
|
|
302
400
|
#define OMX_LPF_FREQ_RANGE_MAX 20000
|
|
303
401
|
#define OMX_LPF_FREQ_RANGE_MIN 1000
|
|
304
402
|
#define OMX_LPF_FREQ_RANGE_STEP 10
|
|
403
|
+
#define OMX_OPERATOR_EQ_BANDS_RESERVE 9
|
|
305
404
|
#define OMX_PAN_RANGE_MAX 1
|
|
306
405
|
#define OMX_PAN_RANGE_MIN -1
|
|
307
406
|
#define OMX_PAN_RANGE_STEP 0
|
|
@@ -322,6 +421,7 @@
|
|
|
322
421
|
#define OMX_PHASER_FEEDBACK_RANGE_MIN_DOUBLE -0.9
|
|
323
422
|
#define OMX_PHASER_FEEDBACK_RANGE_STEP 0.01f
|
|
324
423
|
#define OMX_PHASER_FEEDBACK_RANGE_STEP_DOUBLE 0.01
|
|
424
|
+
#define OMX_PHASER_F_TOP_HZ 16000
|
|
325
425
|
#define OMX_PHASER_MIX_RANGE_DEFAULT 50
|
|
326
426
|
#define OMX_PHASER_MIX_RANGE_MAX 100
|
|
327
427
|
#define OMX_PHASER_MIX_RANGE_MIN 0
|
|
@@ -349,11 +449,14 @@
|
|
|
349
449
|
#define OMX_PROGRAM_RELEASE_PROFILES_OPTO_SHARE_DOUBLE 0.5
|
|
350
450
|
#define OMX_PROGRAM_RELEASE_PROFILES_OPTO_SLOW_MAX_MS 1100
|
|
351
451
|
#define OMX_PROGRAM_RELEASE_PROFILES_OPTO_SLOW_MIN_MS 110
|
|
452
|
+
#define OMX_PSHR_MIN_DB 10
|
|
352
453
|
#define OMX_REVERB_DAMPING_RANGE_DEFAULT 0.5f
|
|
353
454
|
#define OMX_REVERB_DAMPING_RANGE_DEFAULT_DOUBLE 0.5
|
|
354
455
|
#define OMX_REVERB_DAMPING_RANGE_MAX 1
|
|
355
456
|
#define OMX_REVERB_DAMPING_RANGE_MIN 0
|
|
356
457
|
#define OMX_REVERB_DAMPING_RANGE_STEP 0
|
|
458
|
+
#define OMX_REVERB_GATE_ATTACK_MS 1.5f
|
|
459
|
+
#define OMX_REVERB_GATE_ATTACK_MS_DOUBLE 1.5
|
|
357
460
|
#define OMX_REVERB_GATE_THRESHOLD_RANGE_DEFAULT -40
|
|
358
461
|
#define OMX_REVERB_GATE_THRESHOLD_RANGE_MAX 0
|
|
359
462
|
#define OMX_REVERB_GATE_THRESHOLD_RANGE_MIN -80
|
|
@@ -460,8 +563,12 @@
|
|
|
460
563
|
#define OMX_ROTARY_RING_FLOATS 256
|
|
461
564
|
#define OMX_ROTARY_STOP_EPS 0.0001f
|
|
462
565
|
#define OMX_ROTARY_STOP_EPS_DOUBLE 0.0001
|
|
566
|
+
#define OMX_RTA_FFT_SIZE_MAX 32768
|
|
567
|
+
#define OMX_RTA_TARGET_BIN_HZ 5.9f
|
|
568
|
+
#define OMX_RTA_TARGET_BIN_HZ_DOUBLE 5.9
|
|
463
569
|
#define OMX_RT_HARD_TARGET_QUANTUM 128
|
|
464
570
|
#define OMX_RT_HARD_TARGET_RATE 192000
|
|
571
|
+
#define OMX_SUBHARMONIC_RADIUS_BINS 2
|
|
465
572
|
#define OMX_TRANSIENT_FAST_ATTACK_MS 0.5f
|
|
466
573
|
#define OMX_TRANSIENT_FAST_ATTACK_MS_DOUBLE 0.5
|
|
467
574
|
#define OMX_TRANSIENT_FAST_RELEASE_MS 20
|
|
@@ -492,11 +599,137 @@
|
|
|
492
599
|
#define OMX_XOVER_PARTITION_TOLERANCE_DOUBLE 0.00001
|
|
493
600
|
|
|
494
601
|
/* Every list rendered to C, sorted by list: OMX_<LIST>_COUNT and OMX_<LIST>_INIT { a, b, … }. */
|
|
602
|
+
#define OMX_EQ_CENTRE_SERIES_R20_HZ_COUNT 61u
|
|
603
|
+
#define OMX_EQ_CENTRE_SERIES_R20_HZ_INIT { 20, 22.4f, 25, 28, 31.5f, 35.5f, 40, 45, 50, 56, 63, 71, 80, 90, 100, 112, 125, 140, 160, 180, 200, 224, 250, 280, 315, 355, 400, 450, 500, 560, 630, 710, 800, 900, 1000, 1120, 1250, 1400, 1600, 1800, 2000, 2240, 2500, 2800, 3150, 3550, 4000, 4500, 5000, 5600, 6300, 7100, 8000, 9000, 10000, 11200, 12500, 14000, 16000, 18000, 20000 }
|
|
604
|
+
#define OMX_EQ_DEFAULT_CENTRES_FOUR_BAND_HZ_COUNT 4u
|
|
605
|
+
#define OMX_EQ_DEFAULT_CENTRES_FOUR_BAND_HZ_INIT { 100, 400, 2000, 8000 }
|
|
606
|
+
#define OMX_ISO_THIRD_OCTAVE_CENTRES_HZ_COUNT 31u
|
|
607
|
+
#define OMX_ISO_THIRD_OCTAVE_CENTRES_HZ_INIT { 20, 25, 31.5f, 40, 50, 63, 80, 100, 125, 160, 200, 250, 315, 400, 500, 630, 800, 1000, 1250, 1600, 2000, 2500, 3150, 4000, 5000, 6300, 8000, 10000, 12500, 16000, 20000 }
|
|
608
|
+
#define OMX_ORACLE_FLOOR_RATES_COUNT 4u
|
|
609
|
+
#define OMX_ORACLE_FLOOR_RATES_INIT { 44100, 48000, 96000, 192000 }
|
|
495
610
|
#define OMX_PHASER_STAGE_COUNTS_COUNT 6u
|
|
496
611
|
#define OMX_PHASER_STAGE_COUNTS_INIT { 2, 4, 6, 8, 10, 12 }
|
|
612
|
+
#define OMX_RME_RATES_COUNT 9u
|
|
613
|
+
#define OMX_RME_RATES_INIT { 32000, 44100, 48000, 64000, 88200, 96000, 128000, 176400, 192000 }
|
|
497
614
|
#define OMX_STANDARD_SAMPLE_RATES_COUNT 6u
|
|
498
615
|
#define OMX_STANDARD_SAMPLE_RATES_INIT { 44100, 48000, 88200, 96000, 176400, 192000 }
|
|
499
616
|
|
|
617
|
+
/* Every set rendered to C, sorted by set: an enum of the ids (a named id's position, or a numeric id's number), `OMX_<SET>_COUNT` and,
|
|
618
|
+
* where the set names a default, `OMX_<SET>_DEFAULT`. */
|
|
619
|
+
enum omx_band_dyn_modes {
|
|
620
|
+
OMX_BAND_DYN_MODES_ABOVE = 0,
|
|
621
|
+
OMX_BAND_DYN_MODES_BELOW = 1,
|
|
622
|
+
};
|
|
623
|
+
#define OMX_BAND_DYN_MODES_COUNT 2u
|
|
624
|
+
#define OMX_BAND_DYN_MODES_DEFAULT OMX_BAND_DYN_MODES_ABOVE
|
|
625
|
+
enum omx_deess_modes {
|
|
626
|
+
OMX_DEESS_MODES_SPLIT = 0,
|
|
627
|
+
OMX_DEESS_MODES_WIDEBAND = 1,
|
|
628
|
+
};
|
|
629
|
+
#define OMX_DEESS_MODES_COUNT 2u
|
|
630
|
+
enum omx_drive_bands {
|
|
631
|
+
OMX_DRIVE_BANDS_FULL = 0,
|
|
632
|
+
OMX_DRIVE_BANDS_LOW = 1,
|
|
633
|
+
OMX_DRIVE_BANDS_HIGH = 2,
|
|
634
|
+
OMX_DRIVE_BANDS_TILT = 3,
|
|
635
|
+
};
|
|
636
|
+
#define OMX_DRIVE_BANDS_COUNT 4u
|
|
637
|
+
enum omx_drive_curves {
|
|
638
|
+
OMX_DRIVE_CURVES_SOFT = 0,
|
|
639
|
+
OMX_DRIVE_CURVES_TAPE = 1,
|
|
640
|
+
OMX_DRIVE_CURVES_TUBE = 2,
|
|
641
|
+
OMX_DRIVE_CURVES_EXCITER = 3,
|
|
642
|
+
};
|
|
643
|
+
#define OMX_DRIVE_CURVES_COUNT 4u
|
|
644
|
+
enum omx_eq_band_types {
|
|
645
|
+
OMX_EQ_BAND_TYPES_BELL = 0,
|
|
646
|
+
OMX_EQ_BAND_TYPES_LOW_SHELF = 1,
|
|
647
|
+
OMX_EQ_BAND_TYPES_HIGH_SHELF = 2,
|
|
648
|
+
OMX_EQ_BAND_TYPES_NOTCH = 3,
|
|
649
|
+
OMX_EQ_BAND_TYPES_ALLPASS1 = 4,
|
|
650
|
+
OMX_EQ_BAND_TYPES_ALLPASS2 = 5,
|
|
651
|
+
};
|
|
652
|
+
#define OMX_EQ_BAND_TYPES_COUNT 6u
|
|
653
|
+
#define OMX_EQ_BAND_TYPES_DEFAULT OMX_EQ_BAND_TYPES_BELL
|
|
654
|
+
enum omx_filter_slopes {
|
|
655
|
+
OMX_FILTER_SLOPES_12 = 12,
|
|
656
|
+
OMX_FILTER_SLOPES_24 = 24,
|
|
657
|
+
};
|
|
658
|
+
#define OMX_FILTER_SLOPES_COUNT 2u
|
|
659
|
+
#define OMX_FILTER_SLOPES_DEFAULT OMX_FILTER_SLOPES_12
|
|
660
|
+
enum omx_gate_key_sources {
|
|
661
|
+
OMX_GATE_KEY_SOURCES_SELF = 0,
|
|
662
|
+
OMX_GATE_KEY_SOURCES_SIDECHAIN = 1,
|
|
663
|
+
};
|
|
664
|
+
#define OMX_GATE_KEY_SOURCES_COUNT 2u
|
|
665
|
+
enum omx_param_scales {
|
|
666
|
+
OMX_PARAM_SCALES_LINEAR = 0,
|
|
667
|
+
OMX_PARAM_SCALES_LOG = 1,
|
|
668
|
+
OMX_PARAM_SCALES_STEPPED = 2,
|
|
669
|
+
};
|
|
670
|
+
#define OMX_PARAM_SCALES_COUNT 3u
|
|
671
|
+
#define OMX_PARAM_SCALES_DEFAULT OMX_PARAM_SCALES_LINEAR
|
|
672
|
+
enum omx_reverb_algorithms {
|
|
673
|
+
OMX_REVERB_ALGORITHMS_ROOM = 0,
|
|
674
|
+
OMX_REVERB_ALGORITHMS_PLATE = 1,
|
|
675
|
+
OMX_REVERB_ALGORITHMS_HALL = 2,
|
|
676
|
+
OMX_REVERB_ALGORITHMS_REVERSE = 3,
|
|
677
|
+
OMX_REVERB_ALGORITHMS_GATED = 4,
|
|
678
|
+
};
|
|
679
|
+
#define OMX_REVERB_ALGORITHMS_COUNT 5u
|
|
680
|
+
enum omx_rotary_speeds {
|
|
681
|
+
OMX_ROTARY_SPEEDS_STOP = 0,
|
|
682
|
+
OMX_ROTARY_SPEEDS_SLOW = 1,
|
|
683
|
+
OMX_ROTARY_SPEEDS_FAST = 2,
|
|
684
|
+
};
|
|
685
|
+
#define OMX_ROTARY_SPEEDS_COUNT 3u
|
|
686
|
+
enum omx_tremolo_modes {
|
|
687
|
+
OMX_TREMOLO_MODES_TREMOLO = 0,
|
|
688
|
+
OMX_TREMOLO_MODES_PAN = 1,
|
|
689
|
+
};
|
|
690
|
+
#define OMX_TREMOLO_MODES_COUNT 2u
|
|
691
|
+
#define OMX_TREMOLO_MODES_DEFAULT OMX_TREMOLO_MODES_TREMOLO
|
|
692
|
+
|
|
693
|
+
/* The default bands of an EQ with `count` bands: THE one rule, for every strip, host and count (omx-contract's
|
|
694
|
+
* lib/eq-defaults.mjs; the ts render exports the same as eqDefaultCentres and eqDefaultTypes). Needs -lm. */
|
|
695
|
+
static inline unsigned omx_eq_default_centres(unsigned count, float *out) {
|
|
696
|
+
static const double r10[] = OMX_ISO_THIRD_OCTAVE_CENTRES_HZ_INIT;
|
|
697
|
+
static const double r20[] = OMX_EQ_CENTRE_SERIES_R20_HZ_INIT;
|
|
698
|
+
static const double four[] = OMX_EQ_DEFAULT_CENTRES_FOUR_BAND_HZ_INIT;
|
|
699
|
+
if (count == 0) return 0;
|
|
700
|
+
if (count == 4) {
|
|
701
|
+
for (unsigned i = 0; i < 4; i++) out[i] = (float)four[i];
|
|
702
|
+
return 4;
|
|
703
|
+
}
|
|
704
|
+
const double lo = log((double)OMX_EQ_FREQ_RANGE_MIN);
|
|
705
|
+
const double span = log((double)OMX_EQ_FREQ_RANGE_MAX / (double)OMX_EQ_FREQ_RANGE_MIN);
|
|
706
|
+
for (unsigned s = 0; s < 2; s++) {
|
|
707
|
+
const double *series = s ? r20 : r10;
|
|
708
|
+
const unsigned n = s ? OMX_EQ_CENTRE_SERIES_R20_HZ_COUNT : OMX_ISO_THIRD_OCTAVE_CENTRES_HZ_COUNT;
|
|
709
|
+
int distinct = count <= n;
|
|
710
|
+
for (unsigned i = 0; distinct && i < count; i++) {
|
|
711
|
+
const double t = lo + span * ((double)i + 0.5) / (double)count;
|
|
712
|
+
unsigned best = 0;
|
|
713
|
+
double best_d = 1e300;
|
|
714
|
+
for (unsigned k = 0; k < n; k++) {
|
|
715
|
+
const double d = fabs(log(series[k]) - t);
|
|
716
|
+
if (d < best_d) { best_d = d; best = k; }
|
|
717
|
+
}
|
|
718
|
+
out[i] = (float)series[best];
|
|
719
|
+
if (i > 0 && out[i] == out[i - 1]) distinct = 0;
|
|
720
|
+
}
|
|
721
|
+
if (distinct) return count;
|
|
722
|
+
}
|
|
723
|
+
return 0;
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
/* The default type of band `index` of an EQ with `count` bands: a low shelf first, a high shelf last, bells
|
|
727
|
+
* between (a single band is a bell). An OMX_EQ_BAND_TYPES_* member. */
|
|
728
|
+
static inline int omx_eq_default_type(unsigned index, unsigned count) {
|
|
729
|
+
if (count < 2) return OMX_EQ_BAND_TYPES_BELL;
|
|
730
|
+
return index == 0 ? OMX_EQ_BAND_TYPES_LOW_SHELF : index == count - 1 ? OMX_EQ_BAND_TYPES_HIGH_SHELF : OMX_EQ_BAND_TYPES_BELL;
|
|
731
|
+
}
|
|
732
|
+
|
|
500
733
|
#endif /* OMX_CONTRACT_LIMITS_H */
|
|
501
734
|
|
|
502
735
|
/* The sample rates the console declares (core's STANDARD_SAMPLE_RATES, row-codecs.ts): the set a
|
package/lib/data.mjs
CHANGED
|
@@ -34,8 +34,7 @@ export function loadData(dir, texts) {
|
|
|
34
34
|
let doc;
|
|
35
35
|
try { doc = JSON.parse(text); } catch (e) { throw new Error(`${rel}: not JSON: ${e.message}`); }
|
|
36
36
|
files.push({ rel, text, doc });
|
|
37
|
-
for (const [name, item] of
|
|
38
|
-
if (name === '$schema') continue;
|
|
37
|
+
for (const [name, item] of entriesOf(rel, doc)) {
|
|
39
38
|
if (items.has(name)) throw new Error(`${rel}: ${name}: already declared by ${items.get(name).rel}`);
|
|
40
39
|
items.set(name, { name, rel, item });
|
|
41
40
|
}
|
|
@@ -43,6 +42,109 @@ export function loadData(dir, texts) {
|
|
|
43
42
|
return { files, items };
|
|
44
43
|
}
|
|
45
44
|
|
|
45
|
+
const snakeOf = (n) => n.replace(/([a-z0-9])([A-Z])/g, '$1_$2').toUpperCase();
|
|
46
|
+
const camelOf = (u) => u.toLowerCase().replace(/_([a-z0-9])/g, (_, x) => x.toUpperCase());
|
|
47
|
+
|
|
48
|
+
/** The four sections of a kernel file, in their order. */
|
|
49
|
+
export const KERNEL_SECTIONS = ['controls', 'tables', 'aggregates', 'constants'];
|
|
50
|
+
|
|
51
|
+
/** Whether a data file is a kernel file (`kernels/<kernel>.json`), which holds the four sections, never an item map. */
|
|
52
|
+
export const isKernelFile = (rel) => /(^|\/)kernels\/[^/]+\.json$/.test(rel);
|
|
53
|
+
|
|
54
|
+
/** The kernel's upper-case prefix, read off its file name: `kernels/band_dyn.json` is BAND_DYN. */
|
|
55
|
+
export const kernelPrefix = (rel) => rel.replace(/^.*\//, '').replace(/\.json$/, '').toUpperCase().replace(/-/g, '_');
|
|
56
|
+
|
|
57
|
+
/** A control's item name: its `global`, else <KERNEL>_<NAME>_RANGE for a travel and <KERNEL>_<NAME>S for a choice. */
|
|
58
|
+
export const controlGlobal = (rel, c) => c.global ?? `${kernelPrefix(rel)}_${snakeOf(c.name)}${c.kind === 'choice' ? 'S' : '_RANGE'}`;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* A data file's items as [name, item] pairs. A kernel file's four sections are expanded into the items the renders
|
|
62
|
+
* read: a travel control is a `travels` item named by controlGlobal, a choice a `set`; the controls of one `table`
|
|
63
|
+
* regroup into that table's `travels` item with `fields`; an aggregate is regenerated as fields that reference its
|
|
64
|
+
* controls; constants pass through. Any other top-level key of a kernel file is not read (validation names it).
|
|
65
|
+
* rates.json and primitives.json are item maps, read as they are.
|
|
66
|
+
*/
|
|
67
|
+
export function entriesOf(rel, doc) {
|
|
68
|
+
if (!isKernelFile(rel)) return Object.entries(doc).filter(([name]) => name !== '$schema');
|
|
69
|
+
const out = [];
|
|
70
|
+
const controls = Array.isArray(doc.controls) ? doc.controls : [];
|
|
71
|
+
const tables = new Map(Object.entries(doc.tables ?? {}).map(([n, meta]) => [n, { kind: 'travels', ...meta, fields: {} }]));
|
|
72
|
+
for (const c of controls) {
|
|
73
|
+
const { name, kind, global, table, ...rest } = c;
|
|
74
|
+
if (table) {
|
|
75
|
+
if (!tables.has(table)) throw new Error(`${rel}: control ${name} names table ${table}, which is not declared`);
|
|
76
|
+
tables.get(table).fields[name] = rest.travel;
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
out.push([controlGlobal(rel, c), kind === 'choice' ? { kind: 'set', ...rest } : { kind: 'travels', ...rest }]);
|
|
80
|
+
}
|
|
81
|
+
for (const [n, t] of tables) out.push([n, t]);
|
|
82
|
+
const byName = new Map(controls.map((c) => [c.name, c]));
|
|
83
|
+
for (const [n, a] of Object.entries(doc.aggregates ?? {})) {
|
|
84
|
+
const { fields, ...meta } = a;
|
|
85
|
+
out.push([n, { kind: 'travels', ...meta, fields: Object.fromEntries((fields ?? []).map((f) => {
|
|
86
|
+
if (!byName.has(f)) throw new Error(`${rel}: aggregate ${n} names control ${f}, which is not declared`);
|
|
87
|
+
return [f, { ref: controlGlobal(rel, byName.get(f)) }];
|
|
88
|
+
})) }]);
|
|
89
|
+
}
|
|
90
|
+
for (const [n, item] of Object.entries(doc.constants ?? {})) out.push([n, item]);
|
|
91
|
+
return out;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const isWholeRef = (v) => typeof v === 'object' && v !== null && Object.keys(v).length === 1 && typeof v.ref === 'string' && !v.ref.includes('.');
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* The kernel file that declares `entries` ([name, item] pairs, the items entriesOf gives back), the inverse of
|
|
98
|
+
* entriesOf: a single travel is a travel control and a set a choice; a fields table whose every field IS a single
|
|
99
|
+
* travel of the kernel (`{ ref }`) is an aggregate, and its field names name those controls; any other fields table
|
|
100
|
+
* is a table whose fields are its controls; every other item is a constant. A control's `global` is written only
|
|
101
|
+
* when its name does not derive it. `kept`, a kernel file already written, is extended: its declarations stay as
|
|
102
|
+
* they are and the entries it lacks are added. Empty sections are left out.
|
|
103
|
+
* @throws naming the item: a fields table that mixes references and travels, an aggregate field whose name is not
|
|
104
|
+
* its control's.
|
|
105
|
+
*/
|
|
106
|
+
export function kernelDocOf(rel, entries, kept) {
|
|
107
|
+
const K = kernelPrefix(rel);
|
|
108
|
+
const doc = kept ? JSON.parse(JSON.stringify(kept)) : {};
|
|
109
|
+
doc.controls ??= [];
|
|
110
|
+
for (const s of KERNEL_SECTIONS.slice(1)) doc[s] ??= {};
|
|
111
|
+
const declared = new Set(entriesOf(rel, kept ?? {}).map(([n]) => n));
|
|
112
|
+
const singles = new Map(entries.filter(([, it]) => (it.kind === 'travels' && it.travel) || it.kind === 'set'));
|
|
113
|
+
for (const c of doc.controls) if (!c.table) singles.set(controlGlobal(rel, c), c);
|
|
114
|
+
const isAggregate = (it) => it.kind === 'travels' && it.fields && Object.values(it.fields).length > 0 && Object.values(it.fields).every((f) => isWholeRef(f) && singles.get(f.ref)?.travel);
|
|
115
|
+
// an aggregate's field names are its controls' names
|
|
116
|
+
const named = new Map();
|
|
117
|
+
for (const [n, it] of entries) if (isAggregate(it)) for (const [f, t] of Object.entries(it.fields)) named.set(t.ref, f);
|
|
118
|
+
for (const [n, it] of entries) {
|
|
119
|
+
if (declared.has(n)) continue;
|
|
120
|
+
if ((it.kind === 'travels' && it.travel) || it.kind === 'set') {
|
|
121
|
+
const { kind, ...rest } = it;
|
|
122
|
+
const ck = kind === 'set' ? 'choice' : 'travel';
|
|
123
|
+
const suffix = ck === 'choice' ? 'S' : '_RANGE';
|
|
124
|
+
const derived = n.startsWith(`${K}_`) && n.endsWith(suffix) && n.length > K.length + 1 + suffix.length ? camelOf(n.slice(K.length + 1, -suffix.length)) : undefined;
|
|
125
|
+
const c = { name: named.get(n) ?? derived ?? camelOf(n.endsWith(suffix) ? n.slice(0, -suffix.length) : n), kind: ck };
|
|
126
|
+
if (controlGlobal(rel, c) !== n) c.global = n;
|
|
127
|
+
doc.controls.push({ ...c, ...rest });
|
|
128
|
+
} else if (it.kind === 'travels' && it.fields && isAggregate(it)) {
|
|
129
|
+
const { kind, fields, ...meta } = it;
|
|
130
|
+
doc.aggregates[n] = { ...meta, fields: Object.entries(fields).map(([f, t]) => {
|
|
131
|
+
const c = doc.controls.find((x) => !x.table && controlGlobal(rel, x) === t.ref) ?? { name: named.get(t.ref) };
|
|
132
|
+
if (c.name !== f) throw new Error(`${rel}: ${n}.${f} refers to ${t.ref}, whose control is named ${c.name}: an aggregate's field is named by its control`);
|
|
133
|
+
return f;
|
|
134
|
+
}) };
|
|
135
|
+
} else if (it.kind === 'travels' && it.fields) {
|
|
136
|
+
const { kind, fields, ...meta } = it;
|
|
137
|
+
if (Object.values(fields).some(isWholeRef)) throw new Error(`${rel}: ${n} mixes fields that refer to single travels with travels of its own: declare it as an aggregate of controls, or as a table`);
|
|
138
|
+
doc.tables[n] = meta;
|
|
139
|
+
for (const [f, travel] of Object.entries(fields)) doc.controls.push({ name: f, kind: 'travel', table: n, travel });
|
|
140
|
+
} else {
|
|
141
|
+
doc.constants[n] = it;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
for (const s of KERNEL_SECTIONS) if (s === 'controls' ? !doc[s].length : !Object.keys(doc[s]).length) delete doc[s];
|
|
145
|
+
return doc;
|
|
146
|
+
}
|
|
147
|
+
|
|
46
148
|
/** An item's own value before resolution, by kind. */
|
|
47
149
|
export function rawValue(item) {
|
|
48
150
|
switch (item.kind) {
|
|
@@ -50,6 +152,7 @@ export function rawValue(item) {
|
|
|
50
152
|
case 'travels': return item.fields ?? item.travel;
|
|
51
153
|
case 'sheet': return item.value;
|
|
52
154
|
case 'list': return item.values;
|
|
155
|
+
case 'set': return item.ids;
|
|
53
156
|
default: return undefined;
|
|
54
157
|
}
|
|
55
158
|
}
|
|
@@ -66,6 +169,11 @@ export const DERIVATIONS = {
|
|
|
66
169
|
if (typeof v !== 'number' || v < 0) throw new Error(`sqrt: ${JSON.stringify(d.of)} is not a non-negative number`);
|
|
67
170
|
return Math.sqrt(v);
|
|
68
171
|
},
|
|
172
|
+
ceilSum: (d, val) => {
|
|
173
|
+
const terms = d.of.map((x) => val(x));
|
|
174
|
+
if (!terms.every((t) => typeof t === 'number' && Number.isFinite(t))) throw new Error(`ceilSum: ${JSON.stringify(d.of)} holds a term that is not a finite number`);
|
|
175
|
+
return Math.ceil(terms.reduce((a, t) => a + t, 0));
|
|
176
|
+
},
|
|
69
177
|
lagrangeReadL1: (d, val) => {
|
|
70
178
|
const order = val(d.order);
|
|
71
179
|
if (!Number.isInteger(order) || order < 1) throw new Error(`lagrangeReadL1: order ${order} is not a positive integer`);
|
|
@@ -104,7 +212,7 @@ export function lagrangeReadL1(order) {
|
|
|
104
212
|
const isObj = (v) => typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
105
213
|
|
|
106
214
|
/**
|
|
107
|
-
* Resolve every item: `{ name, rel, kind, doc, why?, unit?, c?, shape?, value }
|
|
215
|
+
* Resolve every item: `{ name, rel, kind, doc, why?, unit?, c?, shape?, default?, labels?, value }` (default and labels: a set's), where `value` has
|
|
108
216
|
* every `{ref}` and `{derive}` evaluated.
|
|
109
217
|
* @throws naming the item: a reference that does not resolve, a cycle, an unknown derivation.
|
|
110
218
|
*/
|
|
@@ -142,6 +250,10 @@ export function resolveData(data) {
|
|
|
142
250
|
if (item.why !== undefined) r.why = item.why;
|
|
143
251
|
if (item.unit !== undefined) r.unit = item.unit;
|
|
144
252
|
if (item.c !== undefined) r.c = item.c;
|
|
253
|
+
if (item.kind === 'set') {
|
|
254
|
+
if (item.default !== undefined) r.default = item.default;
|
|
255
|
+
if (item.labels !== undefined) r.labels = item.labels;
|
|
256
|
+
}
|
|
145
257
|
if (item.kind === 'travels') r.shape = item.fields ? 'table' : 'travel';
|
|
146
258
|
r.value = val(rawValue(item), name);
|
|
147
259
|
busy.delete(name);
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
2
|
+
// Copyright (C) 2026 Pau Aliagas <linuxnow@gmail.com>
|
|
3
|
+
/**
|
|
4
|
+
* THE default rule for the bands of a fresh EQ, whatever the strip, the host or the band count: one
|
|
5
|
+
* rule, no override, for the console, omx-plugins and any other host. Per strip type the contract
|
|
6
|
+
* declares only the band counts (EQ_BAND_COUNTS: default and maximum); the bands come from here.
|
|
7
|
+
*
|
|
8
|
+
* Types the first band is a low shelf and the last a high shelf (each switchable to a bell by the
|
|
9
|
+
* operator); every band between is a bell. A single band is a bell.
|
|
10
|
+
* Gain, Q every band is EQ_BAND_DEFAULTS.gainDb and .q.
|
|
11
|
+
* Centres
|
|
12
|
+
* 4 bands the declared four (EQ_DEFAULT_CENTRES_FOUR_BAND_HZ): 100, 400, 2000, 8000 Hz,
|
|
13
|
+
* ISO 266 preferred values.
|
|
14
|
+
* N bands N slots of equal width on a log axis across EQ_FREQ_RANGE; band i sits in the
|
|
15
|
+
* middle of slot i (lo * (hi / lo) ** ((i + 0.5) / N)) and takes the nearest preferred
|
|
16
|
+
* frequency on that axis, from the ISO 266 R10 series (ISO_THIRD_OCTAVE_CENTRES_HZ);
|
|
17
|
+
* when two bands would share a value in R10 the same is done on its R20 refinement
|
|
18
|
+
* (EQ_CENTRE_SERIES_R20_HZ). Never a repeated centre: more bands than R20 holds is an
|
|
19
|
+
* error.
|
|
20
|
+
*
|
|
21
|
+
* The same functions are exported by the ts render (`eqDefaultCentres`, `eqDefaultTypes`,
|
|
22
|
+
* `eqDefaultBands`) and the c render (`omx_eq_default_centres`, `omx_eq_default_type`); test/eq-defaults.test.mjs holds the three equal for every count.
|
|
23
|
+
* This file is the one JavaScript spelling: the ts render embeds its source.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* The default band centres (Hz) of an EQ with `count` bands.
|
|
28
|
+
* @param {number} count how many bands the strip's EQ starts with, a positive integer.
|
|
29
|
+
* @param {{ four: number[], series: number[][], lo: number, hi: number }} p the declared four-band
|
|
30
|
+
* set, the preferred-frequency series from coarsest to finest, and the band frequency travel.
|
|
31
|
+
* @returns {number[]}
|
|
32
|
+
*/
|
|
33
|
+
export function eqDefaultCentres(count, p) {
|
|
34
|
+
if (!Number.isInteger(count) || count < 1) throw new RangeError(`eqDefaultCentres: ${count} is not a band count`);
|
|
35
|
+
if (count === 4) return [...p.four];
|
|
36
|
+
const targets = [];
|
|
37
|
+
for (let i = 0; i < count; i++) targets.push(Math.log(p.lo) + (Math.log(p.hi / p.lo) * (i + 0.5)) / count);
|
|
38
|
+
for (const series of p.series) {
|
|
39
|
+
const out = targets.map((t) => {
|
|
40
|
+
let best = series[0];
|
|
41
|
+
let bestD = Infinity;
|
|
42
|
+
for (const f of series) {
|
|
43
|
+
const d = Math.abs(Math.log(f) - t);
|
|
44
|
+
if (d < bestD) { bestD = d; best = f; }
|
|
45
|
+
}
|
|
46
|
+
return best;
|
|
47
|
+
});
|
|
48
|
+
if (new Set(out).size === out.length) return out;
|
|
49
|
+
}
|
|
50
|
+
throw new RangeError(`eqDefaultCentres: ${count} bands have no distinct preferred centres across ${p.lo}..${p.hi} Hz`);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* The band types of an EQ with `count` bands, by EQ_BAND_TYPES id: a low shelf, bells, a high shelf.
|
|
55
|
+
* @param {number} count
|
|
56
|
+
* @returns {string[]}
|
|
57
|
+
*/
|
|
58
|
+
export function eqDefaultTypes(count) {
|
|
59
|
+
if (!Number.isInteger(count) || count < 1) throw new RangeError(`eqDefaultTypes: ${count} is not a band count`);
|
|
60
|
+
return Array.from({ length: count }, (_, i) => (count === 1 ? 'bell' : i === 0 ? 'lowShelf' : i === count - 1 ? 'highShelf' : 'bell'));
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Every default band of an EQ with `count` bands.
|
|
65
|
+
* @param {number} count
|
|
66
|
+
* @param {{ four: number[], series: number[][], lo: number, hi: number, gainDb: number, q: number }} p
|
|
67
|
+
* @returns {{ type: string, freqHz: number, gainDb: number, q: number }[]}
|
|
68
|
+
*/
|
|
69
|
+
export function eqDefaultBands(count, p) {
|
|
70
|
+
const types = eqDefaultTypes(count);
|
|
71
|
+
return eqDefaultCentres(count, p).map((freqHz, i) => ({ type: types[i], freqHz, gainDb: p.gainDb, q: p.q }));
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** The parameters of the rule, read off the resolved items. */
|
|
75
|
+
export function eqDefaultParams(resolved) {
|
|
76
|
+
const v = (name) => {
|
|
77
|
+
const r = resolved.get(name);
|
|
78
|
+
if (!r) throw new Error(`the default centre rule needs ${name}`);
|
|
79
|
+
return r.value;
|
|
80
|
+
};
|
|
81
|
+
const range = v('EQ_FREQ_RANGE');
|
|
82
|
+
const band = v('EQ_BAND_DEFAULTS');
|
|
83
|
+
return {
|
|
84
|
+
four: v('EQ_DEFAULT_CENTRES_FOUR_BAND_HZ'), series: [v('ISO_THIRD_OCTAVE_CENTRES_HZ'), v('EQ_CENTRE_SERIES_R20_HZ')],
|
|
85
|
+
lo: range.min, hi: range.max, gainDb: band.gainDb, q: band.q,
|
|
86
|
+
};
|
|
87
|
+
}
|
package/lib/fmt.mjs
CHANGED
|
@@ -3,12 +3,15 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* The one formatting of a data file (spec §3.2): two-space indent, one key per line, keys in schema
|
|
5
5
|
* order, a trailing newline. Names (items, fields, sheet keys) keep the order the author gave them:
|
|
6
|
-
* a travels table's field order is its C block order.
|
|
6
|
+
* a travels table's field order is its C block order. A kernel file's sections come in their order (controls,
|
|
7
|
+
* tables, aggregates, constants), its controls in the author's order, each control's keys in schema order.
|
|
7
8
|
*/
|
|
8
9
|
|
|
9
10
|
const ORDER = {
|
|
10
|
-
|
|
11
|
-
|
|
11
|
+
control: ['name', 'kind', 'global', 'table', 'since', 'doc', 'why', 'unit', 'ids', 'default', 'labels', 'travel', 'c'],
|
|
12
|
+
sections: ['controls', 'tables', 'aggregates', 'constants'],
|
|
13
|
+
item: ['kind', 'since', 'doc', 'why', 'unit', 'value', 'values', 'ids', 'default', 'labels', 'fields', 'travel', 'c'],
|
|
14
|
+
travel: ['min', 'max', 'step', 'unit', 'default', 'defaultFrom', 'scale', 'byKind', 'doc', 'why'],
|
|
12
15
|
c: ['alias', 'render'],
|
|
13
16
|
alias: ['fact', 'field'],
|
|
14
17
|
number: ['ref', 'derive', 'of', 'order'],
|
|
@@ -52,10 +55,27 @@ function item(it) {
|
|
|
52
55
|
return o;
|
|
53
56
|
}
|
|
54
57
|
|
|
58
|
+
function control(c) {
|
|
59
|
+
if (!isObj(c)) return c;
|
|
60
|
+
const o = ordered(c, ORDER.control);
|
|
61
|
+
if (isObj(o.travel)) o.travel = travel(o.travel);
|
|
62
|
+
if (isObj(o.c)) o.c = item({ c: o.c }).c;
|
|
63
|
+
return o;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const items = (m) => (isObj(m) ? Object.fromEntries(Object.entries(m).map(([k, v]) => [k, item(v)])) : m);
|
|
67
|
+
|
|
55
68
|
/** The canonical text of a parsed data file. */
|
|
56
69
|
export function formatDoc(doc) {
|
|
57
70
|
const out = {};
|
|
58
71
|
if ('$schema' in doc) out.$schema = doc.$schema;
|
|
59
|
-
|
|
72
|
+
if (ORDER.sections.some((k) => k in doc)) {
|
|
73
|
+
for (const [k, v] of Object.entries(ordered(doc, ORDER.sections))) {
|
|
74
|
+
if (k === '$schema') continue;
|
|
75
|
+
out[k] = k === 'controls' && Array.isArray(v) ? v.map(control) : ORDER.sections.includes(k) ? items(v) : item(v);
|
|
76
|
+
}
|
|
77
|
+
} else {
|
|
78
|
+
for (const [k, v] of Object.entries(doc)) if (k !== '$schema') out[k] = item(v);
|
|
79
|
+
}
|
|
60
80
|
return `${JSON.stringify(out, null, 2)}\n`;
|
|
61
81
|
}
|