@openmixer/omx-contract 1.2.1 → 1.3.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 +9 -4
- package/data/kernels/chorus.json +22 -0
- package/data/kernels/deesser.json +8 -0
- package/data/kernels/drive.json +20 -0
- package/data/kernels/eq.json +160 -4
- package/data/kernels/fbs.json +148 -0
- package/data/kernels/flanger.json +22 -0
- package/data/kernels/gate.json +8 -0
- package/data/kernels/hrp.json +62 -0
- package/data/kernels/mixmatrix.json +9 -0
- package/data/kernels/phaser.json +6 -0
- package/data/kernels/reverb.json +17 -0
- package/data/kernels/rotary.json +9 -0
- package/data/kernels/rta.json +15 -0
- package/data/kernels/tremolo.json +9 -0
- package/data/primitives.json +51 -0
- package/data/rates.json +29 -0
- package/dist/ts/omx-contract.d.ts +416 -0
- package/dist/ts/omx-contract.js +682 -0
- package/include/omxcontract/omx_contract_limits.h +198 -0
- package/lib/data.mjs +11 -1
- package/lib/eq-defaults.mjs +87 -0
- package/lib/fmt.mjs +2 -2
- package/lib/semver.mjs +12 -2
- package/lib/validate.mjs +60 -1
- 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 +590 -4
- 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,16 @@
|
|
|
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_BUS_INPUT_CAP 128
|
|
131
133
|
#define OMX_BUTTERWORTH_Q 0.7071067811865476f
|
|
132
134
|
#define OMX_BUTTERWORTH_Q_DOUBLE 0.7071067811865476
|
|
135
|
+
#define OMX_CHORUS_BASE_MS 10
|
|
133
136
|
#define OMX_CHORUS_DEPTH_RANGE_DEFAULT 4
|
|
134
137
|
#define OMX_CHORUS_DEPTH_RANGE_MAX 12
|
|
135
138
|
#define OMX_CHORUS_DEPTH_RANGE_MIN 0
|
|
136
139
|
#define OMX_CHORUS_DEPTH_RANGE_STEP 0.1f
|
|
137
140
|
#define OMX_CHORUS_DEPTH_RANGE_STEP_DOUBLE 0.1
|
|
141
|
+
#define OMX_CHORUS_MAX_MS 22
|
|
138
142
|
#define OMX_CHORUS_MIX_RANGE_DEFAULT 35
|
|
139
143
|
#define OMX_CHORUS_MIX_RANGE_MAX 100
|
|
140
144
|
#define OMX_CHORUS_MIX_RANGE_MIN 0
|
|
@@ -157,6 +161,7 @@
|
|
|
157
161
|
#define OMX_CHORUS_VOICES_RANGE_MAX 4
|
|
158
162
|
#define OMX_CHORUS_VOICES_RANGE_MIN 1
|
|
159
163
|
#define OMX_CHORUS_VOICES_RANGE_STEP 1
|
|
164
|
+
#define OMX_DEEP_PLATEAU_FRAMES 20
|
|
160
165
|
#define OMX_DEESS_ATTACK_RANGE_DEFAULT 1
|
|
161
166
|
#define OMX_DEESS_ATTACK_RANGE_MAX 50
|
|
162
167
|
#define OMX_DEESS_ATTACK_RANGE_MIN 0.1f
|
|
@@ -193,6 +198,20 @@
|
|
|
193
198
|
#define OMX_DEESS_WIDTH_RANGE_MIN_DOUBLE 0.25
|
|
194
199
|
#define OMX_DEESS_WIDTH_RANGE_STEP 0.05f
|
|
195
200
|
#define OMX_DEESS_WIDTH_RANGE_STEP_DOUBLE 0.05
|
|
201
|
+
#define OMX_DEFAULT_THRESHOLDS_GROWTH_CONFIRM_FRAMES 2
|
|
202
|
+
#define OMX_DEFAULT_THRESHOLDS_GROWTH_MAX_DIP_DB 0.5f
|
|
203
|
+
#define OMX_DEFAULT_THRESHOLDS_GROWTH_MAX_DIP_DB_DOUBLE 0.5
|
|
204
|
+
#define OMX_DEFAULT_THRESHOLDS_GROWTH_MAX_SINGLE_FRAME_SHARE 0.5f
|
|
205
|
+
#define OMX_DEFAULT_THRESHOLDS_GROWTH_MAX_SINGLE_FRAME_SHARE_DOUBLE 0.5
|
|
206
|
+
#define OMX_DEFAULT_THRESHOLDS_GROWTH_MIN_DB_PER_FRAME 0.8f
|
|
207
|
+
#define OMX_DEFAULT_THRESHOLDS_GROWTH_MIN_DB_PER_FRAME_DOUBLE 0.8
|
|
208
|
+
#define OMX_DEFAULT_THRESHOLDS_GROWTH_MIN_TOTAL_RISE_DB 6
|
|
209
|
+
#define OMX_DEFAULT_THRESHOLDS_PAPR_DB 18
|
|
210
|
+
#define OMX_DEFAULT_THRESHOLDS_PERSIST_FRAMES 5
|
|
211
|
+
#define OMX_DEFAULT_THRESHOLDS_PHPR_DB 9
|
|
212
|
+
#define OMX_DEFAULT_THRESHOLDS_PNPR_DB 12
|
|
213
|
+
#define OMX_DEFAULT_THRESHOLDS_PSHR_MIN_DB 10
|
|
214
|
+
#define OMX_DEFAULT_THRESHOLDS_SUB_CLEAN_FRAMES 5
|
|
196
215
|
#define OMX_DELAY_MIX_RANGE_BY_KIND_FX_RETURN 1
|
|
197
216
|
#define OMX_DELAY_MIX_RANGE_DEFAULT 0.3f
|
|
198
217
|
#define OMX_DELAY_MIX_RANGE_DEFAULT_DOUBLE 0.3
|
|
@@ -231,6 +250,18 @@
|
|
|
231
250
|
#define OMX_DRIVE_TRIM_RANGE_STEP 0.1f
|
|
232
251
|
#define OMX_DRIVE_TRIM_RANGE_STEP_DOUBLE 0.1
|
|
233
252
|
#define OMX_DSP_KNOB_REFERENCE_RATE 96000
|
|
253
|
+
#define OMX_EQ_BAND_COUNTS_CHANNEL_DEFAULT 4
|
|
254
|
+
#define OMX_EQ_BAND_COUNTS_CHANNEL_MAX 24
|
|
255
|
+
#define OMX_EQ_BAND_COUNTS_EQ16_DEFAULT 16
|
|
256
|
+
#define OMX_EQ_BAND_COUNTS_EQ16_MAX 16
|
|
257
|
+
#define OMX_EQ_BAND_COUNTS_EQ32_DEFAULT 32
|
|
258
|
+
#define OMX_EQ_BAND_COUNTS_EQ32_MAX 32
|
|
259
|
+
#define OMX_EQ_BAND_COUNTS_EQ8_DEFAULT 8
|
|
260
|
+
#define OMX_EQ_BAND_COUNTS_EQ8_MAX 8
|
|
261
|
+
#define OMX_EQ_BAND_COUNTS_STRIP_DEFAULT 4
|
|
262
|
+
#define OMX_EQ_BAND_COUNTS_STRIP_MAX 4
|
|
263
|
+
#define OMX_EQ_BAND_DEFAULTS_GAIN_DB 0
|
|
264
|
+
#define OMX_EQ_BAND_DEFAULTS_Q 1
|
|
234
265
|
#define OMX_EQ_FREQ_RANGE_MAX 20000
|
|
235
266
|
#define OMX_EQ_FREQ_RANGE_MIN 20
|
|
236
267
|
#define OMX_EQ_FREQ_RANGE_STEP 10
|
|
@@ -243,14 +274,29 @@
|
|
|
243
274
|
#define OMX_EQ_NOTCH_Q_RANGE_MIN 0.3f
|
|
244
275
|
#define OMX_EQ_NOTCH_Q_RANGE_MIN_DOUBLE 0.3
|
|
245
276
|
#define OMX_EQ_NOTCH_Q_RANGE_STEP 1
|
|
277
|
+
#define OMX_EQ_PASS_FILTER_DEFAULTS_HPF_FREQ_HZ 80
|
|
278
|
+
#define OMX_EQ_PASS_FILTER_DEFAULTS_LPF_FREQ_HZ 18000
|
|
246
279
|
#define OMX_EQ_Q_RANGE_MAX 8
|
|
247
280
|
#define OMX_EQ_Q_RANGE_MIN 0.3f
|
|
248
281
|
#define OMX_EQ_Q_RANGE_MIN_DOUBLE 0.3
|
|
249
282
|
#define OMX_EQ_Q_RANGE_STEP 0.1f
|
|
250
283
|
#define OMX_EQ_Q_RANGE_STEP_DOUBLE 0.1
|
|
284
|
+
#define OMX_FBS_DEFAULT_MAX_AUTO_BANDS 6
|
|
285
|
+
#define OMX_FBS_DEFAULT_NOTCH_Q 116
|
|
286
|
+
#define OMX_FBS_FLOOR_LIN 1e-12f
|
|
287
|
+
#define OMX_FBS_FLOOR_LIN_DOUBLE 1e-12
|
|
288
|
+
#define OMX_FBS_MAX_NOTCH_DEPTH_DB 18
|
|
289
|
+
#define OMX_FBS_PAPR_GUARD_BINS 2
|
|
290
|
+
#define OMX_FBS_PHPR_HARMONICS 3
|
|
291
|
+
#define OMX_FBS_PNPR_GUARD_BINS 1
|
|
292
|
+
#define OMX_FBS_PNPR_RADIUS_BINS 3
|
|
293
|
+
#define OMX_FBS_PSHR_SELF_SKIP_BINS 3
|
|
294
|
+
#define OMX_FBS_TRACK_SLOTS 512
|
|
251
295
|
#define OMX_FDELAY_MOD_READ_ORDER 3
|
|
252
296
|
#define OMX_FDELAY_READ_L1_NORM 1.25f
|
|
253
297
|
#define OMX_FDELAY_READ_L1_NORM_DOUBLE 1.25
|
|
298
|
+
#define OMX_FLANGER_BASE_MS 0.5f
|
|
299
|
+
#define OMX_FLANGER_BASE_MS_DOUBLE 0.5
|
|
254
300
|
#define OMX_FLANGER_DEPTH_RANGE_DEFAULT 2
|
|
255
301
|
#define OMX_FLANGER_DEPTH_RANGE_MAX 5
|
|
256
302
|
#define OMX_FLANGER_DEPTH_RANGE_MIN 0
|
|
@@ -264,6 +310,7 @@
|
|
|
264
310
|
#define OMX_FLANGER_FEEDBACK_RANGE_MIN_DOUBLE -0.95
|
|
265
311
|
#define OMX_FLANGER_FEEDBACK_RANGE_STEP 0.01f
|
|
266
312
|
#define OMX_FLANGER_FEEDBACK_RANGE_STEP_DOUBLE 0.01
|
|
313
|
+
#define OMX_FLANGER_MAX_MS 6
|
|
267
314
|
#define OMX_FLANGER_MIX_RANGE_DEFAULT 50
|
|
268
315
|
#define OMX_FLANGER_MIX_RANGE_MAX 100
|
|
269
316
|
#define OMX_FLANGER_MIX_RANGE_MIN 0
|
|
@@ -296,12 +343,35 @@
|
|
|
296
343
|
#define OMX_GEQ_BAND_RANGE_STEP_DOUBLE 0.5
|
|
297
344
|
#define OMX_GEQ_DESIGN_GAIN_MAX_DB 30
|
|
298
345
|
#define OMX_GEQ_PROTO_DB 12
|
|
346
|
+
#define OMX_GROWTH_CONFIRM_FRAMES 2
|
|
347
|
+
#define OMX_GROWTH_MAX_DIP_DB 0.5f
|
|
348
|
+
#define OMX_GROWTH_MAX_DIP_DB_DOUBLE 0.5
|
|
349
|
+
#define OMX_GROWTH_MAX_SINGLE_FRAME_SHARE 0.5f
|
|
350
|
+
#define OMX_GROWTH_MAX_SINGLE_FRAME_SHARE_DOUBLE 0.5
|
|
351
|
+
#define OMX_GROWTH_MIN_DB_PER_FRAME 0.8f
|
|
352
|
+
#define OMX_GROWTH_MIN_DB_PER_FRAME_DOUBLE 0.8
|
|
353
|
+
#define OMX_GROWTH_MIN_TOTAL_RISE_DB 6
|
|
354
|
+
#define OMX_GROWTH_WINDOW_FRAMES 5
|
|
299
355
|
#define OMX_HPF_FREQ_RANGE_MAX 1000
|
|
300
356
|
#define OMX_HPF_FREQ_RANGE_MIN 20
|
|
301
357
|
#define OMX_HPF_FREQ_RANGE_STEP 10
|
|
358
|
+
#define OMX_HRP_AMOUNT_RANGE_DEFAULT 0.5f
|
|
359
|
+
#define OMX_HRP_AMOUNT_RANGE_DEFAULT_DOUBLE 0.5
|
|
360
|
+
#define OMX_HRP_AMOUNT_RANGE_MAX 1
|
|
361
|
+
#define OMX_HRP_AMOUNT_RANGE_MIN 0
|
|
362
|
+
#define OMX_HRP_AMOUNT_RANGE_STEP 0
|
|
363
|
+
#define OMX_HRP_ATTRIBUTION_CENTS 60
|
|
364
|
+
#define OMX_HRP_BAND_Q 5
|
|
365
|
+
#define OMX_HRP_COLLISION_CENTS 100
|
|
366
|
+
#define OMX_HRP_DEFAULT_MAX_AUTO_BANDS 8
|
|
367
|
+
#define OMX_HRP_EXCESS_THRESHOLD_DB 3
|
|
368
|
+
#define OMX_HRP_GAIN_STEP_DB 2
|
|
369
|
+
#define OMX_HRP_MAX_CUT_DB 6
|
|
370
|
+
#define OMX_HRP_MAX_VOICES 8
|
|
302
371
|
#define OMX_LPF_FREQ_RANGE_MAX 20000
|
|
303
372
|
#define OMX_LPF_FREQ_RANGE_MIN 1000
|
|
304
373
|
#define OMX_LPF_FREQ_RANGE_STEP 10
|
|
374
|
+
#define OMX_OPERATOR_EQ_BANDS_RESERVE 9
|
|
305
375
|
#define OMX_PAN_RANGE_MAX 1
|
|
306
376
|
#define OMX_PAN_RANGE_MIN -1
|
|
307
377
|
#define OMX_PAN_RANGE_STEP 0
|
|
@@ -322,6 +392,7 @@
|
|
|
322
392
|
#define OMX_PHASER_FEEDBACK_RANGE_MIN_DOUBLE -0.9
|
|
323
393
|
#define OMX_PHASER_FEEDBACK_RANGE_STEP 0.01f
|
|
324
394
|
#define OMX_PHASER_FEEDBACK_RANGE_STEP_DOUBLE 0.01
|
|
395
|
+
#define OMX_PHASER_F_TOP_HZ 16000
|
|
325
396
|
#define OMX_PHASER_MIX_RANGE_DEFAULT 50
|
|
326
397
|
#define OMX_PHASER_MIX_RANGE_MAX 100
|
|
327
398
|
#define OMX_PHASER_MIX_RANGE_MIN 0
|
|
@@ -349,11 +420,14 @@
|
|
|
349
420
|
#define OMX_PROGRAM_RELEASE_PROFILES_OPTO_SHARE_DOUBLE 0.5
|
|
350
421
|
#define OMX_PROGRAM_RELEASE_PROFILES_OPTO_SLOW_MAX_MS 1100
|
|
351
422
|
#define OMX_PROGRAM_RELEASE_PROFILES_OPTO_SLOW_MIN_MS 110
|
|
423
|
+
#define OMX_PSHR_MIN_DB 10
|
|
352
424
|
#define OMX_REVERB_DAMPING_RANGE_DEFAULT 0.5f
|
|
353
425
|
#define OMX_REVERB_DAMPING_RANGE_DEFAULT_DOUBLE 0.5
|
|
354
426
|
#define OMX_REVERB_DAMPING_RANGE_MAX 1
|
|
355
427
|
#define OMX_REVERB_DAMPING_RANGE_MIN 0
|
|
356
428
|
#define OMX_REVERB_DAMPING_RANGE_STEP 0
|
|
429
|
+
#define OMX_REVERB_GATE_ATTACK_MS 1.5f
|
|
430
|
+
#define OMX_REVERB_GATE_ATTACK_MS_DOUBLE 1.5
|
|
357
431
|
#define OMX_REVERB_GATE_THRESHOLD_RANGE_DEFAULT -40
|
|
358
432
|
#define OMX_REVERB_GATE_THRESHOLD_RANGE_MAX 0
|
|
359
433
|
#define OMX_REVERB_GATE_THRESHOLD_RANGE_MIN -80
|
|
@@ -460,8 +534,12 @@
|
|
|
460
534
|
#define OMX_ROTARY_RING_FLOATS 256
|
|
461
535
|
#define OMX_ROTARY_STOP_EPS 0.0001f
|
|
462
536
|
#define OMX_ROTARY_STOP_EPS_DOUBLE 0.0001
|
|
537
|
+
#define OMX_RTA_FFT_SIZE_MAX 32768
|
|
538
|
+
#define OMX_RTA_TARGET_BIN_HZ 5.9f
|
|
539
|
+
#define OMX_RTA_TARGET_BIN_HZ_DOUBLE 5.9
|
|
463
540
|
#define OMX_RT_HARD_TARGET_QUANTUM 128
|
|
464
541
|
#define OMX_RT_HARD_TARGET_RATE 192000
|
|
542
|
+
#define OMX_SUBHARMONIC_RADIUS_BINS 2
|
|
465
543
|
#define OMX_TRANSIENT_FAST_ATTACK_MS 0.5f
|
|
466
544
|
#define OMX_TRANSIENT_FAST_ATTACK_MS_DOUBLE 0.5
|
|
467
545
|
#define OMX_TRANSIENT_FAST_RELEASE_MS 20
|
|
@@ -492,11 +570,131 @@
|
|
|
492
570
|
#define OMX_XOVER_PARTITION_TOLERANCE_DOUBLE 0.00001
|
|
493
571
|
|
|
494
572
|
/* Every list rendered to C, sorted by list: OMX_<LIST>_COUNT and OMX_<LIST>_INIT { a, b, … }. */
|
|
573
|
+
#define OMX_EQ_CENTRE_SERIES_R20_HZ_COUNT 61u
|
|
574
|
+
#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 }
|
|
575
|
+
#define OMX_EQ_DEFAULT_CENTRES_FOUR_BAND_HZ_COUNT 4u
|
|
576
|
+
#define OMX_EQ_DEFAULT_CENTRES_FOUR_BAND_HZ_INIT { 100, 400, 2000, 8000 }
|
|
577
|
+
#define OMX_ISO_THIRD_OCTAVE_CENTRES_HZ_COUNT 31u
|
|
578
|
+
#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 }
|
|
579
|
+
#define OMX_ORACLE_FLOOR_RATES_COUNT 4u
|
|
580
|
+
#define OMX_ORACLE_FLOOR_RATES_INIT { 44100, 48000, 96000, 192000 }
|
|
495
581
|
#define OMX_PHASER_STAGE_COUNTS_COUNT 6u
|
|
496
582
|
#define OMX_PHASER_STAGE_COUNTS_INIT { 2, 4, 6, 8, 10, 12 }
|
|
583
|
+
#define OMX_RME_RATES_COUNT 9u
|
|
584
|
+
#define OMX_RME_RATES_INIT { 32000, 44100, 48000, 64000, 88200, 96000, 128000, 176400, 192000 }
|
|
497
585
|
#define OMX_STANDARD_SAMPLE_RATES_COUNT 6u
|
|
498
586
|
#define OMX_STANDARD_SAMPLE_RATES_INIT { 44100, 48000, 88200, 96000, 176400, 192000 }
|
|
499
587
|
|
|
588
|
+
/* 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,
|
|
589
|
+
* where the set names a default, `OMX_<SET>_DEFAULT`. */
|
|
590
|
+
enum omx_deess_modes {
|
|
591
|
+
OMX_DEESS_MODES_SPLIT = 0,
|
|
592
|
+
OMX_DEESS_MODES_WIDEBAND = 1,
|
|
593
|
+
};
|
|
594
|
+
#define OMX_DEESS_MODES_COUNT 2u
|
|
595
|
+
enum omx_drive_bands {
|
|
596
|
+
OMX_DRIVE_BANDS_FULL = 0,
|
|
597
|
+
OMX_DRIVE_BANDS_LOW = 1,
|
|
598
|
+
OMX_DRIVE_BANDS_HIGH = 2,
|
|
599
|
+
OMX_DRIVE_BANDS_TILT = 3,
|
|
600
|
+
};
|
|
601
|
+
#define OMX_DRIVE_BANDS_COUNT 4u
|
|
602
|
+
enum omx_drive_curves {
|
|
603
|
+
OMX_DRIVE_CURVES_SOFT = 0,
|
|
604
|
+
OMX_DRIVE_CURVES_TAPE = 1,
|
|
605
|
+
OMX_DRIVE_CURVES_TUBE = 2,
|
|
606
|
+
OMX_DRIVE_CURVES_EXCITER = 3,
|
|
607
|
+
};
|
|
608
|
+
#define OMX_DRIVE_CURVES_COUNT 4u
|
|
609
|
+
enum omx_eq_band_types {
|
|
610
|
+
OMX_EQ_BAND_TYPES_BELL = 0,
|
|
611
|
+
OMX_EQ_BAND_TYPES_LOW_SHELF = 1,
|
|
612
|
+
OMX_EQ_BAND_TYPES_HIGH_SHELF = 2,
|
|
613
|
+
OMX_EQ_BAND_TYPES_NOTCH = 3,
|
|
614
|
+
OMX_EQ_BAND_TYPES_ALLPASS1 = 4,
|
|
615
|
+
OMX_EQ_BAND_TYPES_ALLPASS2 = 5,
|
|
616
|
+
};
|
|
617
|
+
#define OMX_EQ_BAND_TYPES_COUNT 6u
|
|
618
|
+
#define OMX_EQ_BAND_TYPES_DEFAULT OMX_EQ_BAND_TYPES_BELL
|
|
619
|
+
enum omx_filter_slopes {
|
|
620
|
+
OMX_FILTER_SLOPES_12 = 12,
|
|
621
|
+
OMX_FILTER_SLOPES_24 = 24,
|
|
622
|
+
};
|
|
623
|
+
#define OMX_FILTER_SLOPES_COUNT 2u
|
|
624
|
+
#define OMX_FILTER_SLOPES_DEFAULT OMX_FILTER_SLOPES_12
|
|
625
|
+
enum omx_gate_key_sources {
|
|
626
|
+
OMX_GATE_KEY_SOURCES_SELF = 0,
|
|
627
|
+
OMX_GATE_KEY_SOURCES_SIDECHAIN = 1,
|
|
628
|
+
};
|
|
629
|
+
#define OMX_GATE_KEY_SOURCES_COUNT 2u
|
|
630
|
+
enum omx_param_scales {
|
|
631
|
+
OMX_PARAM_SCALES_LINEAR = 0,
|
|
632
|
+
OMX_PARAM_SCALES_LOG = 1,
|
|
633
|
+
OMX_PARAM_SCALES_STEPPED = 2,
|
|
634
|
+
};
|
|
635
|
+
#define OMX_PARAM_SCALES_COUNT 3u
|
|
636
|
+
#define OMX_PARAM_SCALES_DEFAULT OMX_PARAM_SCALES_LINEAR
|
|
637
|
+
enum omx_reverb_algorithms {
|
|
638
|
+
OMX_REVERB_ALGORITHMS_ROOM = 0,
|
|
639
|
+
OMX_REVERB_ALGORITHMS_PLATE = 1,
|
|
640
|
+
OMX_REVERB_ALGORITHMS_HALL = 2,
|
|
641
|
+
OMX_REVERB_ALGORITHMS_REVERSE = 3,
|
|
642
|
+
OMX_REVERB_ALGORITHMS_GATED = 4,
|
|
643
|
+
};
|
|
644
|
+
#define OMX_REVERB_ALGORITHMS_COUNT 5u
|
|
645
|
+
enum omx_rotary_speeds {
|
|
646
|
+
OMX_ROTARY_SPEEDS_STOP = 0,
|
|
647
|
+
OMX_ROTARY_SPEEDS_SLOW = 1,
|
|
648
|
+
OMX_ROTARY_SPEEDS_FAST = 2,
|
|
649
|
+
};
|
|
650
|
+
#define OMX_ROTARY_SPEEDS_COUNT 3u
|
|
651
|
+
enum omx_tremolo_modes {
|
|
652
|
+
OMX_TREMOLO_MODES_TREMOLO = 0,
|
|
653
|
+
OMX_TREMOLO_MODES_PAN = 1,
|
|
654
|
+
};
|
|
655
|
+
#define OMX_TREMOLO_MODES_COUNT 2u
|
|
656
|
+
#define OMX_TREMOLO_MODES_DEFAULT OMX_TREMOLO_MODES_TREMOLO
|
|
657
|
+
|
|
658
|
+
/* The default bands of an EQ with `count` bands: THE one rule, for every strip, host and count (omx-contract's
|
|
659
|
+
* lib/eq-defaults.mjs; the ts render exports the same as eqDefaultCentres and eqDefaultTypes). Needs -lm. */
|
|
660
|
+
static inline unsigned omx_eq_default_centres(unsigned count, float *out) {
|
|
661
|
+
static const double r10[] = OMX_ISO_THIRD_OCTAVE_CENTRES_HZ_INIT;
|
|
662
|
+
static const double r20[] = OMX_EQ_CENTRE_SERIES_R20_HZ_INIT;
|
|
663
|
+
static const double four[] = OMX_EQ_DEFAULT_CENTRES_FOUR_BAND_HZ_INIT;
|
|
664
|
+
if (count == 0) return 0;
|
|
665
|
+
if (count == 4) {
|
|
666
|
+
for (unsigned i = 0; i < 4; i++) out[i] = (float)four[i];
|
|
667
|
+
return 4;
|
|
668
|
+
}
|
|
669
|
+
const double lo = log((double)OMX_EQ_FREQ_RANGE_MIN);
|
|
670
|
+
const double span = log((double)OMX_EQ_FREQ_RANGE_MAX / (double)OMX_EQ_FREQ_RANGE_MIN);
|
|
671
|
+
for (unsigned s = 0; s < 2; s++) {
|
|
672
|
+
const double *series = s ? r20 : r10;
|
|
673
|
+
const unsigned n = s ? OMX_EQ_CENTRE_SERIES_R20_HZ_COUNT : OMX_ISO_THIRD_OCTAVE_CENTRES_HZ_COUNT;
|
|
674
|
+
int distinct = count <= n;
|
|
675
|
+
for (unsigned i = 0; distinct && i < count; i++) {
|
|
676
|
+
const double t = lo + span * ((double)i + 0.5) / (double)count;
|
|
677
|
+
unsigned best = 0;
|
|
678
|
+
double best_d = 1e300;
|
|
679
|
+
for (unsigned k = 0; k < n; k++) {
|
|
680
|
+
const double d = fabs(log(series[k]) - t);
|
|
681
|
+
if (d < best_d) { best_d = d; best = k; }
|
|
682
|
+
}
|
|
683
|
+
out[i] = (float)series[best];
|
|
684
|
+
if (i > 0 && out[i] == out[i - 1]) distinct = 0;
|
|
685
|
+
}
|
|
686
|
+
if (distinct) return count;
|
|
687
|
+
}
|
|
688
|
+
return 0;
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
/* The default type of band `index` of an EQ with `count` bands: a low shelf first, a high shelf last, bells
|
|
692
|
+
* between (a single band is a bell). An OMX_EQ_BAND_TYPES_* member. */
|
|
693
|
+
static inline int omx_eq_default_type(unsigned index, unsigned count) {
|
|
694
|
+
if (count < 2) return OMX_EQ_BAND_TYPES_BELL;
|
|
695
|
+
return index == 0 ? OMX_EQ_BAND_TYPES_LOW_SHELF : index == count - 1 ? OMX_EQ_BAND_TYPES_HIGH_SHELF : OMX_EQ_BAND_TYPES_BELL;
|
|
696
|
+
}
|
|
697
|
+
|
|
500
698
|
#endif /* OMX_CONTRACT_LIMITS_H */
|
|
501
699
|
|
|
502
700
|
/* The sample rates the console declares (core's STANDARD_SAMPLE_RATES, row-codecs.ts): the set a
|
package/lib/data.mjs
CHANGED
|
@@ -50,6 +50,7 @@ export function rawValue(item) {
|
|
|
50
50
|
case 'travels': return item.fields ?? item.travel;
|
|
51
51
|
case 'sheet': return item.value;
|
|
52
52
|
case 'list': return item.values;
|
|
53
|
+
case 'set': return item.ids;
|
|
53
54
|
default: return undefined;
|
|
54
55
|
}
|
|
55
56
|
}
|
|
@@ -66,6 +67,11 @@ export const DERIVATIONS = {
|
|
|
66
67
|
if (typeof v !== 'number' || v < 0) throw new Error(`sqrt: ${JSON.stringify(d.of)} is not a non-negative number`);
|
|
67
68
|
return Math.sqrt(v);
|
|
68
69
|
},
|
|
70
|
+
ceilSum: (d, val) => {
|
|
71
|
+
const terms = d.of.map((x) => val(x));
|
|
72
|
+
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`);
|
|
73
|
+
return Math.ceil(terms.reduce((a, t) => a + t, 0));
|
|
74
|
+
},
|
|
69
75
|
lagrangeReadL1: (d, val) => {
|
|
70
76
|
const order = val(d.order);
|
|
71
77
|
if (!Number.isInteger(order) || order < 1) throw new Error(`lagrangeReadL1: order ${order} is not a positive integer`);
|
|
@@ -104,7 +110,7 @@ export function lagrangeReadL1(order) {
|
|
|
104
110
|
const isObj = (v) => typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
105
111
|
|
|
106
112
|
/**
|
|
107
|
-
* Resolve every item: `{ name, rel, kind, doc, why?, unit?, c?, shape?, value }
|
|
113
|
+
* Resolve every item: `{ name, rel, kind, doc, why?, unit?, c?, shape?, default?, labels?, value }` (default and labels: a set's), where `value` has
|
|
108
114
|
* every `{ref}` and `{derive}` evaluated.
|
|
109
115
|
* @throws naming the item: a reference that does not resolve, a cycle, an unknown derivation.
|
|
110
116
|
*/
|
|
@@ -142,6 +148,10 @@ export function resolveData(data) {
|
|
|
142
148
|
if (item.why !== undefined) r.why = item.why;
|
|
143
149
|
if (item.unit !== undefined) r.unit = item.unit;
|
|
144
150
|
if (item.c !== undefined) r.c = item.c;
|
|
151
|
+
if (item.kind === 'set') {
|
|
152
|
+
if (item.default !== undefined) r.default = item.default;
|
|
153
|
+
if (item.labels !== undefined) r.labels = item.labels;
|
|
154
|
+
}
|
|
145
155
|
if (item.kind === 'travels') r.shape = item.fields ? 'table' : 'travel';
|
|
146
156
|
r.value = val(rawValue(item), name);
|
|
147
157
|
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
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
const ORDER = {
|
|
10
|
-
item: ['kind', 'doc', 'why', 'unit', 'value', 'values', 'fields', 'travel', 'c'],
|
|
11
|
-
travel: ['min', 'max', 'step', 'unit', 'default', 'defaultFrom', 'byKind', 'doc', 'why'],
|
|
10
|
+
item: ['kind', 'since', 'doc', 'why', 'unit', 'value', 'values', 'ids', 'default', 'labels', 'fields', 'travel', 'c'],
|
|
11
|
+
travel: ['min', 'max', 'step', 'unit', 'default', 'defaultFrom', 'scale', 'byKind', 'doc', 'why'],
|
|
12
12
|
c: ['alias', 'render'],
|
|
13
13
|
alias: ['fact', 'field'],
|
|
14
14
|
number: ['ref', 'derive', 'of', 'order'],
|
package/lib/semver.mjs
CHANGED
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
* major a field or alias removed; an item removed (MINOR in the development phase, below); a
|
|
8
8
|
* unit or kind changed; a travel narrowed; a constant a kernel computes with changed (a
|
|
9
9
|
* scalar, sheet leaf or derived value that is not a travel bound or default; a list member
|
|
10
|
-
* changed or removed)
|
|
11
|
-
* minor an item, field, sheet leaf
|
|
10
|
+
* or set id changed or removed; a set's default added, removed)
|
|
11
|
+
* minor an item, field, sheet leaf, list member or set id added (appended); a travel widened;
|
|
12
12
|
* a default moved inside its travel; a step changed
|
|
13
13
|
* patch doc and why text
|
|
14
14
|
*/
|
|
@@ -32,6 +32,7 @@ function travelChanges(at, a, b, say) {
|
|
|
32
32
|
if (a.default !== b.default) say(a.default === undefined || b.default === undefined ? 'major' : 'minor', `${at}: default ${a.default} -> ${b.default}`);
|
|
33
33
|
if (a.step !== b.step) say('minor', `${at}: step ${a.step} -> ${b.step}`);
|
|
34
34
|
if (a.defaultFrom !== b.defaultFrom) say('minor', `${at}: defaultFrom ${a.defaultFrom} -> ${b.defaultFrom}`);
|
|
35
|
+
if (a.scale !== b.scale) say('minor', `${at}: scale ${a.scale} -> ${b.scale}`);
|
|
35
36
|
const ka = a.byKind ?? {};
|
|
36
37
|
const kb = b.byKind ?? {};
|
|
37
38
|
for (const k of Object.keys(ka)) if (!(k in kb)) say('major', `${at}.byKind.${k} removed`);
|
|
@@ -92,6 +93,15 @@ export function classify(prev, next, { developmentPhase = DEVELOPMENT_PHASE } =
|
|
|
92
93
|
});
|
|
93
94
|
if (b.value.length > a.value.length) say('minor', `${name}: ${b.value.length - a.value.length} member(s) appended`);
|
|
94
95
|
break;
|
|
96
|
+
case 'set':
|
|
97
|
+
a.value.forEach((v, i) => {
|
|
98
|
+
if (i >= b.value.length) say('major', `${name}[${i}] removed`);
|
|
99
|
+
else if (b.value[i] !== v) say('major', `${name}[${i}]: ${v} -> ${b.value[i]}`);
|
|
100
|
+
});
|
|
101
|
+
if (b.value.length > a.value.length) say('minor', `${name}: ${b.value.length - a.value.length} id(s) appended`);
|
|
102
|
+
if (a.default !== b.default) say(a.default === undefined || b.default === undefined ? 'major' : 'minor', `${name}: default ${a.default} -> ${b.default}`);
|
|
103
|
+
if (!same(a.labels, b.labels)) say('patch', `${name}: labels`);
|
|
104
|
+
break;
|
|
95
105
|
default:
|
|
96
106
|
break;
|
|
97
107
|
}
|
package/lib/validate.mjs
CHANGED
|
@@ -9,6 +9,7 @@ import { readFileSync } from 'node:fs';
|
|
|
9
9
|
import { posix } from 'node:path';
|
|
10
10
|
import Ajv2020 from 'ajv/dist/2020.js';
|
|
11
11
|
import { resolveData } from './data.mjs';
|
|
12
|
+
import { eqDefaultBands, eqDefaultParams } from './eq-defaults.mjs';
|
|
12
13
|
import { renderC } from '../render/c.mjs';
|
|
13
14
|
import { renderTs } from '../render/ts.mjs';
|
|
14
15
|
|
|
@@ -22,6 +23,62 @@ export function schemaValidator() {
|
|
|
22
23
|
|
|
23
24
|
const constCase = (s) => s.replace(/([a-z0-9])([A-Z])/g, '$1_$2').toUpperCase();
|
|
24
25
|
|
|
26
|
+
/**
|
|
27
|
+
* The rules about the meaning of the numbers, not their shape (they live with the data they judge):
|
|
28
|
+
* a set's default and labels; a travel's scale is a PARAM_SCALES id; the EQ band counts and budget; the
|
|
29
|
+
* default EQ rule's inputs.
|
|
30
|
+
*/
|
|
31
|
+
function semanticRules(resolved, say) {
|
|
32
|
+
const val = (name) => resolved.get(name)?.value;
|
|
33
|
+
for (const r of resolved.values()) {
|
|
34
|
+
if (r.kind === 'set') {
|
|
35
|
+
if (r.default !== undefined && !r.value.includes(r.default)) say(r.rel, r.name, 'set-default', `default ${JSON.stringify(r.default)} is not one of ${JSON.stringify(r.value)}`);
|
|
36
|
+
if (r.labels !== undefined && r.labels.length !== r.value.length) say(r.rel, r.name, 'set-labels', `${r.labels.length} labels for ${r.value.length} ids`);
|
|
37
|
+
}
|
|
38
|
+
const travels = r.kind === 'travels' ? (r.shape === 'table' ? Object.entries(r.value) : [['', r.value]]) : [];
|
|
39
|
+
for (const [field, t] of travels) {
|
|
40
|
+
if (t.scale !== undefined && !(val('PARAM_SCALES') ?? []).includes(t.scale)) say(r.rel, r.name, 'scale', `${field ? `${r.name}.${field}` : r.name}: scale ${JSON.stringify(t.scale)} is not an id of PARAM_SCALES`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// The EQ band budget (ruling 2026-10-08): what the operator keeps, what the feedback suppressor plants
|
|
45
|
+
// and what the ring correction plants all fit in the band maximum.
|
|
46
|
+
const reserve = val('OPERATOR_EQ_BANDS_RESERVE');
|
|
47
|
+
if (reserve !== undefined) {
|
|
48
|
+
const need = reserve + val('FBS_DEFAULT_MAX_AUTO_BANDS') + val('HRP_DEFAULT_MAX_AUTO_BANDS');
|
|
49
|
+
const cap = val('EQ_MAX_BANDS');
|
|
50
|
+
if (!(need <= cap)) say(resolved.get('OPERATOR_EQ_BANDS_RESERVE').rel, 'OPERATOR_EQ_BANDS_RESERVE', 'eq-band-budget',
|
|
51
|
+
`OPERATOR_EQ_BANDS_RESERVE ${reserve} + FBS_DEFAULT_MAX_AUTO_BANDS ${val('FBS_DEFAULT_MAX_AUTO_BANDS')} + HRP_DEFAULT_MAX_AUTO_BANDS ${val('HRP_DEFAULT_MAX_AUTO_BANDS')} = ${need} exceeds EQ_MAX_BANDS ${cap}`);
|
|
52
|
+
}
|
|
53
|
+
const counts = val('EQ_BAND_COUNTS');
|
|
54
|
+
if (counts) {
|
|
55
|
+
const rel = resolved.get('EQ_BAND_COUNTS').rel;
|
|
56
|
+
for (const [strip, c] of Object.entries(counts)) {
|
|
57
|
+
for (const k of ['default', 'max']) if (!Number.isInteger(c[k]) || c[k] < 1) say(rel, 'EQ_BAND_COUNTS', 'eq-band-counts', `${strip}.${k} ${c[k]} is not a positive integer`);
|
|
58
|
+
if (c.default > c.max) say(rel, 'EQ_BAND_COUNTS', 'eq-band-counts', `${strip}: default ${c.default} exceeds max ${c.max}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// The default EQ rule: its inputs are consistent and it answers for every declared default count.
|
|
63
|
+
if (resolved.has('EQ_DEFAULT_CENTRES_FOUR_BAND_HZ')) {
|
|
64
|
+
const rel = resolved.get('EQ_DEFAULT_CENTRES_FOUR_BAND_HZ').rel;
|
|
65
|
+
const bad = (rule, message) => say(rel, 'EQ_DEFAULT_CENTRES_FOUR_BAND_HZ', rule, message);
|
|
66
|
+
let p;
|
|
67
|
+
try { p = eqDefaultParams(resolved); } catch (e) { bad('eq-default-rule', e.message); return; }
|
|
68
|
+
const [r10, r20] = p.series;
|
|
69
|
+
if (p.four.length !== 4) bad('eq-default-rule', `the four-band set holds ${p.four.length} centres`);
|
|
70
|
+
for (const [name, list] of [['four-band set', p.four], ['R10', r10], ['R20', r20]]) {
|
|
71
|
+
if (!list.every((f, i) => f >= p.lo && f <= p.hi && (i === 0 || f > list[i - 1]))) bad('eq-default-rule', `the ${name} is not ascending inside [${p.lo}, ${p.hi}] Hz`);
|
|
72
|
+
}
|
|
73
|
+
for (const f of [...p.four, ...r10]) if (!r20.includes(f)) bad('eq-default-rule', `${f} Hz is not in the R20 series: R10 and the four-band set are preferred values of it`);
|
|
74
|
+
const types = val('EQ_BAND_TYPES') ?? [];
|
|
75
|
+
for (const id of ['bell', 'lowShelf', 'highShelf']) if (!types.includes(id)) bad('eq-default-rule', `EQ_BAND_TYPES lacks ${id}, which the default rule uses`);
|
|
76
|
+
for (const [strip, c] of Object.entries(counts ?? {})) {
|
|
77
|
+
try { eqDefaultBands(c.default, p); } catch (e) { bad('eq-default-rule', `${strip}: ${e.message}`); }
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
25
82
|
/** Every problem of the loaded data: `[{ file, item, rule, message }]`; empty is valid. */
|
|
26
83
|
export function validateData(data) {
|
|
27
84
|
const problems = [];
|
|
@@ -71,6 +128,8 @@ export function validateData(data) {
|
|
|
71
128
|
if (typeof r.doc !== 'string' || !r.doc.trim()) say(r.rel, r.name, 'doc', 'every item carries its doc');
|
|
72
129
|
}
|
|
73
130
|
|
|
131
|
+
semanticRules(resolved, say);
|
|
132
|
+
|
|
74
133
|
for (const [target, files] of [['c', () => renderC(resolved)], ['ts', () => renderTs(resolved)]]) {
|
|
75
134
|
let out;
|
|
76
135
|
try {
|
|
@@ -82,7 +141,7 @@ export function validateData(data) {
|
|
|
82
141
|
if (target !== 'c') continue;
|
|
83
142
|
for (const f of out) {
|
|
84
143
|
const seen = new Map();
|
|
85
|
-
for (const m of f.text.matchAll(
|
|
144
|
+
for (const m of f.text.matchAll(/^(?:#define | )(OMX_\w+)(?= = |\s)/gm)) {
|
|
86
145
|
if (seen.has(m[1])) say('-', m[1], 'c-name-unique', `${f.path} defines ${m[1]} twice`);
|
|
87
146
|
seen.set(m[1], true);
|
|
88
147
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openmixer/omx-contract",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.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",
|