diff --git a/packages/superdough/nodePools.mjs b/packages/superdough/nodePools.mjs index 205352247..000099dc6 100644 --- a/packages/superdough/nodePools.mjs +++ b/packages/superdough/nodePools.mjs @@ -8,7 +8,6 @@ This program is free software: you can redistribute it and/or modify it under th const nodePools = new Map(); const POOL_KEY = Symbol('nodePoolKey'); const IS_WORKLET_DEAD = Symbol('nodePoolIsWorkletDead'); -const MAX_POOL_SIZE = 64; export const isPoolable = (node) => !!node[POOL_KEY]; @@ -47,10 +46,8 @@ export const releaseNodeToPool = (node) => { const now = node.context?.currentTime ?? 0; getParams(node).forEach((param) => param.cancelScheduledValues(now)); const pool = nodePools.get(key) ?? []; - if (pool.length < MAX_POOL_SIZE) { - pool.push(new WeakRef(node)); - nodePools.set(key, pool); - } + pool.push(new WeakRef(node)); + nodePools.set(key, pool); }; export const markWorkletAsDead = (worklet) => (worklet[IS_WORKLET_DEAD] = true); diff --git a/packages/superdough/synth.mjs b/packages/superdough/synth.mjs index f4bdd749f..ec1724da0 100644 --- a/packages/superdough/synth.mjs +++ b/packages/superdough/synth.mjs @@ -186,7 +186,10 @@ export function registerSynthSounds() { }); o.port.postMessage({ type: 'initialize' }); o.port.onmessage = (e) => { - if (e.data.type === 'died') markWorkletAsDead(o); + if (e.data.type === 'died') { + markWorkletAsDead(o); + o.port.postMessage({ type: 'diedACK' }); + } o.port.onmessage = null; }; const gainAdjustment = 1 / Math.sqrt(voices); diff --git a/packages/superdough/wavetable.mjs b/packages/superdough/wavetable.mjs index adf8b0c44..a228bc1d7 100644 --- a/packages/superdough/wavetable.mjs +++ b/packages/superdough/wavetable.mjs @@ -252,7 +252,10 @@ export async function onTriggerSynth(t, value, onended, tables, cps, frameLen) { }); source.port.postMessage({ type: 'initialize', payload }); source.port.onmessage = (e) => { - if (e.data.type === 'died') markWorkletAsDead(source); + if (e.data.type === 'died') { + markWorkletAsDead(source); + source.port.postMessage({ type: 'diedACK' }); + } source.port.onmessage = null; }; if (ac.currentTime > t) { diff --git a/packages/superdough/worklets.mjs b/packages/superdough/worklets.mjs index 52c13e836..61c620878 100644 --- a/packages/superdough/worklets.mjs +++ b/packages/superdough/worklets.mjs @@ -464,11 +464,19 @@ class SuperSawOscillatorProcessor extends AudioWorkletProcessor { constructor() { super(); this.isAlive = true; // used internally to prevent multiple death messages + // diedACK is used for the main thread to acknowledge that the worklet has died + // This is so that we don't risk simultaneously killing the worklet (`return false`) + // and pooling the worklet (main thread) before the async `died` message hits + // the main thread + this.diedACK = false; this.port.onmessage = (e) => { const { type, payload } = e.data || {}; if (type === 'initialize') { this.initialize(payload); } + if (type === 'diedACK') { + this.diedACK = true; + } }; this.initialize(); } @@ -529,7 +537,10 @@ class SuperSawOscillatorProcessor extends AudioWorkletProcessor { this.port.postMessage({ type: 'died' }); this.isAlive = false; } - return false; + if (this.diedACK || currentTime >= params.end[1] + 1) { + return false; + } + return true; } if (currentTime >= params.end[0] || currentTime <= params.begin[0]) { // Inside of grace period or not yet started @@ -1165,11 +1176,19 @@ class WavetableOscillatorProcessor extends AudioWorkletProcessor { constructor(options) { super(options); this.isAlive = true; // used internally to prevent multiple death messages + // diedACK is used for the main thread to acknowledge that the worklet has died + // This is so that we don't risk simultaneously killing the worklet (`return false`) + // and pooling the worklet (main thread) before the async `died` message hits + // the main thread + this.diedACK = false; this.port.onmessage = (e) => { const { type, payload } = e.data || {}; if (type === 'initialize') { this.initialize(payload); } + if (type === 'diedACK') { + this.diedACK = true; + } }; this.initialize(); } @@ -1338,7 +1357,10 @@ class WavetableOscillatorProcessor extends AudioWorkletProcessor { this.port.postMessage({ type: 'died' }); this.isAlive = false; } - return false; + if (this.diedACK || currentTime >= parameters.end[1] + 1) { + return false; + } + return true; } if (currentTime >= parameters.end[0] || currentTime <= parameters.begin[0]) { // Inside of grace period or not yet started