@openmixer/omx-contract 0.0.0 → 1.1.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 +53 -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/deesser.json +93 -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/flanger.json +51 -0
- package/data/kernels/gate.json +81 -0
- package/data/kernels/geq.json +33 -0
- package/data/kernels/limiter.json +33 -0
- package/data/kernels/phaser.json +109 -0
- package/data/kernels/pitch.json +35 -0
- package/data/kernels/reverb.json +15 -0
- package/data/kernels/rotary.json +186 -0
- package/data/kernels/transient.json +73 -0
- package/data/kernels/tremolo.json +54 -0
- package/data/primitives.json +47 -0
- package/data/rates.json +30 -0
- package/dist/ts/omx-contract.d.ts +1071 -0
- package/dist/ts/omx-contract.js +1117 -0
- package/include/omxcontract/omx_contract_limits.h +381 -0
- package/lib/data.mjs +159 -0
- package/lib/fmt.mjs +61 -0
- package/lib/semver.mjs +125 -0
- package/lib/validate.mjs +92 -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 +94 -0
- package/render/doors.mjs +63 -0
- package/render/json.mjs +16 -0
- package/render/ts.mjs +41 -0
- package/schema/omx-contract.schema.json +164 -0
- package/share/omx-contract/omx-contract.json +1202 -0
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
2
|
+
// Copyright (C) 2026 Pau Aliagas <linuxnow@gmail.com>
|
|
3
|
+
#ifndef OMX_CONTRACT_LIMITS_H
|
|
4
|
+
#define OMX_CONTRACT_LIMITS_H
|
|
5
|
+
/*
|
|
6
|
+
* GENERATED — DO NOT EDIT BY HAND.
|
|
7
|
+
* Produced by `omx-contract render --target c` from FreeMixer/omx-contract's data/, the declaration
|
|
8
|
+
* as data (each item's reason is its `doc`). Change the data, never this file: a consumer builds
|
|
9
|
+
* against the render of the omx-contract version it pins and commits none.
|
|
10
|
+
*
|
|
11
|
+
* A C contract (OMX_PRE/OMX_POST/OMX_INVARIANT) reads a limit from HERE, never a literal.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/* Per-parameter numeric travel, one block per `travels` table named <PREFIX>_LIMITS:
|
|
15
|
+
* OMX_<PREFIX>_<FIELD>_MIN/_MAX/_DEFAULT, float literals. */
|
|
16
|
+
#define OMX_COMP_THRESHOLD_DB_MIN -60.0f
|
|
17
|
+
#define OMX_COMP_THRESHOLD_DB_MAX 0.0f
|
|
18
|
+
#define OMX_COMP_THRESHOLD_DB_DEFAULT -18.0f
|
|
19
|
+
#define OMX_COMP_RATIO_MIN 1.0f
|
|
20
|
+
#define OMX_COMP_RATIO_MAX 20.0f
|
|
21
|
+
#define OMX_COMP_RATIO_DEFAULT 4.0f
|
|
22
|
+
#define OMX_COMP_KNEE_DB_MIN 0.0f
|
|
23
|
+
#define OMX_COMP_KNEE_DB_MAX 24.0f
|
|
24
|
+
#define OMX_COMP_KNEE_DB_DEFAULT 6.0f
|
|
25
|
+
#define OMX_COMP_ATTACK_MS_MIN 0.1f
|
|
26
|
+
#define OMX_COMP_ATTACK_MS_MAX 100.0f
|
|
27
|
+
#define OMX_COMP_ATTACK_MS_DEFAULT 5.0f
|
|
28
|
+
#define OMX_COMP_RELEASE_MS_MIN 5.0f
|
|
29
|
+
#define OMX_COMP_RELEASE_MS_MAX 3000.0f
|
|
30
|
+
#define OMX_COMP_RELEASE_MS_DEFAULT 200.0f
|
|
31
|
+
#define OMX_COMP_MAKEUP_DB_MIN 0.0f
|
|
32
|
+
#define OMX_COMP_MAKEUP_DB_MAX 24.0f
|
|
33
|
+
#define OMX_COMP_MAKEUP_DB_DEFAULT 0.0f
|
|
34
|
+
#define OMX_COMP_MIX_PCT_MIN 0.0f
|
|
35
|
+
#define OMX_COMP_MIX_PCT_MAX 100.0f
|
|
36
|
+
#define OMX_COMP_MIX_PCT_DEFAULT 100.0f
|
|
37
|
+
|
|
38
|
+
#define OMX_GATE_THRESHOLD_DB_MIN -80.0f
|
|
39
|
+
#define OMX_GATE_THRESHOLD_DB_MAX 0.0f
|
|
40
|
+
#define OMX_GATE_THRESHOLD_DB_DEFAULT -40.0f
|
|
41
|
+
#define OMX_GATE_RANGE_DB_MIN -90.0f
|
|
42
|
+
#define OMX_GATE_RANGE_DB_MAX 0.0f
|
|
43
|
+
#define OMX_GATE_RANGE_DB_DEFAULT -90.0f
|
|
44
|
+
#define OMX_GATE_KNEE_START_DB_MIN -80.0f
|
|
45
|
+
#define OMX_GATE_KNEE_START_DB_MAX 0.0f
|
|
46
|
+
#define OMX_GATE_KNEE_START_DB_DEFAULT -43.0f
|
|
47
|
+
#define OMX_GATE_KNEE_END_DB_MIN -80.0f
|
|
48
|
+
#define OMX_GATE_KNEE_END_DB_MAX 0.0f
|
|
49
|
+
#define OMX_GATE_KNEE_END_DB_DEFAULT -37.0f
|
|
50
|
+
#define OMX_GATE_ATTACK_MS_MIN 0.0f
|
|
51
|
+
#define OMX_GATE_ATTACK_MS_MAX 500.0f
|
|
52
|
+
#define OMX_GATE_ATTACK_MS_DEFAULT 1.0f
|
|
53
|
+
#define OMX_GATE_HOLD_MS_MIN 0.0f
|
|
54
|
+
#define OMX_GATE_HOLD_MS_MAX 2000.0f
|
|
55
|
+
#define OMX_GATE_HOLD_MS_DEFAULT 10.0f
|
|
56
|
+
#define OMX_GATE_RELEASE_MS_MIN 0.0f
|
|
57
|
+
#define OMX_GATE_RELEASE_MS_MAX 5000.0f
|
|
58
|
+
#define OMX_GATE_RELEASE_MS_DEFAULT 100.0f
|
|
59
|
+
#define OMX_GATE_HYSTERESIS_DB_MIN 0.0f
|
|
60
|
+
#define OMX_GATE_HYSTERESIS_DB_MAX 24.0f
|
|
61
|
+
#define OMX_GATE_HYSTERESIS_DB_DEFAULT 3.0f
|
|
62
|
+
#define OMX_GATE_RATIO_MIN 1.0f
|
|
63
|
+
#define OMX_GATE_RATIO_MAX 100.0f
|
|
64
|
+
#define OMX_GATE_RATIO_DEFAULT 16.0f
|
|
65
|
+
|
|
66
|
+
#define OMX_LIMITER_CEILING_DB_MIN -12.0f
|
|
67
|
+
#define OMX_LIMITER_CEILING_DB_MAX 0.0f
|
|
68
|
+
#define OMX_LIMITER_CEILING_DB_DEFAULT -1.0f
|
|
69
|
+
#define OMX_LIMITER_LOOKAHEAD_MS_MIN 0.5f
|
|
70
|
+
#define OMX_LIMITER_LOOKAHEAD_MS_MAX 5.0f
|
|
71
|
+
#define OMX_LIMITER_LOOKAHEAD_MS_DEFAULT 1.5f
|
|
72
|
+
#define OMX_LIMITER_RELEASE_MS_MIN 1.0f
|
|
73
|
+
#define OMX_LIMITER_RELEASE_MS_MAX 1000.0f
|
|
74
|
+
#define OMX_LIMITER_RELEASE_MS_DEFAULT 50.0f
|
|
75
|
+
|
|
76
|
+
#define OMX_PITCH_SEMITONES_MIN -12.0f
|
|
77
|
+
#define OMX_PITCH_SEMITONES_MAX 12.0f
|
|
78
|
+
#define OMX_PITCH_SEMITONES_DEFAULT 0.0f
|
|
79
|
+
#define OMX_PITCH_CENTS_MIN -50.0f
|
|
80
|
+
#define OMX_PITCH_CENTS_MAX 50.0f
|
|
81
|
+
#define OMX_PITCH_CENTS_DEFAULT 0.0f
|
|
82
|
+
#define OMX_PITCH_MIX_MIN 0.0f
|
|
83
|
+
#define OMX_PITCH_MIX_MAX 100.0f
|
|
84
|
+
#define OMX_PITCH_MIX_DEFAULT 100.0f
|
|
85
|
+
|
|
86
|
+
#define OMX_TRANSIENT_ATTACK_DB_MIN -24.0f
|
|
87
|
+
#define OMX_TRANSIENT_ATTACK_DB_MAX 24.0f
|
|
88
|
+
#define OMX_TRANSIENT_ATTACK_DB_DEFAULT 0.0f
|
|
89
|
+
#define OMX_TRANSIENT_SUSTAIN_DB_MIN -24.0f
|
|
90
|
+
#define OMX_TRANSIENT_SUSTAIN_DB_MAX 24.0f
|
|
91
|
+
#define OMX_TRANSIENT_SUSTAIN_DB_DEFAULT 0.0f
|
|
92
|
+
#define OMX_TRANSIENT_ATTACK_TIME_MS_MIN 2.0f
|
|
93
|
+
#define OMX_TRANSIENT_ATTACK_TIME_MS_MAX 50.0f
|
|
94
|
+
#define OMX_TRANSIENT_ATTACK_TIME_MS_DEFAULT 10.0f
|
|
95
|
+
#define OMX_TRANSIENT_SUSTAIN_TIME_MS_MIN 50.0f
|
|
96
|
+
#define OMX_TRANSIENT_SUSTAIN_TIME_MS_MAX 2000.0f
|
|
97
|
+
#define OMX_TRANSIENT_SUSTAIN_TIME_MS_DEFAULT 250.0f
|
|
98
|
+
#define OMX_TRANSIENT_OUTPUT_DB_MIN -24.0f
|
|
99
|
+
#define OMX_TRANSIENT_OUTPUT_DB_MAX 12.0f
|
|
100
|
+
#define OMX_TRANSIENT_OUTPUT_DB_DEFAULT 0.0f
|
|
101
|
+
|
|
102
|
+
/* The second C spelling of a travel, its item's `c.alias` { fact, field }:
|
|
103
|
+
* OMX_<FACT>_<FIELD>_MIN/_MAX/_DEFAULT. Removed by a MAJOR release once no consumer reads it. */
|
|
104
|
+
#define OMX_DELAY_TIME_MS_MIN 0.0f
|
|
105
|
+
#define OMX_DELAY_TIME_MS_MAX 2000.0f
|
|
106
|
+
#define OMX_DELAY_TIME_MS_DEFAULT 300.0f
|
|
107
|
+
|
|
108
|
+
/* Every scalar, sheet leaf and single travel's numbers, one block sorted by macro. An integer value
|
|
109
|
+
* is an integer literal, any other a float literal AND its OMX_<macro>_DOUBLE spelling. */
|
|
110
|
+
#define OMX_ALLPASS_UNITY_TOLERANCE 0.0001f
|
|
111
|
+
#define OMX_ALLPASS_UNITY_TOLERANCE_DOUBLE 0.0001
|
|
112
|
+
#define OMX_BUTTERWORTH_Q 0.7071067811865476f
|
|
113
|
+
#define OMX_BUTTERWORTH_Q_DOUBLE 0.7071067811865476
|
|
114
|
+
#define OMX_CHORUS_SPREAD_RANGE_DEFAULT 0
|
|
115
|
+
#define OMX_CHORUS_SPREAD_RANGE_MAX 0.5f
|
|
116
|
+
#define OMX_CHORUS_SPREAD_RANGE_MAX_DOUBLE 0.5
|
|
117
|
+
#define OMX_CHORUS_SPREAD_RANGE_MIN 0
|
|
118
|
+
#define OMX_CHORUS_SPREAD_RANGE_STEP 0.01f
|
|
119
|
+
#define OMX_CHORUS_SPREAD_RANGE_STEP_DOUBLE 0.01
|
|
120
|
+
#define OMX_DEESS_ATTACK_RANGE_DEFAULT 1
|
|
121
|
+
#define OMX_DEESS_ATTACK_RANGE_MAX 50
|
|
122
|
+
#define OMX_DEESS_ATTACK_RANGE_MIN 0.1f
|
|
123
|
+
#define OMX_DEESS_ATTACK_RANGE_MIN_DOUBLE 0.1
|
|
124
|
+
#define OMX_DEESS_ATTACK_RANGE_STEP 0.1f
|
|
125
|
+
#define OMX_DEESS_ATTACK_RANGE_STEP_DOUBLE 0.1
|
|
126
|
+
#define OMX_DEESS_FREQ_RANGE_DEFAULT 7000
|
|
127
|
+
#define OMX_DEESS_FREQ_RANGE_MAX 16000
|
|
128
|
+
#define OMX_DEESS_FREQ_RANGE_MIN 2000
|
|
129
|
+
#define OMX_DEESS_FREQ_RANGE_STEP 10
|
|
130
|
+
#define OMX_DEESS_KNEE_DB 6
|
|
131
|
+
#define OMX_DEESS_RANGE_RANGE_DEFAULT -12
|
|
132
|
+
#define OMX_DEESS_RANGE_RANGE_MAX 0
|
|
133
|
+
#define OMX_DEESS_RANGE_RANGE_MIN -24
|
|
134
|
+
#define OMX_DEESS_RANGE_RANGE_STEP 0.5f
|
|
135
|
+
#define OMX_DEESS_RANGE_RANGE_STEP_DOUBLE 0.5
|
|
136
|
+
#define OMX_DEESS_RATIO_RANGE_DEFAULT 4
|
|
137
|
+
#define OMX_DEESS_RATIO_RANGE_MAX 20
|
|
138
|
+
#define OMX_DEESS_RATIO_RANGE_MIN 1
|
|
139
|
+
#define OMX_DEESS_RATIO_RANGE_STEP 0.1f
|
|
140
|
+
#define OMX_DEESS_RATIO_RANGE_STEP_DOUBLE 0.1
|
|
141
|
+
#define OMX_DEESS_RELEASE_RANGE_DEFAULT 60
|
|
142
|
+
#define OMX_DEESS_RELEASE_RANGE_MAX 500
|
|
143
|
+
#define OMX_DEESS_RELEASE_RANGE_MIN 5
|
|
144
|
+
#define OMX_DEESS_RELEASE_RANGE_STEP 1
|
|
145
|
+
#define OMX_DEESS_THRESHOLD_RANGE_DEFAULT -30
|
|
146
|
+
#define OMX_DEESS_THRESHOLD_RANGE_MAX 0
|
|
147
|
+
#define OMX_DEESS_THRESHOLD_RANGE_MIN -60
|
|
148
|
+
#define OMX_DEESS_THRESHOLD_RANGE_STEP 0.5f
|
|
149
|
+
#define OMX_DEESS_THRESHOLD_RANGE_STEP_DOUBLE 0.5
|
|
150
|
+
#define OMX_DEESS_WIDTH_RANGE_DEFAULT 1
|
|
151
|
+
#define OMX_DEESS_WIDTH_RANGE_MAX 4
|
|
152
|
+
#define OMX_DEESS_WIDTH_RANGE_MIN 0.25f
|
|
153
|
+
#define OMX_DEESS_WIDTH_RANGE_MIN_DOUBLE 0.25
|
|
154
|
+
#define OMX_DEESS_WIDTH_RANGE_STEP 0.05f
|
|
155
|
+
#define OMX_DEESS_WIDTH_RANGE_STEP_DOUBLE 0.05
|
|
156
|
+
#define OMX_DELAY_MIX_RANGE_BY_KIND_FX_RETURN 1
|
|
157
|
+
#define OMX_DELAY_MIX_RANGE_DEFAULT 0.3f
|
|
158
|
+
#define OMX_DELAY_MIX_RANGE_DEFAULT_DOUBLE 0.3
|
|
159
|
+
#define OMX_DELAY_MIX_RANGE_MAX 1
|
|
160
|
+
#define OMX_DELAY_MIX_RANGE_MIN 0
|
|
161
|
+
#define OMX_DELAY_MIX_RANGE_STEP 0
|
|
162
|
+
#define OMX_DELAY_TONE_RANGE_DEFAULT 0.3f
|
|
163
|
+
#define OMX_DELAY_TONE_RANGE_DEFAULT_DOUBLE 0.3
|
|
164
|
+
#define OMX_DELAY_TONE_RANGE_MAX 1
|
|
165
|
+
#define OMX_DELAY_TONE_RANGE_MIN 0
|
|
166
|
+
#define OMX_DELAY_TONE_RANGE_STEP 0
|
|
167
|
+
#define OMX_DRIVE_BIAS_MAX 0.7071067811865476f
|
|
168
|
+
#define OMX_DRIVE_BIAS_MAX_DOUBLE 0.7071067811865476
|
|
169
|
+
#define OMX_DSP_KNOB_REFERENCE_RATE 96000
|
|
170
|
+
#define OMX_EQ_MAX_BANDS 24
|
|
171
|
+
#define OMX_FDELAY_MOD_READ_ORDER 3
|
|
172
|
+
#define OMX_FDELAY_READ_L1_NORM 1.25f
|
|
173
|
+
#define OMX_FDELAY_READ_L1_NORM_DOUBLE 1.25
|
|
174
|
+
#define OMX_FLANGER_DEPTH_RANGE_DEFAULT 2
|
|
175
|
+
#define OMX_FLANGER_DEPTH_RANGE_MAX 5
|
|
176
|
+
#define OMX_FLANGER_DEPTH_RANGE_MIN 0
|
|
177
|
+
#define OMX_FLANGER_DEPTH_RANGE_STEP 0.1f
|
|
178
|
+
#define OMX_FLANGER_DEPTH_RANGE_STEP_DOUBLE 0.1
|
|
179
|
+
#define OMX_FLANGER_FEEDBACK_RANGE_DEFAULT 0.6f
|
|
180
|
+
#define OMX_FLANGER_FEEDBACK_RANGE_DEFAULT_DOUBLE 0.6
|
|
181
|
+
#define OMX_FLANGER_FEEDBACK_RANGE_MAX 0.95f
|
|
182
|
+
#define OMX_FLANGER_FEEDBACK_RANGE_MAX_DOUBLE 0.95
|
|
183
|
+
#define OMX_FLANGER_FEEDBACK_RANGE_MIN -0.95f
|
|
184
|
+
#define OMX_FLANGER_FEEDBACK_RANGE_MIN_DOUBLE -0.95
|
|
185
|
+
#define OMX_FLANGER_FEEDBACK_RANGE_STEP 0.01f
|
|
186
|
+
#define OMX_FLANGER_FEEDBACK_RANGE_STEP_DOUBLE 0.01
|
|
187
|
+
#define OMX_FLANGER_MIX_RANGE_DEFAULT 50
|
|
188
|
+
#define OMX_FLANGER_MIX_RANGE_MAX 100
|
|
189
|
+
#define OMX_FLANGER_MIX_RANGE_MIN 0
|
|
190
|
+
#define OMX_FLANGER_MIX_RANGE_STEP 0.1f
|
|
191
|
+
#define OMX_FLANGER_MIX_RANGE_STEP_DOUBLE 0.1
|
|
192
|
+
#define OMX_FLANGER_RATE_RANGE_DEFAULT 0.25f
|
|
193
|
+
#define OMX_FLANGER_RATE_RANGE_DEFAULT_DOUBLE 0.25
|
|
194
|
+
#define OMX_FLANGER_RATE_RANGE_MAX 5
|
|
195
|
+
#define OMX_FLANGER_RATE_RANGE_MIN 0.05f
|
|
196
|
+
#define OMX_FLANGER_RATE_RANGE_MIN_DOUBLE 0.05
|
|
197
|
+
#define OMX_FLANGER_RATE_RANGE_STEP 0.01f
|
|
198
|
+
#define OMX_FLANGER_RATE_RANGE_STEP_DOUBLE 0.01
|
|
199
|
+
#define OMX_FX_DELAY_FEEDBACK_RANGE_DEFAULT 0.3f
|
|
200
|
+
#define OMX_FX_DELAY_FEEDBACK_RANGE_DEFAULT_DOUBLE 0.3
|
|
201
|
+
#define OMX_FX_DELAY_FEEDBACK_RANGE_MAX 0.99f
|
|
202
|
+
#define OMX_FX_DELAY_FEEDBACK_RANGE_MAX_DOUBLE 0.99
|
|
203
|
+
#define OMX_FX_DELAY_FEEDBACK_RANGE_MIN 0
|
|
204
|
+
#define OMX_FX_DELAY_FEEDBACK_RANGE_STEP 0
|
|
205
|
+
#define OMX_FX_DELAY_TIME_RANGE_DEFAULT 300
|
|
206
|
+
#define OMX_FX_DELAY_TIME_RANGE_MAX 2000
|
|
207
|
+
#define OMX_FX_DELAY_TIME_RANGE_MIN 0
|
|
208
|
+
#define OMX_FX_DELAY_TIME_RANGE_STEP 1
|
|
209
|
+
#define OMX_GEQ_BANDS 31
|
|
210
|
+
#define OMX_GEQ_BAND_Q 4.3f
|
|
211
|
+
#define OMX_GEQ_BAND_Q_DOUBLE 4.3
|
|
212
|
+
#define OMX_GEQ_BAND_RANGE_DEFAULT 0
|
|
213
|
+
#define OMX_GEQ_BAND_RANGE_MAX 15
|
|
214
|
+
#define OMX_GEQ_BAND_RANGE_MIN -15
|
|
215
|
+
#define OMX_GEQ_BAND_RANGE_STEP 0.5f
|
|
216
|
+
#define OMX_GEQ_BAND_RANGE_STEP_DOUBLE 0.5
|
|
217
|
+
#define OMX_GEQ_DESIGN_GAIN_MAX_DB 30
|
|
218
|
+
#define OMX_GEQ_PROTO_DB 12
|
|
219
|
+
#define OMX_PHASER_BASE_RANGE_DEFAULT 200
|
|
220
|
+
#define OMX_PHASER_BASE_RANGE_MAX 2000
|
|
221
|
+
#define OMX_PHASER_BASE_RANGE_MIN 50
|
|
222
|
+
#define OMX_PHASER_BASE_RANGE_STEP 1
|
|
223
|
+
#define OMX_PHASER_DEPTH_RANGE_DEFAULT 4
|
|
224
|
+
#define OMX_PHASER_DEPTH_RANGE_MAX 6
|
|
225
|
+
#define OMX_PHASER_DEPTH_RANGE_MIN 0
|
|
226
|
+
#define OMX_PHASER_DEPTH_RANGE_STEP 0.1f
|
|
227
|
+
#define OMX_PHASER_DEPTH_RANGE_STEP_DOUBLE 0.1
|
|
228
|
+
#define OMX_PHASER_FEEDBACK_RANGE_DEFAULT 0.4f
|
|
229
|
+
#define OMX_PHASER_FEEDBACK_RANGE_DEFAULT_DOUBLE 0.4
|
|
230
|
+
#define OMX_PHASER_FEEDBACK_RANGE_MAX 0.9f
|
|
231
|
+
#define OMX_PHASER_FEEDBACK_RANGE_MAX_DOUBLE 0.9
|
|
232
|
+
#define OMX_PHASER_FEEDBACK_RANGE_MIN -0.9f
|
|
233
|
+
#define OMX_PHASER_FEEDBACK_RANGE_MIN_DOUBLE -0.9
|
|
234
|
+
#define OMX_PHASER_FEEDBACK_RANGE_STEP 0.01f
|
|
235
|
+
#define OMX_PHASER_FEEDBACK_RANGE_STEP_DOUBLE 0.01
|
|
236
|
+
#define OMX_PHASER_MIX_RANGE_DEFAULT 50
|
|
237
|
+
#define OMX_PHASER_MIX_RANGE_MAX 100
|
|
238
|
+
#define OMX_PHASER_MIX_RANGE_MIN 0
|
|
239
|
+
#define OMX_PHASER_MIX_RANGE_STEP 0.1f
|
|
240
|
+
#define OMX_PHASER_MIX_RANGE_STEP_DOUBLE 0.1
|
|
241
|
+
#define OMX_PHASER_RATE_RANGE_DEFAULT 0.5f
|
|
242
|
+
#define OMX_PHASER_RATE_RANGE_DEFAULT_DOUBLE 0.5
|
|
243
|
+
#define OMX_PHASER_RATE_RANGE_MAX 5
|
|
244
|
+
#define OMX_PHASER_RATE_RANGE_MIN 0.05f
|
|
245
|
+
#define OMX_PHASER_RATE_RANGE_MIN_DOUBLE 0.05
|
|
246
|
+
#define OMX_PHASER_RATE_RANGE_STEP 0.01f
|
|
247
|
+
#define OMX_PHASER_RATE_RANGE_STEP_DOUBLE 0.01
|
|
248
|
+
#define OMX_PHASER_STAGES_RANGE_DEFAULT 6
|
|
249
|
+
#define OMX_PHASER_STAGES_RANGE_MAX 12
|
|
250
|
+
#define OMX_PHASER_STAGES_RANGE_MIN 2
|
|
251
|
+
#define OMX_PHASER_STAGES_RANGE_STEP 2
|
|
252
|
+
#define OMX_PITCH_PREFILTER_CEILING_HZ 20000
|
|
253
|
+
#define OMX_PITCH_PREFILTER_Q 0.7071067811865476f
|
|
254
|
+
#define OMX_PITCH_PREFILTER_Q_DOUBLE 0.7071067811865476
|
|
255
|
+
#define OMX_PITCH_WINDOW_MS 40
|
|
256
|
+
#define OMX_PROGRAM_RELEASE_CHARGE_MS 1000
|
|
257
|
+
#define OMX_PROGRAM_RELEASE_DISCHARGE_MS 5000
|
|
258
|
+
#define OMX_PROGRAM_RELEASE_PROFILES_OPTO_FAST_MS 70
|
|
259
|
+
#define OMX_PROGRAM_RELEASE_PROFILES_OPTO_SHARE 0.5f
|
|
260
|
+
#define OMX_PROGRAM_RELEASE_PROFILES_OPTO_SHARE_DOUBLE 0.5
|
|
261
|
+
#define OMX_PROGRAM_RELEASE_PROFILES_OPTO_SLOW_MAX_MS 1100
|
|
262
|
+
#define OMX_PROGRAM_RELEASE_PROFILES_OPTO_SLOW_MIN_MS 110
|
|
263
|
+
#define OMX_REVERB_PLATE_MOD_DEPTH_RANGE_DEFAULT 100
|
|
264
|
+
#define OMX_REVERB_PLATE_MOD_DEPTH_RANGE_MAX 400
|
|
265
|
+
#define OMX_REVERB_PLATE_MOD_DEPTH_RANGE_MIN 0
|
|
266
|
+
#define OMX_REVERB_PLATE_MOD_DEPTH_RANGE_STEP 1
|
|
267
|
+
#define OMX_ROTARY_ACCEL_RANGE_DEFAULT 1
|
|
268
|
+
#define OMX_ROTARY_ACCEL_RANGE_MAX 4
|
|
269
|
+
#define OMX_ROTARY_ACCEL_RANGE_MIN 0.25f
|
|
270
|
+
#define OMX_ROTARY_ACCEL_RANGE_MIN_DOUBLE 0.25
|
|
271
|
+
#define OMX_ROTARY_ACCEL_RANGE_STEP 0.01f
|
|
272
|
+
#define OMX_ROTARY_ACCEL_RANGE_STEP_DOUBLE 0.01
|
|
273
|
+
#define OMX_ROTARY_BALANCE_RANGE_DEFAULT 0
|
|
274
|
+
#define OMX_ROTARY_BALANCE_RANGE_MAX 100
|
|
275
|
+
#define OMX_ROTARY_BALANCE_RANGE_MIN -100
|
|
276
|
+
#define OMX_ROTARY_BALANCE_RANGE_STEP 1
|
|
277
|
+
#define OMX_ROTARY_BASE_MS 0.1f
|
|
278
|
+
#define OMX_ROTARY_BASE_MS_DOUBLE 0.1
|
|
279
|
+
#define OMX_ROTARY_CROSSOVER_HZ 800
|
|
280
|
+
#define OMX_ROTARY_DRUM_ACCEL_MS 1700
|
|
281
|
+
#define OMX_ROTARY_DRUM_AM 0.3f
|
|
282
|
+
#define OMX_ROTARY_DRUM_AM_DOUBLE 0.3
|
|
283
|
+
#define OMX_ROTARY_DRUM_DECEL_MS 1800
|
|
284
|
+
#define OMX_ROTARY_DRUM_DOPPLER_MS 0.29f
|
|
285
|
+
#define OMX_ROTARY_DRUM_DOPPLER_MS_DOUBLE 0.29
|
|
286
|
+
#define OMX_ROTARY_DRUM_FAST_RANGE_DEFAULT 5.9f
|
|
287
|
+
#define OMX_ROTARY_DRUM_FAST_RANGE_DEFAULT_DOUBLE 5.9
|
|
288
|
+
#define OMX_ROTARY_DRUM_FAST_RANGE_MAX 10
|
|
289
|
+
#define OMX_ROTARY_DRUM_FAST_RANGE_MIN 3
|
|
290
|
+
#define OMX_ROTARY_DRUM_FAST_RANGE_STEP 0.01f
|
|
291
|
+
#define OMX_ROTARY_DRUM_FAST_RANGE_STEP_DOUBLE 0.01
|
|
292
|
+
#define OMX_ROTARY_DRUM_SLOW_RANGE_DEFAULT 0.7f
|
|
293
|
+
#define OMX_ROTARY_DRUM_SLOW_RANGE_DEFAULT_DOUBLE 0.7
|
|
294
|
+
#define OMX_ROTARY_DRUM_SLOW_RANGE_MAX 2
|
|
295
|
+
#define OMX_ROTARY_DRUM_SLOW_RANGE_MIN 0.1f
|
|
296
|
+
#define OMX_ROTARY_DRUM_SLOW_RANGE_MIN_DOUBLE 0.1
|
|
297
|
+
#define OMX_ROTARY_DRUM_SLOW_RANGE_STEP 0.01f
|
|
298
|
+
#define OMX_ROTARY_DRUM_SLOW_RANGE_STEP_DOUBLE 0.01
|
|
299
|
+
#define OMX_ROTARY_HORN_ACCEL_MS 330
|
|
300
|
+
#define OMX_ROTARY_HORN_AM 0.5f
|
|
301
|
+
#define OMX_ROTARY_HORN_AM_DOUBLE 0.5
|
|
302
|
+
#define OMX_ROTARY_HORN_DECEL_MS 500
|
|
303
|
+
#define OMX_ROTARY_HORN_DOPPLER_MS 0.44f
|
|
304
|
+
#define OMX_ROTARY_HORN_DOPPLER_MS_DOUBLE 0.44
|
|
305
|
+
#define OMX_ROTARY_HORN_FAST_RANGE_DEFAULT 6.8f
|
|
306
|
+
#define OMX_ROTARY_HORN_FAST_RANGE_DEFAULT_DOUBLE 6.8
|
|
307
|
+
#define OMX_ROTARY_HORN_FAST_RANGE_MAX 10
|
|
308
|
+
#define OMX_ROTARY_HORN_FAST_RANGE_MIN 3
|
|
309
|
+
#define OMX_ROTARY_HORN_FAST_RANGE_STEP 0.01f
|
|
310
|
+
#define OMX_ROTARY_HORN_FAST_RANGE_STEP_DOUBLE 0.01
|
|
311
|
+
#define OMX_ROTARY_HORN_SLOW_RANGE_DEFAULT 0.8f
|
|
312
|
+
#define OMX_ROTARY_HORN_SLOW_RANGE_DEFAULT_DOUBLE 0.8
|
|
313
|
+
#define OMX_ROTARY_HORN_SLOW_RANGE_MAX 2
|
|
314
|
+
#define OMX_ROTARY_HORN_SLOW_RANGE_MIN 0.1f
|
|
315
|
+
#define OMX_ROTARY_HORN_SLOW_RANGE_MIN_DOUBLE 0.1
|
|
316
|
+
#define OMX_ROTARY_HORN_SLOW_RANGE_STEP 0.01f
|
|
317
|
+
#define OMX_ROTARY_HORN_SLOW_RANGE_STEP_DOUBLE 0.01
|
|
318
|
+
#define OMX_ROTARY_MIX_RANGE_DEFAULT 100
|
|
319
|
+
#define OMX_ROTARY_MIX_RANGE_MAX 100
|
|
320
|
+
#define OMX_ROTARY_MIX_RANGE_MIN 0
|
|
321
|
+
#define OMX_ROTARY_MIX_RANGE_STEP 0.1f
|
|
322
|
+
#define OMX_ROTARY_MIX_RANGE_STEP_DOUBLE 0.1
|
|
323
|
+
#define OMX_ROTARY_RING_FLOATS 256
|
|
324
|
+
#define OMX_ROTARY_STOP_EPS 0.0001f
|
|
325
|
+
#define OMX_ROTARY_STOP_EPS_DOUBLE 0.0001
|
|
326
|
+
#define OMX_RT_HARD_TARGET_QUANTUM 128
|
|
327
|
+
#define OMX_RT_HARD_TARGET_RATE 192000
|
|
328
|
+
#define OMX_TRANSIENT_FAST_ATTACK_MS 0.5f
|
|
329
|
+
#define OMX_TRANSIENT_FAST_ATTACK_MS_DOUBLE 0.5
|
|
330
|
+
#define OMX_TRANSIENT_FAST_RELEASE_MS 20
|
|
331
|
+
#define OMX_TRANSIENT_FLOOR_LIN 0.00001f
|
|
332
|
+
#define OMX_TRANSIENT_FLOOR_LIN_DOUBLE 0.00001
|
|
333
|
+
#define OMX_TRANSIENT_REF_DB 6
|
|
334
|
+
#define OMX_TREMOLO_DEPTH_RANGE_DEFAULT 50
|
|
335
|
+
#define OMX_TREMOLO_DEPTH_RANGE_MAX 100
|
|
336
|
+
#define OMX_TREMOLO_DEPTH_RANGE_MIN 0
|
|
337
|
+
#define OMX_TREMOLO_DEPTH_RANGE_STEP 0.1f
|
|
338
|
+
#define OMX_TREMOLO_DEPTH_RANGE_STEP_DOUBLE 0.1
|
|
339
|
+
#define OMX_TREMOLO_MIX_RANGE_DEFAULT 100
|
|
340
|
+
#define OMX_TREMOLO_MIX_RANGE_MAX 100
|
|
341
|
+
#define OMX_TREMOLO_MIX_RANGE_MIN 0
|
|
342
|
+
#define OMX_TREMOLO_MIX_RANGE_STEP 0.1f
|
|
343
|
+
#define OMX_TREMOLO_MIX_RANGE_STEP_DOUBLE 0.1
|
|
344
|
+
#define OMX_TREMOLO_RATE_RANGE_DEFAULT 4
|
|
345
|
+
#define OMX_TREMOLO_RATE_RANGE_MAX 20
|
|
346
|
+
#define OMX_TREMOLO_RATE_RANGE_MIN 0.1f
|
|
347
|
+
#define OMX_TREMOLO_RATE_RANGE_MIN_DOUBLE 0.1
|
|
348
|
+
#define OMX_TREMOLO_RATE_RANGE_STEP 0.01f
|
|
349
|
+
#define OMX_TREMOLO_RATE_RANGE_STEP_DOUBLE 0.01
|
|
350
|
+
#define OMX_XOVER_LR2_SECTION_Q 0.5f
|
|
351
|
+
#define OMX_XOVER_LR2_SECTION_Q_DOUBLE 0.5
|
|
352
|
+
#define OMX_XOVER_LR4_SECTION_Q 0.7071067811865476f
|
|
353
|
+
#define OMX_XOVER_LR4_SECTION_Q_DOUBLE 0.7071067811865476
|
|
354
|
+
#define OMX_XOVER_PARTITION_TOLERANCE 0.00001f
|
|
355
|
+
#define OMX_XOVER_PARTITION_TOLERANCE_DOUBLE 0.00001
|
|
356
|
+
|
|
357
|
+
/* Every list rendered to C, sorted by list: OMX_<LIST>_COUNT and OMX_<LIST>_INIT { a, b, … }. */
|
|
358
|
+
#define OMX_PHASER_STAGE_COUNTS_COUNT 6u
|
|
359
|
+
#define OMX_PHASER_STAGE_COUNTS_INIT { 2, 4, 6, 8, 10, 12 }
|
|
360
|
+
#define OMX_STANDARD_SAMPLE_RATES_COUNT 6u
|
|
361
|
+
#define OMX_STANDARD_SAMPLE_RATES_INIT { 44100, 48000, 88200, 96000, 176400, 192000 }
|
|
362
|
+
|
|
363
|
+
#endif /* OMX_CONTRACT_LIMITS_H */
|
|
364
|
+
|
|
365
|
+
/* The sample rates the console declares (core's STANDARD_SAMPLE_RATES, row-codecs.ts): the set a
|
|
366
|
+
* contract's rate-is-declared precondition accepts, through omx_rate_is_declared(), and the grid a
|
|
367
|
+
* native tool iterates. Guarded on its own so a tool built against a pinned copy of this header
|
|
368
|
+
* (lv2-inprocess-pin.sh) can include this tree's copy after it and gain the rates without mixing
|
|
369
|
+
* the pin's limits. */
|
|
370
|
+
#ifndef OMX_DECLARED_RATE_COUNT
|
|
371
|
+
#define OMX_DECLARED_RATE_COUNT 6u
|
|
372
|
+
static const float OMX_DECLARED_RATES[OMX_DECLARED_RATE_COUNT] = { 44100.0f, 48000.0f, 88200.0f, 96000.0f, 176400.0f, 192000.0f };
|
|
373
|
+
/* The declared rates that are whole multiples of `base` (a tool's default grid: the 48 kHz family),
|
|
374
|
+
* in declaration order, at most `cap` of them; returns how many were written to `out`. */
|
|
375
|
+
static inline int omx_declared_rates_multiple_of(unsigned base, int *out, int cap) {
|
|
376
|
+
int n = 0;
|
|
377
|
+
for (unsigned k = 0; k < OMX_DECLARED_RATE_COUNT && n < cap; k++)
|
|
378
|
+
if ((unsigned)OMX_DECLARED_RATES[k] % base == 0) out[n++] = (int)OMX_DECLARED_RATES[k];
|
|
379
|
+
return n;
|
|
380
|
+
}
|
|
381
|
+
#endif
|
package/lib/data.mjs
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
2
|
+
// Copyright (C) 2026 Pau Aliagas <linuxnow@gmail.com>
|
|
3
|
+
/**
|
|
4
|
+
* The declaration as data: load every `data/**.json` file, then resolve each item's references
|
|
5
|
+
* and derivations into plain values. The renderers are pure functions of the resolved items.
|
|
6
|
+
*/
|
|
7
|
+
import { readdirSync, readFileSync, statSync } from 'node:fs';
|
|
8
|
+
import { join, relative } from 'node:path';
|
|
9
|
+
|
|
10
|
+
/** Every `.json` file under `dir`, sorted by its path relative to `dir`. */
|
|
11
|
+
export function dataFiles(dir) {
|
|
12
|
+
const out = [];
|
|
13
|
+
const walk = (d) => {
|
|
14
|
+
for (const f of readdirSync(d).sort()) {
|
|
15
|
+
const p = join(d, f);
|
|
16
|
+
if (statSync(p).isDirectory()) walk(p);
|
|
17
|
+
else if (f.endsWith('.json')) out.push(p);
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
walk(dir);
|
|
21
|
+
return out.sort((a, b) => (relative(dir, a) < relative(dir, b) ? -1 : 1));
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* The raw data: `{ files: [{ path, rel, doc }], items: Map<name, { name, rel, item }> }`, items in
|
|
26
|
+
* file order then key order. `files` may be handed in as `{ rel: text }` (a tag's data, a test).
|
|
27
|
+
* @throws naming the file when one is not JSON, and an item declared by two files.
|
|
28
|
+
*/
|
|
29
|
+
export function loadData(dir, texts) {
|
|
30
|
+
const files = [];
|
|
31
|
+
const entries = texts ? Object.entries(texts).sort(([a], [b]) => (a < b ? -1 : 1)) : dataFiles(dir).map((p) => [relative(join(dir, '..'), p), readFileSync(p, 'utf8')]);
|
|
32
|
+
const items = new Map();
|
|
33
|
+
for (const [rel, text] of entries) {
|
|
34
|
+
let doc;
|
|
35
|
+
try { doc = JSON.parse(text); } catch (e) { throw new Error(`${rel}: not JSON: ${e.message}`); }
|
|
36
|
+
files.push({ rel, text, doc });
|
|
37
|
+
for (const [name, item] of Object.entries(doc)) {
|
|
38
|
+
if (name === '$schema') continue;
|
|
39
|
+
if (items.has(name)) throw new Error(`${rel}: ${name}: already declared by ${items.get(name).rel}`);
|
|
40
|
+
items.set(name, { name, rel, item });
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return { files, items };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** An item's own value before resolution, by kind. */
|
|
47
|
+
export function rawValue(item) {
|
|
48
|
+
switch (item.kind) {
|
|
49
|
+
case 'scalar': return item.value;
|
|
50
|
+
case 'travels': return item.fields ?? item.travel;
|
|
51
|
+
case 'sheet': return item.value;
|
|
52
|
+
case 'list': return item.values;
|
|
53
|
+
default: return undefined;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** The closed list of derivations (spec §3.3). A new one is a change here with its own test. */
|
|
58
|
+
export const DERIVATIONS = {
|
|
59
|
+
count: (d, val) => {
|
|
60
|
+
const v = val(typeof d.of === 'string' ? { ref: d.of } : d.of);
|
|
61
|
+
if (!Array.isArray(v)) throw new Error(`count: ${JSON.stringify(d.of)} is not a list`);
|
|
62
|
+
return v.length;
|
|
63
|
+
},
|
|
64
|
+
sqrt: (d, val) => {
|
|
65
|
+
const v = val(d.of);
|
|
66
|
+
if (typeof v !== 'number' || v < 0) throw new Error(`sqrt: ${JSON.stringify(d.of)} is not a non-negative number`);
|
|
67
|
+
return Math.sqrt(v);
|
|
68
|
+
},
|
|
69
|
+
lagrangeReadL1: (d, val) => {
|
|
70
|
+
const order = val(d.order);
|
|
71
|
+
if (!Number.isInteger(order) || order < 1) throw new Error(`lagrangeReadL1: order ${order} is not a positive integer`);
|
|
72
|
+
return lagrangeReadL1(order);
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
/** The taps of the order-`order` Lagrange fractional read at fraction `f` (the fdelay kernel's read). */
|
|
77
|
+
export function lagrangeReadTaps(order, f) {
|
|
78
|
+
const off = Math.floor((order - 1) / 2);
|
|
79
|
+
const c = [];
|
|
80
|
+
for (let k = 0; k <= order; k++) {
|
|
81
|
+
let num = 1;
|
|
82
|
+
let den = 1;
|
|
83
|
+
for (let j = 0; j <= order; j++) {
|
|
84
|
+
if (j === k) continue;
|
|
85
|
+
num *= f - (j - off);
|
|
86
|
+
den *= k - j;
|
|
87
|
+
}
|
|
88
|
+
c.push(num / den);
|
|
89
|
+
}
|
|
90
|
+
return c;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** The worst L1 norm of the read over 1024 fractions, rounded to 1e-9 (core's readKernelL1Norm). */
|
|
94
|
+
export function lagrangeReadL1(order) {
|
|
95
|
+
const FRACTION_STEPS = 1024;
|
|
96
|
+
let worst = 0;
|
|
97
|
+
for (let i = 0; i < FRACTION_STEPS; i++) {
|
|
98
|
+
const l1 = lagrangeReadTaps(order, i / FRACTION_STEPS).reduce((a, c) => a + Math.abs(c), 0);
|
|
99
|
+
if (l1 > worst) worst = l1;
|
|
100
|
+
}
|
|
101
|
+
return Math.round(worst * 1e9) / 1e9;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const isObj = (v) => typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Resolve every item: `{ name, rel, kind, doc, why?, unit?, c?, shape?, value }`, where `value` has
|
|
108
|
+
* every `{ref}` and `{derive}` evaluated.
|
|
109
|
+
* @throws naming the item: a reference that does not resolve, a cycle, an unknown derivation.
|
|
110
|
+
*/
|
|
111
|
+
export function resolveData(data) {
|
|
112
|
+
const done = new Map();
|
|
113
|
+
const busy = new Set();
|
|
114
|
+
const lookup = (path, from) => {
|
|
115
|
+
const [head, ...rest] = path.split('.');
|
|
116
|
+
const entry = data.items.get(head);
|
|
117
|
+
if (!entry) throw new Error(`${from}: reference ${path}: no item ${head}`);
|
|
118
|
+
let v = resolveItem(head).value;
|
|
119
|
+
for (const k of rest) {
|
|
120
|
+
if (!isObj(v) || !(k in v)) throw new Error(`${from}: reference ${path}: ${head} has no ${k}`);
|
|
121
|
+
v = v[k];
|
|
122
|
+
}
|
|
123
|
+
return v;
|
|
124
|
+
};
|
|
125
|
+
const val = (v, from) => {
|
|
126
|
+
if (Array.isArray(v)) return v.map((x) => val(x, from));
|
|
127
|
+
if (!isObj(v)) return v;
|
|
128
|
+
if ('ref' in v) return lookup(v.ref, from);
|
|
129
|
+
if ('derive' in v) {
|
|
130
|
+
const fn = DERIVATIONS[v.derive];
|
|
131
|
+
if (!fn) throw new Error(`${from}: unknown derivation ${v.derive}`);
|
|
132
|
+
try { return fn(v, (x) => val(x, from)); } catch (e) { throw new Error(`${from}: ${e.message}`); }
|
|
133
|
+
}
|
|
134
|
+
return Object.fromEntries(Object.entries(v).map(([k, x]) => [k, val(x, from)]));
|
|
135
|
+
};
|
|
136
|
+
function resolveItem(name) {
|
|
137
|
+
if (done.has(name)) return done.get(name);
|
|
138
|
+
if (busy.has(name)) throw new Error(`${name}: reference cycle through ${[...busy].join(' -> ')} -> ${name}`);
|
|
139
|
+
busy.add(name);
|
|
140
|
+
const { rel, item } = data.items.get(name);
|
|
141
|
+
const r = { name, rel, kind: item.kind, doc: item.doc };
|
|
142
|
+
if (item.why !== undefined) r.why = item.why;
|
|
143
|
+
if (item.unit !== undefined) r.unit = item.unit;
|
|
144
|
+
if (item.c !== undefined) r.c = item.c;
|
|
145
|
+
if (item.kind === 'travels') r.shape = item.fields ? 'table' : 'travel';
|
|
146
|
+
r.value = val(rawValue(item), name);
|
|
147
|
+
busy.delete(name);
|
|
148
|
+
done.set(name, r);
|
|
149
|
+
return r;
|
|
150
|
+
}
|
|
151
|
+
const out = new Map();
|
|
152
|
+
for (const name of data.items.keys()) out.set(name, resolveItem(name));
|
|
153
|
+
return out;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/** The package version (package.json), which names the tag, the release and the npm version. */
|
|
157
|
+
export function packageVersion(root) {
|
|
158
|
+
return JSON.parse(readFileSync(join(root, 'package.json'), 'utf8')).version;
|
|
159
|
+
}
|
package/lib/fmt.mjs
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
2
|
+
// Copyright (C) 2026 Pau Aliagas <linuxnow@gmail.com>
|
|
3
|
+
/**
|
|
4
|
+
* The one formatting of a data file (spec §3.2): two-space indent, one key per line, keys in schema
|
|
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.
|
|
7
|
+
*/
|
|
8
|
+
|
|
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'],
|
|
12
|
+
c: ['alias', 'render'],
|
|
13
|
+
alias: ['fact', 'field'],
|
|
14
|
+
number: ['ref', 'derive', 'of', 'order'],
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
function ordered(obj, order) {
|
|
18
|
+
const known = order.filter((k) => k in obj);
|
|
19
|
+
const rest = Object.keys(obj).filter((k) => !order.includes(k));
|
|
20
|
+
return Object.fromEntries([...known, ...rest].map((k) => [k, obj[k]]));
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const isObj = (v) => typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
24
|
+
|
|
25
|
+
function number(v) {
|
|
26
|
+
if (!isObj(v)) return v;
|
|
27
|
+
return Object.fromEntries(Object.entries(ordered(v, ORDER.number)).map(([k, x]) => [k, number(x)]));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function sheet(v) {
|
|
31
|
+
if (!isObj(v) || 'ref' in v || 'derive' in v) return number(v);
|
|
32
|
+
return Object.fromEntries(Object.entries(v).map(([k, x]) => [k, sheet(x)]));
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function travel(t) {
|
|
36
|
+
const o = ordered(t, ORDER.travel);
|
|
37
|
+
for (const k of ['min', 'max', 'step', 'default']) if (k in o) o[k] = number(o[k]);
|
|
38
|
+
if (isObj(o.byKind)) o.byKind = Object.fromEntries(Object.entries(o.byKind).map(([k, x]) => [k, number(x)]));
|
|
39
|
+
return o;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function item(it) {
|
|
43
|
+
if (!isObj(it)) return it;
|
|
44
|
+
const o = ordered(it, ORDER.item);
|
|
45
|
+
if ('value' in o) o.value = o.kind === 'sheet' ? sheet(o.value) : number(o.value);
|
|
46
|
+
if (isObj(o.fields)) o.fields = Object.fromEntries(Object.entries(o.fields).map(([k, t]) => [k, isObj(t) ? travel(t) : t]));
|
|
47
|
+
if (isObj(o.travel)) o.travel = travel(o.travel);
|
|
48
|
+
if (isObj(o.c)) {
|
|
49
|
+
o.c = ordered(o.c, ORDER.c);
|
|
50
|
+
if (isObj(o.c.alias)) o.c.alias = ordered(o.c.alias, ORDER.alias);
|
|
51
|
+
}
|
|
52
|
+
return o;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** The canonical text of a parsed data file. */
|
|
56
|
+
export function formatDoc(doc) {
|
|
57
|
+
const out = {};
|
|
58
|
+
if ('$schema' in doc) out.$schema = doc.$schema;
|
|
59
|
+
for (const [k, v] of Object.entries(doc)) if (k !== '$schema') out[k] = item(v);
|
|
60
|
+
return `${JSON.stringify(out, null, 2)}\n`;
|
|
61
|
+
}
|