@effetune/dsp 0.5.0 → 0.7.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.
@@ -10,13 +10,13 @@ export const IR_ASSET_TOPOLOGY = Object.freeze({
10
10
  matrix: 4
11
11
  });
12
12
 
13
- const MAX_CHANNELS = 8;
14
- const MAX_MATRIX_PATHS = 8;
13
+ const MAX_CHANNELS = 16;
14
+ const MAX_MATRIX_PATHS = 16;
15
15
  const MATRIX_PATH_BYTES = 12;
16
16
 
17
17
  function validateChannels(channels) {
18
18
  if (!Array.isArray(channels) || channels.length < 1 || channels.length > MAX_CHANNELS) {
19
- throw new TypeError('IR channels must contain between 1 and 8 Float32Array values');
19
+ throw new TypeError('IR channels must contain between 1 and 16 Float32Array values');
20
20
  }
21
21
  const frames = channels[0] instanceof Float32Array ? channels[0].length : 0;
22
22
  if (frames === 0) throw new TypeError('IR channels must not be empty');
@@ -42,7 +42,7 @@ function validateTopology(topology, paths, channelCount) {
42
42
  return [];
43
43
  }
44
44
  if (!Array.isArray(paths) || paths.length < 1 || paths.length > MAX_MATRIX_PATHS) {
45
- throw new TypeError('Matrix topology requires between 1 and 8 paths');
45
+ throw new TypeError('Matrix topology requires between 1 and 16 paths');
46
46
  }
47
47
  return paths.map(path => {
48
48
  const inputSlot = path?.inputSlot;
@@ -5,7 +5,7 @@ export const IR_KERNEL_ASSET_CAPACITY_BYTES = 32 * 1024 * 1024;
5
5
 
6
6
  const KERNEL_FIXED_FOOTPRINT_BYTES = 2 * 1024 * 1024;
7
7
  const KERNEL_PATH_FRAME_BYTES = 16;
8
- const CONVOLVER_IMPL_BYTES_UPPER_BOUND = 512;
8
+ const CONVOLVER_IMPL_BYTES_UPPER_BOUND = 16 * 1024;
9
9
  const CONVOLVER_STAGE_BYTES_UPPER_BOUND = 512;
10
10
  const PFFFT_SETUP_FIXED_BYTES_UPPER_BOUND = 136;
11
11
  const MATRIX_PATH_BYTES = 12;
@@ -24,18 +24,22 @@ function topologyInputCount(topology, processingChannels, inputCount = 0) {
24
24
  }
25
25
 
26
26
  export function selectedIrChannelCount(channel, engineChannels) {
27
- if (!Number.isInteger(engineChannels) || engineChannels < 1 || engineChannels > 8) return 0;
27
+ if (!Number.isInteger(engineChannels) || engineChannels < 1 || engineChannels > 16) return 0;
28
28
  if (channel === 'A') return engineChannels;
29
29
  if (channel === null || channel === undefined) return engineChannels >= 2 ? 2 : 1;
30
- if (channel === 'L' || channel === 'R' || /^[1-8]$/.test(String(channel))) return 1;
30
+ if (channel === 'L' || channel === 'R' || /^([1-9]|1[0-6])$/.test(String(channel))) return 1;
31
31
  if (channel === '34') return engineChannels >= 4 ? 2 : 0;
32
32
  if (channel === '56') return engineChannels >= 6 ? 2 : 0;
33
33
  if (channel === '78') return engineChannels >= 8 ? 2 : 0;
34
+ if (channel === '910') return engineChannels >= 10 ? 2 : 0;
35
+ if (channel === '1112') return engineChannels >= 12 ? 2 : 0;
36
+ if (channel === '1314') return engineChannels >= 14 ? 2 : 0;
37
+ if (channel === '1516') return engineChannels >= 16 ? 2 : 0;
34
38
  return 0;
35
39
  }
36
40
 
37
41
  function diagonalPaths(channelCount, selectedChannels) {
38
- const count = Math.min(channelCount, selectedChannels, 8);
42
+ const count = Math.min(channelCount, selectedChannels, 16);
39
43
  return Array.from({ length: count }, (_, index) => ({
40
44
  inputSlot: index,
41
45
  outputSlot: index,
@@ -102,7 +106,7 @@ export function estimateIrConvolverMemoryUpperBound({
102
106
  export function resolveIrProcessingConfig({
103
107
  sampleRate,
104
108
  channelCount,
105
- engineChannels = 8,
109
+ engineChannels = 16,
106
110
  selectedChannels,
107
111
  channel,
108
112
  channelMode = 'auto',
@@ -112,7 +116,7 @@ export function resolveIrProcessingConfig({
112
116
  if (!Number.isFinite(sampleRate) || sampleRate <= 0) {
113
117
  return { valid: false, message: 'The current audio sample rate is unavailable.' };
114
118
  }
115
- if (!Number.isInteger(channelCount) || channelCount < 1 || channelCount > 8) {
119
+ if (!Number.isInteger(channelCount) || channelCount < 1 || channelCount > 16) {
116
120
  return { valid: false, message: 'This impulse response has an unsupported channel count.' };
117
121
  }
118
122
  const routedChannels = selectedChannels ?? selectedIrChannelCount(channel, engineChannels);
package/dist/preset.js CHANGED
@@ -58,7 +58,7 @@ function legacyChannel(value) {
58
58
  stereo: 'stereo'
59
59
  };
60
60
  const normalized = mapping[value] ?? value;
61
- if (['1', '2', '3', '4', '5', '6', '7', '8', '34', '56', '78'].includes(normalized)) {
61
+ if (['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '34', '56', '78', '910', '1112', '1314', '1516'].includes(normalized)) {
62
62
  return normalized;
63
63
  }
64
64
  if (['all', 'stereo', 'left', 'right'].includes(normalized)) return normalized;
@@ -309,7 +309,11 @@ function expandLegacyShortKeyArraysV1(parameters, { effectLabel, itemLabel, memb
309
309
  `Legacy ${effectLabel} contains unsupported or incomplete ${itemLabel} settings.`
310
310
  );
311
311
  }
312
- parameters[publicName] = values;
312
+ // App presets retain eight channels when the extended channels are at their defaults.
313
+ const originalCount = legacyName === 'l' ? 7 : 8;
314
+ const defaultValue = legacyName === 'v' || legacyName === 'd' ? 0 : false;
315
+ parameters[publicName] = values.length === originalCount
316
+ ? [...values, ...Array(8).fill(defaultValue)] : values;
313
317
  }
314
318
  }
315
319
 
package/dist/runtime.js CHANGED
@@ -17,8 +17,8 @@ import {
17
17
  const PARAMETER_EVENT_KEYS = new Set(['frame', 'effectId', 'parameters']);
18
18
 
19
19
  function validateAudio(audio) {
20
- if (!Array.isArray(audio) || audio.length < 1 || audio.length > 8) {
21
- throw new ValidationError('Audio must be an array containing between 1 and 8 Float32Array channels.');
20
+ if (!Array.isArray(audio) || audio.length < 1 || audio.length > 16) {
21
+ throw new ValidationError('Audio must be an array containing between 1 and 16 Float32Array channels.');
22
22
  }
23
23
  const frames = audio[0] instanceof Float32Array ? audio[0].length : -1;
24
24
  for (const channel of audio) {
@@ -390,8 +390,8 @@ export class Chain {
390
390
  } = {}) {
391
391
  this._assertOpen();
392
392
  const rate = validateSampleRate(sampleRate);
393
- if (!Number.isInteger(channels) || channels < 1 || channels > 8) {
394
- throw new ValidationError('channels must be an integer from 1 to 8.');
393
+ if (!Number.isInteger(channels) || channels < 1 || channels > 16) {
394
+ throw new ValidationError('channels must be an integer from 1 to 16.');
395
395
  }
396
396
  const frames = validateBlockSize(blockSize);
397
397
  const normalizedSeed = validateSeed(seed);
@@ -434,8 +434,8 @@ export class Chain {
434
434
  } = {}) {
435
435
  this._assertOpen();
436
436
  const rate = validateSampleRate(sampleRate);
437
- if (!Number.isInteger(channels) || channels < 1 || channels > 8) {
438
- throw new ValidationError('channels must be an integer from 1 to 8.');
437
+ if (!Number.isInteger(channels) || channels < 1 || channels > 16) {
438
+ throw new ValidationError('channels must be an integer from 1 to 16.');
439
439
  }
440
440
  const framesPerBlock = validateBlockSize(blockSize);
441
441
  const normalizedSeed = validateSeed(seed);
@@ -116,7 +116,7 @@
116
116
  "channels": {
117
117
  "type": "integer",
118
118
  "minimum": 1,
119
- "maximum": 8
119
+ "maximum": 16
120
120
  },
121
121
  "frames": {
122
122
  "type": "integer",
@@ -142,12 +142,12 @@
142
142
  "pathCount": {
143
143
  "type": "integer",
144
144
  "minimum": 0,
145
- "maximum": 8
145
+ "maximum": 16
146
146
  },
147
147
  "paths": {
148
148
  "type": "array",
149
149
  "minItems": 1,
150
- "maxItems": 8,
150
+ "maxItems": 16,
151
151
  "description": "Matrix routes. Distinct inputSlot values must be exactly 0..N-1, and N must not exceed the selected effect processing-channel count.",
152
152
  "items": {
153
153
  "type": "object",
@@ -161,18 +161,18 @@
161
161
  "inputSlot": {
162
162
  "type": "integer",
163
163
  "minimum": 0,
164
- "maximum": 7,
164
+ "maximum": 15,
165
165
  "description": "Zero-based matrix input; the set of input slots must be contiguous from 0."
166
166
  },
167
167
  "outputSlot": {
168
168
  "type": "integer",
169
169
  "minimum": 0,
170
- "maximum": 7
170
+ "maximum": 15
171
171
  },
172
172
  "irChannel": {
173
173
  "type": "integer",
174
174
  "minimum": 0,
175
- "maximum": 7
175
+ "maximum": 15
176
176
  }
177
177
  }
178
178
  }
@@ -198,7 +198,7 @@
198
198
  "pathCount": {
199
199
  "type": "integer",
200
200
  "minimum": 1,
201
- "maximum": 8
201
+ "maximum": 16
202
202
  }
203
203
  }
204
204
  },
@@ -39,9 +39,21 @@
39
39
  "6",
40
40
  "7",
41
41
  "8",
42
+ "9",
43
+ "10",
44
+ "11",
45
+ "12",
46
+ "13",
47
+ "14",
48
+ "15",
49
+ "16",
42
50
  "34",
43
51
  "56",
44
- "78"
52
+ "78",
53
+ "910",
54
+ "1112",
55
+ "1314",
56
+ "1516"
45
57
  ],
46
58
  "default": "all"
47
59
  },
@@ -158,6 +170,9 @@
158
170
  {
159
171
  "$ref": "#/$defs/GroupDelayEQ"
160
172
  },
173
+ {
174
+ "$ref": "#/$defs/GroupDelayPEQ"
175
+ },
161
176
  {
162
177
  "$ref": "#/$defs/HiPassFilter"
163
178
  },
@@ -209,6 +224,9 @@
209
224
  {
210
225
  "$ref": "#/$defs/HumGenerator"
211
226
  },
227
+ {
228
+ "$ref": "#/$defs/MDSimulator"
229
+ },
212
230
  {
213
231
  "$ref": "#/$defs/MP3CodecSimulator"
214
232
  },
@@ -774,7 +792,7 @@
774
792
  "matrixRoutes": {
775
793
  "type": "string",
776
794
  "maxLength": 3072,
777
- "pattern": "^(?:p?[0-8][0-8])*$",
795
+ "pattern": "^(?:p?[0-9a-f][0-9a-f])*$",
778
796
  "default": "0011"
779
797
  }
780
798
  }
@@ -810,12 +828,20 @@
810
828
  "properties": {
811
829
  "mute": {
812
830
  "type": "array",
813
- "minItems": 8,
814
- "maxItems": 8,
831
+ "minItems": 16,
832
+ "maxItems": 16,
815
833
  "items": {
816
834
  "type": "boolean"
817
835
  },
818
836
  "default": [
837
+ false,
838
+ false,
839
+ false,
840
+ false,
841
+ false,
842
+ false,
843
+ false,
844
+ false,
819
845
  false,
820
846
  false,
821
847
  false,
@@ -828,12 +854,20 @@
828
854
  },
829
855
  "solo": {
830
856
  "type": "array",
831
- "minItems": 8,
832
- "maxItems": 8,
857
+ "minItems": 16,
858
+ "maxItems": 16,
833
859
  "items": {
834
860
  "type": "boolean"
835
861
  },
836
862
  "default": [
863
+ false,
864
+ false,
865
+ false,
866
+ false,
867
+ false,
868
+ false,
869
+ false,
870
+ false,
837
871
  false,
838
872
  false,
839
873
  false,
@@ -846,8 +880,8 @@
846
880
  },
847
881
  "volume": {
848
882
  "type": "array",
849
- "minItems": 8,
850
- "maxItems": 8,
883
+ "minItems": 16,
884
+ "maxItems": 16,
851
885
  "items": {
852
886
  "type": "number",
853
887
  "minimum": -20,
@@ -855,6 +889,14 @@
855
889
  "x-effetune-unit": "dB"
856
890
  },
857
891
  "default": [
892
+ 0,
893
+ 0,
894
+ 0,
895
+ 0,
896
+ 0,
897
+ 0,
898
+ 0,
899
+ 0,
858
900
  0,
859
901
  0,
860
902
  0,
@@ -867,8 +909,8 @@
867
909
  },
868
910
  "delay": {
869
911
  "type": "array",
870
- "minItems": 8,
871
- "maxItems": 8,
912
+ "minItems": 16,
913
+ "maxItems": 16,
872
914
  "items": {
873
915
  "type": "number",
874
916
  "minimum": 0,
@@ -876,6 +918,14 @@
876
918
  "x-effetune-unit": "ms"
877
919
  },
878
920
  "default": [
921
+ 0,
922
+ 0,
923
+ 0,
924
+ 0,
925
+ 0,
926
+ 0,
927
+ 0,
928
+ 0,
879
929
  0,
880
930
  0,
881
931
  0,
@@ -888,12 +938,20 @@
888
938
  },
889
939
  "link": {
890
940
  "type": "array",
891
- "minItems": 7,
892
- "maxItems": 7,
941
+ "minItems": 15,
942
+ "maxItems": 15,
893
943
  "items": {
894
944
  "type": "boolean"
895
945
  },
896
946
  "default": [
947
+ false,
948
+ false,
949
+ false,
950
+ false,
951
+ false,
952
+ false,
953
+ false,
954
+ false,
897
955
  false,
898
956
  false,
899
957
  false,
@@ -3138,6 +3196,67 @@
3138
3196
  }
3139
3197
  }
3140
3198
  },
3199
+ "GroupDelayPEQ": {
3200
+ "type": "object",
3201
+ "additionalProperties": false,
3202
+ "required": [
3203
+ "type",
3204
+ "parameters",
3205
+ "assets"
3206
+ ],
3207
+ "properties": {
3208
+ "id": {
3209
+ "type": "string",
3210
+ "minLength": 1,
3211
+ "maxLength": 128
3212
+ },
3213
+ "type": {
3214
+ "const": "GroupDelayPEQ"
3215
+ },
3216
+ "enabled": {
3217
+ "type": "boolean",
3218
+ "default": true
3219
+ },
3220
+ "channel": {
3221
+ "$ref": "#/$defs/channel"
3222
+ },
3223
+ "parameters": {
3224
+ "type": "object",
3225
+ "additionalProperties": false,
3226
+ "properties": {
3227
+ "latencyMode": {
3228
+ "type": "string",
3229
+ "enum": [
3230
+ "0",
3231
+ "128",
3232
+ "256",
3233
+ "512",
3234
+ "1024"
3235
+ ],
3236
+ "default": "128"
3237
+ },
3238
+ "filterDelaySamples": {
3239
+ "type": "integer",
3240
+ "minimum": 0,
3241
+ "maximum": 65536,
3242
+ "default": 8192
3243
+ }
3244
+ }
3245
+ },
3246
+ "assets": {
3247
+ "type": "object",
3248
+ "additionalProperties": false,
3249
+ "required": [
3250
+ "impulseResponse"
3251
+ ],
3252
+ "properties": {
3253
+ "impulseResponse": {
3254
+ "$ref": "#/$defs/assetReference"
3255
+ }
3256
+ }
3257
+ }
3258
+ }
3259
+ },
3141
3260
  "HiPassFilter": {
3142
3261
  "type": "object",
3143
3262
  "additionalProperties": false,
@@ -4499,6 +4618,60 @@
4499
4618
  }
4500
4619
  }
4501
4620
  },
4621
+ "MDSimulator": {
4622
+ "type": "object",
4623
+ "additionalProperties": false,
4624
+ "required": [
4625
+ "type",
4626
+ "parameters"
4627
+ ],
4628
+ "properties": {
4629
+ "id": {
4630
+ "type": "string",
4631
+ "minLength": 1,
4632
+ "maxLength": 128
4633
+ },
4634
+ "type": {
4635
+ "const": "MDSimulator"
4636
+ },
4637
+ "enabled": {
4638
+ "type": "boolean",
4639
+ "default": true
4640
+ },
4641
+ "channel": {
4642
+ "$ref": "#/$defs/channel"
4643
+ },
4644
+ "parameters": {
4645
+ "type": "object",
4646
+ "additionalProperties": false,
4647
+ "properties": {
4648
+ "mode": {
4649
+ "type": "string",
4650
+ "enum": [
4651
+ "SP (292 kbps)",
4652
+ "LP2 (132 kbps)",
4653
+ "LP4 (66 kbps)"
4654
+ ],
4655
+ "default": "SP (292 kbps)"
4656
+ },
4657
+ "outputGain": {
4658
+ "type": "number",
4659
+ "minimum": -24,
4660
+ "maximum": 12,
4661
+ "x-effetune-unit": "dB",
4662
+ "default": 0
4663
+ },
4664
+ "mix": {
4665
+ "type": "number",
4666
+ "minimum": 0,
4667
+ "maximum": 100,
4668
+ "x-effetune-unit": "%",
4669
+ "default": 100
4670
+ }
4671
+ }
4672
+ }
4673
+ }
4674
+ },
4502
4675
  "MP3CodecSimulator": {
4503
4676
  "type": "object",
4504
4677
  "additionalProperties": false,
@@ -5043,7 +5216,7 @@
5043
5216
  "type": "number",
5044
5217
  "minimum": 0,
5045
5218
  "maximum": 10,
5046
- "default": 0
5219
+ "default": 10
5047
5220
  },
5048
5221
  "wear": {
5049
5222
  "type": "integer",
@@ -6284,7 +6457,7 @@
6284
6457
  "minimum": -36,
6285
6458
  "maximum": 36,
6286
6459
  "x-effetune-unit": "dB",
6287
- "default": 30
6460
+ "default": 26
6288
6461
  }
6289
6462
  }
6290
6463
  }
@@ -6370,7 +6543,7 @@
6370
6543
  "minimum": -36,
6371
6544
  "maximum": 36,
6372
6545
  "x-effetune-unit": "dB",
6373
- "default": 30
6546
+ "default": 26
6374
6547
  }
6375
6548
  }
6376
6549
  }
@@ -8056,6 +8229,93 @@
8056
8229
  100,
8057
8230
  100
8058
8231
  ]
8232
+ },
8233
+ "regionSolo": {
8234
+ "type": "array",
8235
+ "minItems": 5,
8236
+ "maxItems": 5,
8237
+ "items": {
8238
+ "type": "boolean"
8239
+ },
8240
+ "default": [
8241
+ false,
8242
+ false,
8243
+ false,
8244
+ false,
8245
+ false
8246
+ ]
8247
+ },
8248
+ "outerBalanceLow": {
8249
+ "type": "array",
8250
+ "minItems": 5,
8251
+ "maxItems": 5,
8252
+ "items": {
8253
+ "type": "number",
8254
+ "minimum": -100,
8255
+ "maximum": 100,
8256
+ "x-effetune-unit": "%"
8257
+ },
8258
+ "default": [
8259
+ -100,
8260
+ -100,
8261
+ -100,
8262
+ -100,
8263
+ -100
8264
+ ]
8265
+ },
8266
+ "coreBalanceLow": {
8267
+ "type": "array",
8268
+ "minItems": 5,
8269
+ "maxItems": 5,
8270
+ "items": {
8271
+ "type": "number",
8272
+ "minimum": -100,
8273
+ "maximum": 100,
8274
+ "x-effetune-unit": "%"
8275
+ },
8276
+ "default": [
8277
+ -100,
8278
+ -100,
8279
+ -100,
8280
+ -100,
8281
+ -100
8282
+ ]
8283
+ },
8284
+ "coreBalanceHigh": {
8285
+ "type": "array",
8286
+ "minItems": 5,
8287
+ "maxItems": 5,
8288
+ "items": {
8289
+ "type": "number",
8290
+ "minimum": -100,
8291
+ "maximum": 100,
8292
+ "x-effetune-unit": "%"
8293
+ },
8294
+ "default": [
8295
+ 100,
8296
+ 100,
8297
+ 100,
8298
+ 100,
8299
+ 100
8300
+ ]
8301
+ },
8302
+ "outerBalanceHigh": {
8303
+ "type": "array",
8304
+ "minItems": 5,
8305
+ "maxItems": 5,
8306
+ "items": {
8307
+ "type": "number",
8308
+ "minimum": -100,
8309
+ "maximum": 100,
8310
+ "x-effetune-unit": "%"
8311
+ },
8312
+ "default": [
8313
+ 100,
8314
+ 100,
8315
+ 100,
8316
+ 100,
8317
+ 100
8318
+ ]
8059
8319
  }
8060
8320
  }
8061
8321
  }