@effetune/dsp 0.4.0 → 0.6.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 CHANGED
@@ -3,8 +3,8 @@
3
3
  <!-- BEGIN DSP-LIBRARY-JAVASCRIPT-SUMMARY -->
4
4
  EffeTune DSP provides the same MIT-licensed C++ audio kernels used by EffeTune
5
5
  as a self-contained WebAssembly package for Node.js and evergreen browsers.
6
- Version 0.4.0 exposes all 83 catalog types through the generic Chain and
7
- `createEffect` APIs and 83 generated named convenience classes,
6
+ Version 0.6.0 exposes all 92 catalog types through the generic Chain and
7
+ `createEffect` APIs and 92 generated named convenience classes,
8
8
  decoded analyzer telemetry, versioned semantic presets, deterministic seeds, and an AudioWorklet wrapper.
9
9
  <!-- END DSP-LIBRARY-JAVASCRIPT-SUMMARY -->
10
10
 
@@ -39,6 +39,44 @@ const output = await chain.process(input, { sampleRate: 48000 });
39
39
  console.log(output.length, output[0].length, output[0][0]);
40
40
  chain.close();
41
41
  ```
42
+
43
+ ### Graph v1 quickstart
44
+
45
+ Graph v1 is opt-in routing for branching and merging:
46
+
47
+ ```js
48
+ import { Graph, createGraph, createVolume } from '@effetune/dsp';
49
+
50
+ const input = [
51
+ new Float32Array(128).fill(0.25),
52
+ new Float32Array(128).fill(0.25)
53
+ ];
54
+ const graphDocument = Graph.wetDry(
55
+ createVolume({ id: 'wet', volume: -6 }),
56
+ { dry: 0.5, wet: 0.5 }
57
+ );
58
+ const graph = await createGraph(graphDocument);
59
+ let stream;
60
+
61
+ try {
62
+ const offline = await graph.process(input, { sampleRate: 48000 });
63
+ stream = await graph.stream({
64
+ sampleRate: 48000,
65
+ channels: 2,
66
+ blockSize: 128
67
+ });
68
+ const continuous = await stream.process(input);
69
+ console.log(
70
+ offline[0][0],
71
+ continuous[0][0],
72
+ stream.latencySamples,
73
+ stream.compileSnapshot.effectiveSchedule
74
+ );
75
+ } finally {
76
+ stream?.close();
77
+ graph.close();
78
+ }
79
+ ```
42
80
  <!-- END DSP-LIBRARY-JAVASCRIPT-START -->
43
81
 
44
82
  The package is ESM-only. Save the example as `start.mjs` and run
@@ -51,10 +89,14 @@ Public package entry points are:
51
89
  - `@effetune/dsp/worklet` for `EffeTuneNode`
52
90
  - `@effetune/dsp/processor` for the side-effect AudioWorklet processor
53
91
  - `@effetune/dsp/schemas/chain-v1.json` for the Chain v1 JSON Schema
92
+ - `@effetune/dsp/schemas/graph-v1.json` for the Graph v1 JSON Schema
54
93
  - `@effetune/dsp/schemas/bundle-v1.json` for the Bundle v1 JSON Schema
55
94
  - `@effetune/dsp/catalog` for ESM catalog exports
56
95
  - `@effetune/dsp/catalog.json` for the machine-readable catalog JSON
57
96
 
97
+ Graph v1 is opt-in. Its current capacities and delay-storage accounting are
98
+ published in the [Graph v1 guide](https://effetune.frieve.com/dsp/reference/graph-v1/#capacity).
99
+
58
100
  Every offline `process()` call starts from fresh DSP state and returns newly
59
101
  owned `Float32Array` channels. Input arrays are never mutated. Effects run in
60
102
  array order; a disabled effect and an empty chain are identity operations.
@@ -97,8 +139,9 @@ seed, and DSP state from stream creation.
97
139
  assets to be staged again. Open a new stream after changing
98
140
  `IRReverb.channelMode`, `latency`, or `convolutionRate`;
99
141
  `FIRCrossover.bandCount`, `latencyMode`, or `filterDelaySamples`; or
100
- `latencyMode` / `filterDelaySamples` on `FiveBandFIRPEQ`, `GroupDelayEQ`, or
101
- `RoomEQ`. The same restriction applies to `EffeTuneNode.setParam()`.
142
+ `latencyMode` / `filterDelaySamples` on `FiveBandFIRPEQ`, `GroupDelayEQ`,
143
+ `GroupDelayPEQ`, or `RoomEQ`. The same restriction applies to
144
+ `EffeTuneNode.setParam()`.
102
145
 
103
146
  Canonical presets use semantic long parameter names:
104
147
 
@@ -125,24 +168,83 @@ Move or copy the desired effects into one serial path in the app and export it
125
168
  again, or reproduce the branching in the host around separate Chains.
126
169
  Unsupported fields produce a validation error.
127
170
 
128
- FIR Crossover, Five Band FIR PEQ, Group Delay EQ, IR Reverb, and Room EQ
129
- require an `assets.impulseResponse` reference and an `assetResolver`. The four
130
- FIR filter effects use prepared coefficient impulses at the processing sample
131
- rate. Use the public `encodeEta1({ channels, sampleRate, topology, paths })`
171
+ FIR Crossover, Five Band FIR PEQ, Group Delay EQ, Group Delay PEQ, IR Reverb,
172
+ and Room EQ require an `assets.impulseResponse` reference and an
173
+ `assetResolver`. The five FIR filter effects use prepared coefficient impulses
174
+ at the processing sample rate. Use the public
175
+ `encodeEta1({ channels, sampleRate, topology, paths })`
132
176
  helper to encode raw planar float32 arrays for a resolver. Bundle manifests
133
177
  verify exact byte length and SHA-256 before accepting an ETA1 payload. The
134
178
  complete payload and convolution footprint must fit the 32 MiB kernel cap.
135
179
 
136
180
  `EFFECT_CATALOG` and `getEffectCatalog()` expose the machine-readable semantic
137
- catalog for all 83 root classes and their `create<Type>()` factories. The
181
+ catalog for all 92 root classes and their `create<Type>()` factories. The
138
182
  catalog contains channel choices, parameters, required assets, telemetry, and
139
183
  latency declarations, but no private implementation mapping.
140
184
 
185
+ ### Modulation Style recipes
186
+
187
+ The application-only **Style** selector is not a DSP parameter or a second
188
+ preset API. The following JSON-compatible objects are the equivalent public
189
+ parameter dictionaries. Copy one into a named constructor, for example
190
+ `new Chorus(MODULATION_STYLES.Chorus.Flanger)`, or into a Chain effect's
191
+ `parameters` object.
192
+
193
+ ```js
194
+ const MODULATION_STYLES = {
195
+ AutoFilter: {
196
+ "Auto Filter Sweep": { mode: "LFO", filterType: "Low-pass", minimumFrequency: 200, maximumFrequency: 4000, resonance: 1.5, mix: 80, rate: 0.5, waveform: "Sine", stereoPhase: 0, sensitivity: 24, attack: 20, release: 250, direction: "Up" },
197
+ "Stereo Filter Sweep": { mode: "LFO", filterType: "Low-pass", minimumFrequency: 160, maximumFrequency: 6000, resonance: 2, mix: 85, rate: 0.35, waveform: "Sine", stereoPhase: 120, sensitivity: 24, attack: 20, release: 250, direction: "Up" },
198
+ "Envelope Filter": { mode: "Envelope", filterType: "Low-pass", minimumFrequency: 100, maximumFrequency: 5000, resonance: 1.2, mix: 85, rate: 0.5, waveform: "Sine", stereoPhase: 0, sensitivity: 24, attack: 18, release: 300, direction: "Up" },
199
+ "Auto Wah": { mode: "Envelope", filterType: "Band-pass", minimumFrequency: 180, maximumFrequency: 2400, resonance: 5, mix: 100, rate: 0.5, waveform: "Sine", stereoPhase: 0, sensitivity: 30, attack: 8, release: 180, direction: "Up" },
200
+ "Reverse Auto Wah": { mode: "Envelope", filterType: "Band-pass", minimumFrequency: 180, maximumFrequency: 2800, resonance: 4, mix: 100, rate: 0.5, waveform: "Sine", stereoPhase: 0, sensitivity: 30, attack: 12, release: 350, direction: "Down" }
201
+ },
202
+ AutoPan: {
203
+ "Gentle Auto Pan": { rate: 0.35, depth: 45, center: 0, width: 70, waveform: "Sine", phase: 0 },
204
+ "Wide Auto Pan": { rate: 0.7, depth: 100, center: 0, width: 100, waveform: "Sine", phase: 0 },
205
+ "Fast Auto Pan": { rate: 4, depth: 85, center: 0, width: 100, waveform: "Triangle", phase: 0 }
206
+ },
207
+ Chorus: {
208
+ "Classic Chorus": { mode: "Chorus", rate: 0.8, delay: 12, depth: 3, voices: 3, stereoSpread: 60, feedback: 0, mix: 45 },
209
+ "Stereo Chorus": { mode: "Stereo Chorus", rate: 0.65, delay: 15, depth: 4, voices: 2, stereoSpread: 80, feedback: 0, mix: 50 },
210
+ Ensemble: { mode: "Ensemble", rate: 0.45, delay: 20, depth: 6, voices: 6, stereoSpread: 100, feedback: 0, mix: 60 },
211
+ Flanger: { mode: "Flanger", rate: 0.35, delay: 2.5, depth: 2, voices: 1, stereoSpread: 35, feedback: 45, mix: 50 },
212
+ "Jet Flanger": { mode: "Flanger", rate: 0.18, delay: 1.5, depth: 1.4, voices: 1, stereoSpread: 70, feedback: -75, mix: 55 },
213
+ Vibrato: { mode: "Vibrato", rate: 4.5, delay: 8, depth: 5, voices: 1, stereoSpread: 50, feedback: 0, mix: 100 }
214
+ },
215
+ FrequencyShifter: {
216
+ "Shift Up": { mode: "Shift", shift: 8, carrierFrequency: 440, minimumShift: 20, maximumShift: 800, rate: 0.15, direction: "Up", stereoPhase: 0, mix: 100 },
217
+ "Shift Down": { mode: "Shift", shift: -8, carrierFrequency: 440, minimumShift: 20, maximumShift: 800, rate: 0.15, direction: "Down", stereoPhase: 0, mix: 100 },
218
+ "Fine Detune": { mode: "Shift", shift: 2, carrierFrequency: 440, minimumShift: 20, maximumShift: 800, rate: 0.15, direction: "Up", stereoPhase: 90, mix: 55 },
219
+ "Ring Modulator": { mode: "Ring Mod", shift: 8, carrierFrequency: 440, minimumShift: 20, maximumShift: 800, rate: 0.15, direction: "Up", stereoPhase: 0, mix: 100 },
220
+ "Barber-pole Up": { mode: "Barber-pole", shift: 8, carrierFrequency: 440, minimumShift: 20, maximumShift: 900, rate: 0.12, direction: "Up", stereoPhase: 90, mix: 85 },
221
+ "Barber-pole Down": { mode: "Barber-pole", shift: -8, carrierFrequency: 440, minimumShift: 20, maximumShift: 900, rate: 0.12, direction: "Down", stereoPhase: 90, mix: 85 }
222
+ },
223
+ Phaser: {
224
+ "Classic Phaser": { mode: "Classic", rate: 0.5, centerFrequency: 1000, range: 3, stages: 6, feedback: 20, stereoPhase: 90, direction: "Up", mix: 50 },
225
+ "Deep Phaser": { mode: "Classic", rate: 0.25, centerFrequency: 700, range: 4.5, stages: 12, feedback: 55, stereoPhase: 30, direction: "Up", mix: 55 },
226
+ "Stereo Phaser": { mode: "Classic", rate: 0.65, centerFrequency: 1200, range: 3.5, stages: 8, feedback: 25, stereoPhase: 120, direction: "Up", mix: 50 },
227
+ "Barber-pole Up": { mode: "Barber-pole", rate: 0.35, centerFrequency: 1000, range: 5, stages: 8, feedback: 30, stereoPhase: 60, direction: "Up", mix: 55 },
228
+ "Barber-pole Down": { mode: "Barber-pole", rate: 0.35, centerFrequency: 1000, range: 5, stages: 8, feedback: 30, stereoPhase: 60, direction: "Down", mix: 55 }
229
+ },
230
+ RotarySpeaker: {
231
+ "Rotary Slow": { speedState: "Slow", speed: 100, acceleration: 2.2, crossover: 800, rotorBalance: 0, stereoWidth: 75, dopplerDepth: 45, amplitudeDepth: 55, mix: 70 },
232
+ "Rotary Fast": { speedState: "Fast", speed: 100, acceleration: 1.4, crossover: 800, rotorBalance: 0, stereoWidth: 85, dopplerDepth: 65, amplitudeDepth: 70, mix: 78 },
233
+ "Gentle Rotary": { speedState: "Slow", speed: 75, acceleration: 3, crossover: 900, rotorBalance: 0, stereoWidth: 45, dopplerDepth: 25, amplitudeDepth: 30, mix: 55 },
234
+ "Leslie Slow": { speedState: "Slow", speed: 100, acceleration: 2.8, crossover: 800, rotorBalance: -5, stereoWidth: 80, dopplerDepth: 50, amplitudeDepth: 60, mix: 75 },
235
+ "Leslie Fast": { speedState: "Fast", speed: 100, acceleration: 1.8, crossover: 800, rotorBalance: -5, stereoWidth: 90, dopplerDepth: 70, amplitudeDepth: 75, mix: 82 }
236
+ }
237
+ };
238
+ ```
239
+
141
240
  For stateful processing, `ChainStream.latencySamples` reports aggregate runtime
142
241
  latency and matches Python `Stream.latency_samples` for the same chain and
143
242
  sample rate. `chain.latencySamples({ sampleRate })` reports the same value
144
- without opening a stream, which aligns offline `process()` output.
145
- `EffeTuneNode` does not expose a latency getter.
243
+ without opening a stream. `EffeTuneNode.latencySamples` exposes the cached
244
+ aggregate for real-time processing; initialization and awaited `setParam()` or
245
+ `reset()` calls update it before returning. These APIs report latency without
246
+ trimming or padding offline output, so the host decides how to place rendered
247
+ audio.
146
248
 
147
249
  For real-time processing:
148
250
 
@@ -156,6 +258,7 @@ const node = await EffeTuneNode.create(context, preset, {
156
258
  });
157
259
  source.connect(node).connect(context.destination);
158
260
  await node.setParam('voice', 'threshold', -20);
261
+ console.log(node.latencySamples);
159
262
  await node.reset();
160
263
  node.close();
161
264
  ```
@@ -1,16 +1,16 @@
1
1
  {
2
2
  "abiVersion": 1,
3
- "sourceDigest": "sha256:1e46f26d7a51f22747ce105a425cf83be4c71ed3f9b1342275cdff2bed6e0590",
3
+ "sourceDigest": "sha256:c00f5411a8fe68c2139dd6a5903e1f480229387a9e7057bd6e246fc2676cddec",
4
4
  "emsdkVersion": "6.0.2",
5
5
  "g726PerformanceInput": {
6
6
  "contract": "g726-production-performance-input-sha256-v2",
7
7
  "hashAlgorithm": "SHA-256 over the contract and ordered UTF-8 components as id\\0content\\0; CRLF and CR normalize to LF",
8
- "digest": "sha256:2a3c283e9f45f68d561b2d651a8c73d78cab2a8f8cbc74f6f99ebcc64e408598",
8
+ "digest": "sha256:0dab4b4c5ba1de2a9998e5f2e8bee1b3d31b654b1029fa1be0c677ef6aa295d1",
9
9
  "inputs": [
10
10
  {
11
11
  "id": "dsp/core/abi.cpp",
12
12
  "kind": "file",
13
- "sha256": "sha256:97e277947544bcb21015c9fe289af338fbe6f46b97dda233d24b594704bd2059"
13
+ "sha256": "sha256:ae52245f49287e6bf3345ba0860e65c7eb9d49fe61fabb0a3fb3459bb9eb6676"
14
14
  },
15
15
  {
16
16
  "id": "dsp/core/allocation_guard.cpp",
@@ -35,17 +35,17 @@
35
35
  {
36
36
  "id": "dsp/core/engine.cpp",
37
37
  "kind": "file",
38
- "sha256": "sha256:49b8be2b35956dbd34c0cb46a48da64132b8b2b4395437ab3381755936fb4741"
38
+ "sha256": "sha256:2d492ff232ddc0d6b64843dba7a08d3f2834c9bb4b0ee923d9a93e2b71c29ec2"
39
39
  },
40
40
  {
41
41
  "id": "dsp/core/engine.h",
42
42
  "kind": "file",
43
- "sha256": "sha256:5959f7d0bca55fb80c580d16cf7f22859db87b3d20a46f589d96f7682f80fd49"
43
+ "sha256": "sha256:373b70d2e7f6925a79c13e067719b40b36539567d26bf6f3d8df575641e47239"
44
44
  },
45
45
  {
46
46
  "id": "dsp/core/registry.cpp",
47
47
  "kind": "file",
48
- "sha256": "sha256:64c18288f9be512826a01e93c387c9b0105fa716cdd36db5c01e9e9a757132b8"
48
+ "sha256": "sha256:1ca815678d0ecc13ee7dfd35f8c0af6b2ea1d4ff1e7100177349057b7ebbdcab"
49
49
  },
50
50
  {
51
51
  "id": "dsp/core/registry.h",
@@ -55,7 +55,7 @@
55
55
  {
56
56
  "id": "dsp/core/telemetry.cpp",
57
57
  "kind": "file",
58
- "sha256": "sha256:515405f783c4b410567e6b44ec66abd68d1872361840e713518c4bf7425bca42"
58
+ "sha256": "sha256:a78cfe83117c9ea3714f0fe83e320e377165331c56627283f2193c78012514da"
59
59
  },
60
60
  {
61
61
  "id": "dsp/EMSDK_VERSION",
@@ -65,7 +65,7 @@
65
65
  {
66
66
  "id": "dsp/exports.txt",
67
67
  "kind": "file",
68
- "sha256": "sha256:a80c7af5a36d703cae78efc96e7458d238cbff7a9ac86ffaecdb2e6d19d18735"
68
+ "sha256": "sha256:d9fafe26c1f1d23eaa4f38fa61073f992f34a0649e85eac39df9bd1dc8215342"
69
69
  },
70
70
  {
71
71
  "id": "dsp/generated/cpp/G726ADPCMSimulatorPluginParams.h",
@@ -75,7 +75,7 @@
75
75
  {
76
76
  "id": "dsp/include/effetune/abi.h",
77
77
  "kind": "file",
78
- "sha256": "sha256:2e13c9f28ba46ec8a0397a003d360923ccb3367639918e0d24d02ed4f6726894"
78
+ "sha256": "sha256:18dcdc3fdd2af9de4b7acb27dacb3441b01a441e9447af1908efb69437b3909a"
79
79
  },
80
80
  {
81
81
  "id": "dsp/include/effetune/dsp/halfband.h",
@@ -115,7 +115,7 @@
115
115
  {
116
116
  "id": "dsp/plugins/lofi/g726_adpcm_simulator/params.json",
117
117
  "kind": "file",
118
- "sha256": "sha256:a096e3cb9174c7650a7d024f3dc2c28506f8e1b98b879329cd8a9f5dc3d685ee"
118
+ "sha256": "sha256:d7ecbfdc5d087b12319c3501e685021b148cd0e21e4f87b36463cbffbabbc879"
119
119
  },
120
120
  {
121
121
  "id": "dsp/registry.inc#G726ADPCMSimulatorPlugin-entry",
@@ -130,17 +130,17 @@
130
130
  {
131
131
  "id": "js/audio/dsp-engine-binding.js",
132
132
  "kind": "file",
133
- "sha256": "sha256:5186b3cd1a1d6897f644bfded4ad2f5542e09addf913e98f85b14a95825240e0"
133
+ "sha256": "sha256:4c0efb5c75ee0c051ba2fc0804f908d61363d077fec95f86f5b390a8eb031cc9"
134
134
  },
135
135
  {
136
136
  "id": "production-build#g726-resolved-authority",
137
137
  "kind": "derived",
138
- "sha256": "sha256:083288185aaf9068f11cca8ffef3eefc2a68f8d9aab59f4a43bc2d141e2218be"
138
+ "sha256": "sha256:872376fbba212753fe6283376ec83125c55906cf51b746cebae39882acc2490d"
139
139
  },
140
140
  {
141
141
  "id": "production-build#g726-source-authority",
142
142
  "kind": "derived",
143
- "sha256": "sha256:957f4ed2f398b92b5d6dce22cfabd431b8445dd0b66e3d0312c063c16e09447e"
143
+ "sha256": "sha256:2f0ae13c16cc15cd2953365a24f94d90cbe00ce65a525368a67a6855459affed"
144
144
  },
145
145
  {
146
146
  "id": "tools/dsp-parity/cases.mjs",
@@ -160,7 +160,7 @@
160
160
  {
161
161
  "id": "tools/dsp-parity/runners.mjs",
162
162
  "kind": "file",
163
- "sha256": "sha256:83be9da46b7fdb60a469c853eb501d1a3a7eca7872b143a0d3e972a633229260"
163
+ "sha256": "sha256:fe1da8063d168c1b9f142a6217a097230bbf8783bd1d8f4bcb8ac807d78d862f"
164
164
  },
165
165
  {
166
166
  "id": "tools/dsp-parity/stimuli.mjs",
@@ -180,7 +180,7 @@
180
180
  "target_compile_options(pffft PRIVATE -msimd128)",
181
181
  "set_target_properties(pffft PROPERTIES POSITION_INDEPENDENT_CODE ON)",
182
182
  "target_link_libraries(pffft PUBLIC m)",
183
- "target_include_directories( effetune_dsp_core PUBLIC include PRIVATE core generated/cpp)",
183
+ "target_include_directories( effetune_dsp_core PUBLIC include bindings/generated PRIVATE core generated/cpp)",
184
184
  "target_link_libraries(effetune_dsp_core PUBLIC pffft)",
185
185
  "target_compile_definitions( effetune_dsp_core PRIVATE $<$<BOOL:${ET_SIMD}>:ET_SIMD=1> $<$<BOOL:${ET_DEBUG_STATE}>:ET_DEBUG_STATE=1> $<$<CONFIG:Debug>:ET_DEBUG_BUILD=1> $<$<CONFIG:Debug>:ET_ALLOCATION_GUARD=1> $<$<AND:$<CONFIG:Debug>,$<NOT:$<CXX_COMPILER_ID:MSVC>>>:ET_WRAP_MALLOC=1> $<$<BOOL:${BUILD_TESTING}>:ET_ENABLE_TEST_KERNEL=1>)",
186
186
  "target_link_options( effetune_dsp_core INTERFACE $<$<AND:$<CONFIG:Debug>,$<NOT:$<CXX_COMPILER_ID:MSVC>>>:-Wl,--wrap=malloc>)",
@@ -222,7 +222,7 @@
222
222
  "-DBUILD_TESTING=OFF"
223
223
  ]
224
224
  },
225
- "digest": "sha256:9f661f9436b7a66184aec1c77806dbfa36d5fe8ed156e4911a771fae4a0d95da"
225
+ "digest": "sha256:c2ea8f18f42afd6375341c9df08f4f21ef57a44875f540126eef084101ddef99"
226
226
  },
227
227
  "resolved": {
228
228
  "source": "configured CMake Ninja compile/link edges",
@@ -255,49 +255,49 @@
255
255
  "source": "dsp/core/abi.cpp",
256
256
  "definitions": "-DET_ENABLE_LIFECYCLE_EXCEPTION_BOUNDARY=1 -DPFFFT_STATIC_DEFINE=1",
257
257
  "flags": "-O3 -DNDEBUG -std=c++20 -Wall -Wextra -Wpedantic -Werror -fwasm-exceptions -fno-rtti -O3 -flto",
258
- "includes": "-I<repo>/dsp/include -I<repo>/dsp/core -I<repo>/dsp/generated/cpp -I<repo>/dsp/vendor/pffft/include/pffft"
258
+ "includes": "-I<repo>/dsp/include -I<repo>/dsp/bindings/generated -I<repo>/dsp/core -I<repo>/dsp/generated/cpp -I<repo>/dsp/vendor/pffft/include/pffft"
259
259
  },
260
260
  {
261
261
  "source": "dsp/core/allocation_guard.cpp",
262
262
  "definitions": "-DET_ENABLE_LIFECYCLE_EXCEPTION_BOUNDARY=1 -DPFFFT_STATIC_DEFINE=1",
263
263
  "flags": "-O3 -DNDEBUG -std=c++20 -Wall -Wextra -Wpedantic -Werror -fwasm-exceptions -fno-rtti -O3 -flto",
264
- "includes": "-I<repo>/dsp/include -I<repo>/dsp/core -I<repo>/dsp/generated/cpp -I<repo>/dsp/vendor/pffft/include/pffft"
264
+ "includes": "-I<repo>/dsp/include -I<repo>/dsp/bindings/generated -I<repo>/dsp/core -I<repo>/dsp/generated/cpp -I<repo>/dsp/vendor/pffft/include/pffft"
265
265
  },
266
266
  {
267
267
  "source": "dsp/core/arena.cpp",
268
268
  "definitions": "-DET_ENABLE_LIFECYCLE_EXCEPTION_BOUNDARY=1 -DPFFFT_STATIC_DEFINE=1",
269
269
  "flags": "-O3 -DNDEBUG -std=c++20 -Wall -Wextra -Wpedantic -Werror -fwasm-exceptions -fno-rtti -O3 -flto",
270
- "includes": "-I<repo>/dsp/include -I<repo>/dsp/core -I<repo>/dsp/generated/cpp -I<repo>/dsp/vendor/pffft/include/pffft"
270
+ "includes": "-I<repo>/dsp/include -I<repo>/dsp/bindings/generated -I<repo>/dsp/core -I<repo>/dsp/generated/cpp -I<repo>/dsp/vendor/pffft/include/pffft"
271
271
  },
272
272
  {
273
273
  "source": "dsp/core/engine.cpp",
274
274
  "definitions": "-DET_ENABLE_LIFECYCLE_EXCEPTION_BOUNDARY=1 -DPFFFT_STATIC_DEFINE=1",
275
275
  "flags": "-O3 -DNDEBUG -std=c++20 -Wall -Wextra -Wpedantic -Werror -fwasm-exceptions -fno-rtti -O3 -flto",
276
- "includes": "-I<repo>/dsp/include -I<repo>/dsp/core -I<repo>/dsp/generated/cpp -I<repo>/dsp/vendor/pffft/include/pffft"
276
+ "includes": "-I<repo>/dsp/include -I<repo>/dsp/bindings/generated -I<repo>/dsp/core -I<repo>/dsp/generated/cpp -I<repo>/dsp/vendor/pffft/include/pffft"
277
277
  },
278
278
  {
279
279
  "source": "dsp/core/registry.cpp",
280
280
  "definitions": "-DET_ENABLE_LIFECYCLE_EXCEPTION_BOUNDARY=1 -DPFFFT_STATIC_DEFINE=1",
281
281
  "flags": "-O3 -DNDEBUG -std=c++20 -Wall -Wextra -Wpedantic -Werror -fwasm-exceptions -fno-rtti -O3 -flto",
282
- "includes": "-I<repo>/dsp/include -I<repo>/dsp/core -I<repo>/dsp/generated/cpp -I<repo>/dsp/vendor/pffft/include/pffft"
282
+ "includes": "-I<repo>/dsp/include -I<repo>/dsp/bindings/generated -I<repo>/dsp/core -I<repo>/dsp/generated/cpp -I<repo>/dsp/vendor/pffft/include/pffft"
283
283
  },
284
284
  {
285
285
  "source": "dsp/core/telemetry.cpp",
286
286
  "definitions": "-DET_ENABLE_LIFECYCLE_EXCEPTION_BOUNDARY=1 -DPFFFT_STATIC_DEFINE=1",
287
287
  "flags": "-O3 -DNDEBUG -std=c++20 -Wall -Wextra -Wpedantic -Werror -fwasm-exceptions -fno-rtti -O3 -flto",
288
- "includes": "-I<repo>/dsp/include -I<repo>/dsp/core -I<repo>/dsp/generated/cpp -I<repo>/dsp/vendor/pffft/include/pffft"
288
+ "includes": "-I<repo>/dsp/include -I<repo>/dsp/bindings/generated -I<repo>/dsp/core -I<repo>/dsp/generated/cpp -I<repo>/dsp/vendor/pffft/include/pffft"
289
289
  },
290
290
  {
291
291
  "source": "dsp/plugins/lofi/g726_adpcm_simulator/kernel.cpp",
292
292
  "definitions": "-DET_ENABLE_LIFECYCLE_EXCEPTION_BOUNDARY=1 -DPFFFT_STATIC_DEFINE=1",
293
293
  "flags": "-O3 -DNDEBUG -std=c++20 -Wall -Wextra -Wpedantic -Werror -fwasm-exceptions -fno-rtti -O3 -flto",
294
- "includes": "-I<repo>/dsp/include -I<repo>/dsp/core -I<repo>/dsp/generated/cpp -I<repo>/dsp/vendor/pffft/include/pffft"
294
+ "includes": "-I<repo>/dsp/include -I<repo>/dsp/bindings/generated -I<repo>/dsp/core -I<repo>/dsp/generated/cpp -I<repo>/dsp/vendor/pffft/include/pffft"
295
295
  },
296
296
  {
297
297
  "source": "dsp/wasm/no_entry.cpp",
298
298
  "definitions": "-DPFFFT_STATIC_DEFINE=1",
299
299
  "flags": "-O3 -DNDEBUG -std=c++20",
300
- "includes": "-I<repo>/dsp/include -I<repo>/dsp/vendor/pffft/include/pffft"
300
+ "includes": "-I<repo>/dsp/include -I<repo>/dsp/bindings/generated -I<repo>/dsp/vendor/pffft/include/pffft"
301
301
  }
302
302
  ],
303
303
  "linkCommand": {
@@ -334,49 +334,49 @@
334
334
  "source": "dsp/core/abi.cpp",
335
335
  "definitions": "-DET_ENABLE_LIFECYCLE_EXCEPTION_BOUNDARY=1 -DET_SIMD=1 -DPFFFT_STATIC_DEFINE=1",
336
336
  "flags": "-O3 -DNDEBUG -std=c++20 -Wall -Wextra -Wpedantic -Werror -fwasm-exceptions -fno-rtti -O3 -flto -msimd128",
337
- "includes": "-I<repo>/dsp/include -I<repo>/dsp/core -I<repo>/dsp/generated/cpp -I<repo>/dsp/vendor/pffft/include/pffft"
337
+ "includes": "-I<repo>/dsp/include -I<repo>/dsp/bindings/generated -I<repo>/dsp/core -I<repo>/dsp/generated/cpp -I<repo>/dsp/vendor/pffft/include/pffft"
338
338
  },
339
339
  {
340
340
  "source": "dsp/core/allocation_guard.cpp",
341
341
  "definitions": "-DET_ENABLE_LIFECYCLE_EXCEPTION_BOUNDARY=1 -DET_SIMD=1 -DPFFFT_STATIC_DEFINE=1",
342
342
  "flags": "-O3 -DNDEBUG -std=c++20 -Wall -Wextra -Wpedantic -Werror -fwasm-exceptions -fno-rtti -O3 -flto -msimd128",
343
- "includes": "-I<repo>/dsp/include -I<repo>/dsp/core -I<repo>/dsp/generated/cpp -I<repo>/dsp/vendor/pffft/include/pffft"
343
+ "includes": "-I<repo>/dsp/include -I<repo>/dsp/bindings/generated -I<repo>/dsp/core -I<repo>/dsp/generated/cpp -I<repo>/dsp/vendor/pffft/include/pffft"
344
344
  },
345
345
  {
346
346
  "source": "dsp/core/arena.cpp",
347
347
  "definitions": "-DET_ENABLE_LIFECYCLE_EXCEPTION_BOUNDARY=1 -DET_SIMD=1 -DPFFFT_STATIC_DEFINE=1",
348
348
  "flags": "-O3 -DNDEBUG -std=c++20 -Wall -Wextra -Wpedantic -Werror -fwasm-exceptions -fno-rtti -O3 -flto -msimd128",
349
- "includes": "-I<repo>/dsp/include -I<repo>/dsp/core -I<repo>/dsp/generated/cpp -I<repo>/dsp/vendor/pffft/include/pffft"
349
+ "includes": "-I<repo>/dsp/include -I<repo>/dsp/bindings/generated -I<repo>/dsp/core -I<repo>/dsp/generated/cpp -I<repo>/dsp/vendor/pffft/include/pffft"
350
350
  },
351
351
  {
352
352
  "source": "dsp/core/engine.cpp",
353
353
  "definitions": "-DET_ENABLE_LIFECYCLE_EXCEPTION_BOUNDARY=1 -DET_SIMD=1 -DPFFFT_STATIC_DEFINE=1",
354
354
  "flags": "-O3 -DNDEBUG -std=c++20 -Wall -Wextra -Wpedantic -Werror -fwasm-exceptions -fno-rtti -O3 -flto -msimd128",
355
- "includes": "-I<repo>/dsp/include -I<repo>/dsp/core -I<repo>/dsp/generated/cpp -I<repo>/dsp/vendor/pffft/include/pffft"
355
+ "includes": "-I<repo>/dsp/include -I<repo>/dsp/bindings/generated -I<repo>/dsp/core -I<repo>/dsp/generated/cpp -I<repo>/dsp/vendor/pffft/include/pffft"
356
356
  },
357
357
  {
358
358
  "source": "dsp/core/registry.cpp",
359
359
  "definitions": "-DET_ENABLE_LIFECYCLE_EXCEPTION_BOUNDARY=1 -DET_SIMD=1 -DPFFFT_STATIC_DEFINE=1",
360
360
  "flags": "-O3 -DNDEBUG -std=c++20 -Wall -Wextra -Wpedantic -Werror -fwasm-exceptions -fno-rtti -O3 -flto -msimd128",
361
- "includes": "-I<repo>/dsp/include -I<repo>/dsp/core -I<repo>/dsp/generated/cpp -I<repo>/dsp/vendor/pffft/include/pffft"
361
+ "includes": "-I<repo>/dsp/include -I<repo>/dsp/bindings/generated -I<repo>/dsp/core -I<repo>/dsp/generated/cpp -I<repo>/dsp/vendor/pffft/include/pffft"
362
362
  },
363
363
  {
364
364
  "source": "dsp/core/telemetry.cpp",
365
365
  "definitions": "-DET_ENABLE_LIFECYCLE_EXCEPTION_BOUNDARY=1 -DET_SIMD=1 -DPFFFT_STATIC_DEFINE=1",
366
366
  "flags": "-O3 -DNDEBUG -std=c++20 -Wall -Wextra -Wpedantic -Werror -fwasm-exceptions -fno-rtti -O3 -flto -msimd128",
367
- "includes": "-I<repo>/dsp/include -I<repo>/dsp/core -I<repo>/dsp/generated/cpp -I<repo>/dsp/vendor/pffft/include/pffft"
367
+ "includes": "-I<repo>/dsp/include -I<repo>/dsp/bindings/generated -I<repo>/dsp/core -I<repo>/dsp/generated/cpp -I<repo>/dsp/vendor/pffft/include/pffft"
368
368
  },
369
369
  {
370
370
  "source": "dsp/plugins/lofi/g726_adpcm_simulator/kernel.cpp",
371
371
  "definitions": "-DET_ENABLE_LIFECYCLE_EXCEPTION_BOUNDARY=1 -DET_SIMD=1 -DPFFFT_STATIC_DEFINE=1",
372
372
  "flags": "-O3 -DNDEBUG -std=c++20 -Wall -Wextra -Wpedantic -Werror -fwasm-exceptions -fno-rtti -O3 -flto -msimd128",
373
- "includes": "-I<repo>/dsp/include -I<repo>/dsp/core -I<repo>/dsp/generated/cpp -I<repo>/dsp/vendor/pffft/include/pffft"
373
+ "includes": "-I<repo>/dsp/include -I<repo>/dsp/bindings/generated -I<repo>/dsp/core -I<repo>/dsp/generated/cpp -I<repo>/dsp/vendor/pffft/include/pffft"
374
374
  },
375
375
  {
376
376
  "source": "dsp/wasm/no_entry.cpp",
377
377
  "definitions": "-DPFFFT_STATIC_DEFINE=1",
378
378
  "flags": "-O3 -DNDEBUG -std=c++20",
379
- "includes": "-I<repo>/dsp/include -I<repo>/dsp/vendor/pffft/include/pffft"
379
+ "includes": "-I<repo>/dsp/include -I<repo>/dsp/bindings/generated -I<repo>/dsp/vendor/pffft/include/pffft"
380
380
  }
381
381
  ],
382
382
  "linkCommand": {
@@ -386,7 +386,7 @@
386
386
  }
387
387
  }
388
388
  },
389
- "digest": "sha256:49d590ffe39aeb113169fefad12d64eef03bd8125686fbed577ddb0f86b4f833"
389
+ "digest": "sha256:25a31669bb24da034d90512065fd746433745ead5d247e352c9ed08b3cbd24ea"
390
390
  }
391
391
  }
392
392
  },
@@ -622,6 +622,19 @@
622
622
  }
623
623
  ]
624
624
  },
625
+ {
626
+ "name": "GroupDelayPEQPlugin",
627
+ "hash": 2941825417,
628
+ "byteCapacity": 0,
629
+ "assets": [
630
+ {
631
+ "slot": 0,
632
+ "format": "ET_ASSET_F32_MULTICH",
633
+ "capacity": "32 MiB convolution cap",
634
+ "byteCapacity": 33554432
635
+ }
636
+ ]
637
+ },
625
638
  {
626
639
  "name": "HiPassFilterPlugin",
627
640
  "hash": 299011831,
@@ -731,6 +744,12 @@
731
744
  "byteCapacity": 0,
732
745
  "assets": []
733
746
  },
747
+ {
748
+ "name": "MDSimulatorPlugin",
749
+ "hash": 2124600068,
750
+ "byteCapacity": 0,
751
+ "assets": []
752
+ },
734
753
  {
735
754
  "name": "MP3CodecSimulatorPlugin",
736
755
  "hash": 3523139611,
@@ -773,18 +792,60 @@
773
792
  "byteCapacity": 0,
774
793
  "assets": []
775
794
  },
795
+ {
796
+ "name": "AutoFilterPlugin",
797
+ "hash": 1612236675,
798
+ "byteCapacity": 0,
799
+ "assets": []
800
+ },
801
+ {
802
+ "name": "AutoPanPlugin",
803
+ "hash": 1469569767,
804
+ "byteCapacity": 0,
805
+ "assets": []
806
+ },
807
+ {
808
+ "name": "ChorusPlugin",
809
+ "hash": 2730690922,
810
+ "byteCapacity": 0,
811
+ "assets": []
812
+ },
776
813
  {
777
814
  "name": "DopplerDistortionPlugin",
778
815
  "hash": 10372816,
779
816
  "byteCapacity": 0,
780
817
  "assets": []
781
818
  },
819
+ {
820
+ "name": "FrequencyShifterPlugin",
821
+ "hash": 1854760556,
822
+ "byteCapacity": 0,
823
+ "assets": []
824
+ },
825
+ {
826
+ "name": "PhaserPlugin",
827
+ "hash": 2823426285,
828
+ "byteCapacity": 0,
829
+ "assets": []
830
+ },
782
831
  {
783
832
  "name": "PitchShifterPlugin",
784
833
  "hash": 1998192054,
785
834
  "byteCapacity": 0,
786
835
  "assets": []
787
836
  },
837
+ {
838
+ "name": "PitchShifterHQPlugin",
839
+ "hash": 3982397611,
840
+ "byteCapacity": 0,
841
+ "assets": []
842
+ },
843
+ {
844
+ "name": "RotarySpeakerPlugin",
845
+ "hash": 1430720979,
846
+ "byteCapacity": 0,
847
+ "assets": []
848
+ },
788
849
  {
789
850
  "name": "TremoloPlugin",
790
851
  "hash": 1836520376,
@@ -835,7 +896,7 @@
835
896
  },
836
897
  {
837
898
  "name": "IRReverbPlugin",
838
- "hash": 2199744560,
899
+ "hash": 2529061658,
839
900
  "byteCapacity": 0,
840
901
  "assets": [
841
902
  {
@@ -852,6 +913,12 @@
852
913
  "byteCapacity": 0,
853
914
  "assets": []
854
915
  },
916
+ {
917
+ "name": "BandwidthExtenderPlugin",
918
+ "hash": 3030838001,
919
+ "byteCapacity": 0,
920
+ "assets": []
921
+ },
855
922
  {
856
923
  "name": "DynamicSaturationPlugin",
857
924
  "hash": 3365051379,
@@ -896,7 +963,7 @@
896
963
  },
897
964
  {
898
965
  "name": "TubeSimulatorPlugin",
899
- "hash": 3886736006,
966
+ "hash": 127429451,
900
967
  "byteCapacity": 0,
901
968
  "assets": []
902
969
  },
@@ -918,6 +985,12 @@
918
985
  "byteCapacity": 0,
919
986
  "assets": []
920
987
  },
988
+ {
989
+ "name": "PhaseSelectEqPlugin",
990
+ "hash": 1371985786,
991
+ "byteCapacity": 0,
992
+ "assets": []
993
+ },
921
994
  {
922
995
  "name": "StereoBlendPlugin",
923
996
  "hash": 648556109,
@@ -926,7 +999,7 @@
926
999
  }
927
1000
  ],
928
1001
  "sizes": {
929
- "baseline": 801049,
930
- "simd": 892774
1002
+ "baseline": 1167544,
1003
+ "simd": 1286159
931
1004
  }
932
1005
  }
Binary file
Binary file
package/dist/assets.js CHANGED
@@ -705,6 +705,29 @@ function prepareFirFilterAsset(effect, resolvedAssets, {
705
705
  path.irChannel !== paths[index].irChannel))) {
706
706
  throw new AssetError(`${effect.id} filter paths do not match its band layout.`);
707
707
  }
708
+ } else if (effect.type === 'RoomEQ') {
709
+ const explicitTopology = asset.format.topology;
710
+ if (explicitTopology === IR_ASSET_TOPOLOGY.mono ||
711
+ (explicitTopology === IR_ASSET_TOPOLOGY.unspecified && asset.format.channels === 1)) {
712
+ topology = IR_ASSET_TOPOLOGY.mono;
713
+ } else if (explicitTopology === IR_ASSET_TOPOLOGY.independent ||
714
+ (explicitTopology === IR_ASSET_TOPOLOGY.unspecified &&
715
+ asset.format.channels === processingChannels)) {
716
+ topology = IR_ASSET_TOPOLOGY.independent;
717
+ } else {
718
+ throw new AssetError(
719
+ `${effect.id} requires either one shared filter channel or one filter channel per processing channel.`
720
+ );
721
+ }
722
+ assetChannels = asset.format.channels;
723
+ paths = [];
724
+ inputCount = 0;
725
+ if ((topology === IR_ASSET_TOPOLOGY.mono && assetChannels !== 1) ||
726
+ (topology === IR_ASSET_TOPOLOGY.independent && assetChannels !== processingChannels)) {
727
+ throw new AssetError(
728
+ `${effect.id} requires either one shared filter channel or one filter channel per processing channel.`
729
+ );
730
+ }
708
731
  } else {
709
732
  topology = IR_ASSET_TOPOLOGY.mono;
710
733
  assetChannels = 1;