@opendaw/studio-core-wasm 0.0.16 → 0.0.18

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.
@@ -1 +1 @@
1
- {"version":3,"file":"engine-modules.d.ts","sourceRoot":"","sources":["../src/engine-modules.ts"],"names":[],"mappings":"AASA,MAAM,MAAM,aAAa,GAAG;IACxB,OAAO,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAG7E,mBAAmB,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAC;IAE3E,eAAe,EAAE,MAAM,CAAC;IAGxB,YAAY,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAG3C,cAAc,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAC9C,CAAA;AASD,MAAM,MAAM,mBAAmB,GAAG;IAC9B,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,mBAAmB,CAAA;IACzB,WAAW,EAAE,0BAA0B,CAAA;IACvC,YAAY,EAAE,MAAM,CAAA;IACpB,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,aAAa,EAAE,MAAM,CAAA;IACrB,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;CAC1C,CAAA;AAGD,oBAAY,mBAAmB;IAAE,WAAW,IAAI;IAAE,UAAU,IAAI;CAAC;AAGjE,oBAAY,0BAA0B;IAAE,SAAS,IAAI;IAAE,MAAM,IAAI;IAAE,SAAS,IAAI;CAAC;AAEjF,MAAM,MAAM,aAAa,GAAG;IACxB,YAAY,EAAE,WAAW,CAAC,MAAM,CAAA;IAChC,aAAa,EAAE,aAAa,CAAC,WAAW,CAAC,MAAM,CAAC,CAAA;IAChD,cAAc,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;IACrC,UAAU,EAAE,aAAa,CAAC,aAAa,CAAC,CAAA;IACxC,gBAAgB,EAAE,aAAa,CAAC,mBAAmB,CAAC,CAAA;CACvD,CAAA;AAQD,eAAO,MAAM,kBAAkB,QAAO,WAAW,CAAC,MAAgD,CAAA;AAMlG,eAAO,MAAM,OAAO,EAAE,aAAa,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CA8BnE,CAAA;AAKD,eAAO,MAAM,UAAU,EAAE,aAAa,CAAC,aAAa,CAWnD,CAAA;AAMD,eAAO,MAAM,iBAAiB,EAAE,aAAa,CAAC,mBAAmB,CA0BhE,CAAA;AAED,eAAO,MAAM,iBAAiB,GAAU,OAAM,MAAW,KAAG,OAAO,CAAC,aAAa,CAUhF,CAAA"}
1
+ {"version":3,"file":"engine-modules.d.ts","sourceRoot":"","sources":["../src/engine-modules.ts"],"names":[],"mappings":"AASA,MAAM,MAAM,aAAa,GAAG;IACxB,OAAO,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAG7E,mBAAmB,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAC;IAE3E,eAAe,EAAE,MAAM,CAAC;IAGxB,YAAY,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAG3C,cAAc,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAC9C,CAAA;AASD,MAAM,MAAM,mBAAmB,GAAG;IAC9B,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,mBAAmB,CAAA;IACzB,WAAW,EAAE,0BAA0B,CAAA;IACvC,YAAY,EAAE,MAAM,CAAA;IACpB,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,aAAa,EAAE,MAAM,CAAA;IACrB,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;CAC1C,CAAA;AAGD,oBAAY,mBAAmB;IAAE,WAAW,IAAI;IAAE,UAAU,IAAI;CAAC;AAGjE,oBAAY,0BAA0B;IAAE,SAAS,IAAI;IAAE,MAAM,IAAI;IAAE,SAAS,IAAI;CAAC;AAEjF,MAAM,MAAM,aAAa,GAAG;IACxB,YAAY,EAAE,WAAW,CAAC,MAAM,CAAA;IAChC,aAAa,EAAE,aAAa,CAAC,WAAW,CAAC,MAAM,CAAC,CAAA;IAChD,cAAc,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;IACrC,UAAU,EAAE,aAAa,CAAC,aAAa,CAAC,CAAA;IACxC,gBAAgB,EAAE,aAAa,CAAC,mBAAmB,CAAC,CAAA;CACvD,CAAA;AAQD,eAAO,MAAM,kBAAkB,QAAO,WAAW,CAAC,MAAgD,CAAA;AAMlG,eAAO,MAAM,OAAO,EAAE,aAAa,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CA+BnE,CAAA;AAKD,eAAO,MAAM,UAAU,EAAE,aAAa,CAAC,aAAa,CAYnD,CAAA;AAMD,eAAO,MAAM,iBAAiB,EAAE,aAAa,CAAC,mBAAmB,CA0BhE,CAAA;AAED,eAAO,MAAM,iBAAiB,GAAU,OAAM,MAAW,KAAG,OAAO,CAAC,aAAa,CAUhF,CAAA"}
@@ -28,6 +28,7 @@ export const createEngineMemory = () => new WebAssembly.Memory({ initial: 256 })
28
28
  export const DEVICES = [
29
29
  { url: "/wasm/plugins/device_vaporisateur.wasm", boxType: "VaporisateurDeviceBox" }, // instrument
30
30
  { url: "/wasm/plugins/device_neon.wasm", boxType: "NeonDeviceBox" }, // instrument (phase distortion)
31
+ { url: "/wasm/plugins/device_tubular.wasm", boxType: "TubularDeviceBox" }, // instrument (six-operator FM)
31
32
  { url: "/wasm/plugins/device_nano.wasm", boxType: "NanoDeviceBox" }, // instrument (sampler)
32
33
  { url: "/wasm/plugins/device_revamp.wasm", boxType: "RevampDeviceBox" }, // audio effect
33
34
  { url: "/wasm/plugins/device_tidal.wasm", boxType: "TidalDeviceBox" }, // audio effect
@@ -64,15 +65,16 @@ export const COMPOSITES = [
64
65
  { boxType: "PlayfieldDeviceBox", childrenField: 10, indexKey: 15, excludeKey: 42,
65
66
  cellInstrumentField: 0, cellMidiField: 0, cellAudioField: 0, childEnabledKey: 22,
66
67
  childMuteKey: 40, childSoloKey: 41, childVolumeKey: 50, childPanKey: 51 },
67
- // A generic instrument bundle: children are CELLS (CompositeCellBox) at field 10, each wrapping one
68
+ // A generic instrument bundle: children are CELLS (InstrumentCompositeCellBox) at field 10, each wrapping one
68
69
  // instrument (field 2) plus its midi-fx (3) and audio-fx (4) chains, ordered by the cell's own `index`
69
- // (field 5, UI position + engine sort). No note routing, no choke.
70
- { boxType: "CompositeDeviceBox", childrenField: 10, indexKey: 5, excludeKey: 0,
70
+ // (field 5, UI position + engine sort). No note routing, no choke. A cell has its own strip: gain 40,
71
+ // pan 43, and mute 41 / solo 42 silence at the STRIP (the layer keeps running), unlike a Playfield pad.
72
+ { boxType: "InstrumentCompositeBox", childrenField: 10, indexKey: 5, excludeKey: 0,
71
73
  cellInstrumentField: 2, cellMidiField: 3, cellAudioField: 4, childEnabledKey: 0,
72
- childMuteKey: 0, childSoloKey: 0, childVolumeKey: 0, childPanKey: 0 }
74
+ childMuteKey: 41, childSoloKey: 42, childVolumeKey: 40, childPanKey: 43 }
73
75
  ];
74
76
  // The EFFECT composite box types (parallel fx / midi stacks). Each hosts its ENTRIES at field 10, ordered by the
75
- // entry's own `index` (3); an entry holds its chain at field 2, its label at 4, and its gain / mute / solo at
77
+ // entry's own `index` (3); an entry holds its chain at field 2 (its label at 4 is deprecated, labelKey 0), and its gain / mute / solo at
76
78
  // 40 / 41 / 42. An audio composite additionally has its input tap at 11 and dry / wet at 12 / 13. The entry
77
79
  // boxes are NOT plugins — the engine realizes them itself, so nothing is added to DEVICES for them.
78
80
  export const EFFECT_COMPOSITES = [
@@ -80,7 +82,7 @@ export const EFFECT_COMPOSITES = [
80
82
  {
81
83
  boxType: "AudioEffectCompositeBox", kind: EffectCompositeKind.AudioEffect,
82
84
  distributor: EffectCompositeDistributor.Broadcast,
83
- entriesField: 10, indexKey: 3, chainField: 2, labelKey: 4,
85
+ entriesField: 10, indexKey: 3, chainField: 2, labelKey: 0,
84
86
  gainKey: 40, panKey: 43, muteKey: 41, soloKey: 42, dryKey: 12, wetKey: 13, inputTapField: 11,
85
87
  crossoverKeys: [0, 0, 0]
86
88
  },
@@ -88,7 +90,7 @@ export const EFFECT_COMPOSITES = [
88
90
  {
89
91
  boxType: "StereoCompositeBox", kind: EffectCompositeKind.AudioEffect,
90
92
  distributor: EffectCompositeDistributor.Stereo,
91
- entriesField: 10, indexKey: 3, chainField: 2, labelKey: 4,
93
+ entriesField: 10, indexKey: 3, chainField: 2, labelKey: 0,
92
94
  gainKey: 40, panKey: 43, muteKey: 41, soloKey: 42, dryKey: 12, wetKey: 13, inputTapField: 11,
93
95
  crossoverKeys: [0, 0, 0]
94
96
  },
@@ -97,7 +99,7 @@ export const EFFECT_COMPOSITES = [
97
99
  {
98
100
  boxType: "FrequencySplitBox", kind: EffectCompositeKind.AudioEffect,
99
101
  distributor: EffectCompositeDistributor.Frequency,
100
- entriesField: 10, indexKey: 3, chainField: 2, labelKey: 4,
102
+ entriesField: 10, indexKey: 3, chainField: 2, labelKey: 0,
101
103
  gainKey: 40, panKey: 43, muteKey: 41, soloKey: 42, dryKey: 12, wetKey: 13, inputTapField: 11,
102
104
  crossoverKeys: [14, 15, 16]
103
105
  }
@@ -1 +1 @@
1
- {"version":3,"file":"script-bridge.d.ts","sourceRoot":"","sources":["../src/script-bridge.ts"],"names":[],"mappings":"AA2CA,MAAM,WAAW,YAAY;IACzB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAAA;IAC3D,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAA;CACxC;AAyDD,qBAAa,aAAa;;gBASV,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EACpE,SAAS,GAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAe;IAQzE,OAAO,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,MAAM,EAAE,KAAK,MAAM,GAAG,IAAI,CAAC;IA0N/D,eAAe,IAAI,MAAM;CAG5B"}
1
+ {"version":3,"file":"script-bridge.d.ts","sourceRoot":"","sources":["../src/script-bridge.ts"],"names":[],"mappings":"AA4CA,MAAM,WAAW,YAAY;IACzB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAAA;IAC3D,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAA;CACxC;AAyDD,qBAAa,aAAa;;gBAWV,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EACpE,SAAS,GAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAe;IAQzE,OAAO,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,MAAM,EAAE,KAAK,MAAM,GAAG,IAAI,CAAC;IAgO/D,eAAe,IAAI,MAAM;CAG5B"}
@@ -17,6 +17,7 @@ const RENDER_QUANTUM = 128;
17
17
  // ~1 second of render calls (128-frame quanta at 48k) before a scriptless device is reported — long enough to
18
18
  // cover a script still compiling / addModule-ing async, short enough to surface a genuine misconfiguration.
19
19
  const MISSING_GRACE_CALLS = 375;
20
+ const STALE_UPDATE = -2;
20
21
  // Device kinds (mirror abi DEVICE_KIND_*) and their script registries.
21
22
  const KIND_INSTRUMENT = 0;
22
23
  const KIND_AUDIO_EFFECT = 1;
@@ -35,6 +36,7 @@ class Bridge {
35
36
  uuid;
36
37
  kind;
37
38
  registryName;
39
+ key;
38
40
  proc = null;
39
41
  currentUpdate = -1;
40
42
  silenced = false;
@@ -57,10 +59,11 @@ class Bridge {
57
59
  // swallow). Count the render calls that found no registry entry; warn ONCE past the grace window.
58
60
  missingCalls = 0;
59
61
  warnedMissing = false;
60
- constructor(uuid, kind, registryName) {
62
+ constructor(uuid, kind, registryName, key) {
61
63
  this.uuid = uuid;
62
64
  this.kind = kind;
63
65
  this.registryName = registryName;
66
+ this.key = key;
64
67
  }
65
68
  }
66
69
  const resolveMapping = (declaration) => {
@@ -96,7 +99,9 @@ export class ScriptBridges {
96
99
  #sampleRate;
97
100
  #onMessage;
98
101
  #bridges = new Map();
99
- #byUuid = new Map();
102
+ // uuid + state pointer: a composite's replicas of one unit-level device share the box uuid but are separate
103
+ // instances, each with its own Processor
104
+ #byInstance = new Map();
100
105
  #nextHandle = 1;
101
106
  constructor(memory, engine, sampleRate, onMessage = () => { }) {
102
107
  this.#memory = memory;
@@ -118,18 +123,19 @@ export class ScriptBridges {
118
123
  host_script_release: (handle) => this.#release(handle)
119
124
  };
120
125
  }
121
- // A `create` for a uuid that already has a live bridge REPLACES it: release the old one first (its
126
+ // A `create` for an instance that already has a live bridge REPLACES it: release the old one first (its
122
127
  // Processor + limiter + runtime), so a rebind the engine's `terminate` hasn't (yet, or ever) reached for
123
128
  // never orphans the previous bridge — the dedup a bare `#nextHandle++` per call was missing entirely.
124
- #create(uuidPtr, kind, _statePtr) {
129
+ #create(uuidPtr, kind, statePtr) {
125
130
  const uuid = UUID.toString(new Uint8Array(this.#memory.buffer, uuidPtr, 16).slice());
126
- const existingHandle = this.#byUuid.get(uuid);
131
+ const key = `${uuid}:${statePtr}`;
132
+ const existingHandle = this.#byInstance.get(key);
127
133
  if (isDefined(existingHandle)) {
128
134
  this.#release(existingHandle);
129
135
  }
130
136
  const handle = this.#nextHandle++;
131
- this.#bridges.set(handle, new Bridge(uuid, kind, REGISTRY_BY_KIND[kind] ?? "werkstattProcessors"));
132
- this.#byUuid.set(uuid, handle);
137
+ this.#bridges.set(handle, new Bridge(uuid, kind, REGISTRY_BY_KIND[kind] ?? "werkstattProcessors", key));
138
+ this.#byInstance.set(key, handle);
133
139
  return handle;
134
140
  }
135
141
  // Poll the registry and hot-swap the user Processor when its `update` changed (the TS #tryLoad/#swapProcessor),
@@ -245,8 +251,16 @@ export class ScriptBridges {
245
251
  }
246
252
  #reset(handle) {
247
253
  const bridge = this.#bridges.get(handle);
248
- bridge?.proc?.reset?.();
249
- bridge?.spielwerk?.reset();
254
+ if (bridge === undefined) {
255
+ return;
256
+ }
257
+ if (bridge.kind === KIND_AUDIO_EFFECT && !bridge.silenced && typeof bridge.proc?.reset !== "function") {
258
+ bridge.currentUpdate = STALE_UPDATE; // no reset() in the script: the next pull rebuilds the Processor
259
+ }
260
+ else {
261
+ bridge.proc?.reset?.();
262
+ }
263
+ bridge.spielwerk?.reset();
250
264
  }
251
265
  #param(handle, index, kind, value, modulation) {
252
266
  const bridge = this.#bridges.get(handle);
@@ -344,8 +358,8 @@ export class ScriptBridges {
344
358
  return;
345
359
  }
346
360
  this.#bridges.delete(handle);
347
- if (this.#byUuid.get(bridge.uuid) === handle) {
348
- this.#byUuid.delete(bridge.uuid);
361
+ if (this.#byInstance.get(bridge.key) === handle) {
362
+ this.#byInstance.delete(bridge.key);
349
363
  }
350
364
  }
351
365
  /// Test-only introspection: how many bridges are currently live, proving a rebind's `#create` dedup
@@ -1 +1 @@
1
- {"version":3,"file":"script-spielwerk.d.ts","sourceRoot":"","sources":["../src/script-spielwerk.ts"],"names":[],"mappings":"AAuBA,KAAK,aAAa,GAAG;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAC,CAAA;AACxG,KAAK,YAAY,GAAG;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAC,CAAA;AAKnH,qBAAa,gBAAgB;IACzB,QAAQ,CAAC,QAAQ,EAAE,YAAY,EAAE,CAAK;IACtC,QAAQ,CAAC,SAAS,EAAE,aAAa,EAAE,CAAK;IACxC,QAAQ,CAAC,cAAc,2BAAiC;IAExD,KAAK,IAAI,IAAI;CAKhB;AAgBD,eAAO,MAAM,UAAU,GAAI,QAAQ,eAAe,EAAE,OAAO,MAAM,EAAE,SAAS,MAAM,EACvD,QAAQ,MAAM,EAAE,QAAQ,MAAM,KAAG,MAI3D,CAAA;AAiBD,eAAO,MAAM,YAAY,GAAI,SAAS,gBAAgB,EAAE,MAAM,GAAG,EAAE,QAAQ,eAAe,EAC7D,OAAO,MAAM,EAAE,SAAS,MAAM,EAAE,QAAQ,MAAM,EAAE,QAAQ,MAAM,EAC9D,MAAM,MAAM,EAAE,IAAI,MAAM,EAAE,KAAK,MAAM,EAAE,OAAO,MAAM,EAAE,IAAI,MAAM,EAAE,IAAI,MAAM,EAC5E,MAAM,OAAO,KAAG,MAoG5C,CAAA"}
1
+ {"version":3,"file":"script-spielwerk.d.ts","sourceRoot":"","sources":["../src/script-spielwerk.ts"],"names":[],"mappings":"AAuBA,KAAK,aAAa,GAAG;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAC,CAAA;AACxG,KAAK,YAAY,GAAG;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAC,CAAA;AAKnH,qBAAa,gBAAgB;IACzB,QAAQ,CAAC,QAAQ,EAAE,YAAY,EAAE,CAAK;IACtC,QAAQ,CAAC,SAAS,EAAE,aAAa,EAAE,CAAK;IACxC,QAAQ,CAAC,cAAc,2BAAiC;IAExD,KAAK,IAAI,IAAI;CAKhB;AAgBD,eAAO,MAAM,UAAU,GAAI,QAAQ,eAAe,EAAE,OAAO,MAAM,EAAE,SAAS,MAAM,EACvD,QAAQ,MAAM,EAAE,QAAQ,MAAM,KAAG,MAI3D,CAAA;AAiBD,eAAO,MAAM,YAAY,GAAI,SAAS,gBAAgB,EAAE,MAAM,GAAG,EAAE,QAAQ,eAAe,EAC7D,OAAO,MAAM,EAAE,SAAS,MAAM,EAAE,QAAQ,MAAM,EAAE,QAAQ,MAAM,EAC9D,MAAM,MAAM,EAAE,IAAI,MAAM,EAAE,KAAK,MAAM,EAAE,OAAO,MAAM,EAAE,IAAI,MAAM,EAAE,IAAI,MAAM,EAC5E,MAAM,OAAO,KAAG,MAqG5C,CAAA"}
@@ -101,6 +101,7 @@ export const runSpielwerk = (runtime, proc, memory, inPtr, inCount, outPtr, outM
101
101
  emit(KIND_NOTE_OFF, from, note.id, note.pitch, 0, 0, 0);
102
102
  }
103
103
  runtime.reset();
104
+ proc.reset?.();
104
105
  }
105
106
  // Release retained notes whose span completed within this range, emitting their note-off.
106
107
  for (let i = runtime.retained.length - 1; i >= 0; i--) {
Binary file
Binary file
Binary file
Binary file
Binary file