From 4321814d36cac20ae5625bbd813b25ea3048411d Mon Sep 17 00:00:00 2001 From: Aria Date: Thu, 4 Dec 2025 13:04:33 -0600 Subject: [PATCH] Working version for compressor, filter, supersaw, wavetable --- packages/superdough/helpers.mjs | 16 ++++++++++++---- packages/superdough/synth.mjs | 2 +- packages/superdough/wavetable.mjs | 2 +- packages/superdough/worklets.mjs | 16 +++++++++------- 4 files changed, 23 insertions(+), 13 deletions(-) diff --git a/packages/superdough/helpers.mjs b/packages/superdough/helpers.mjs index 219c66d6..c5c03831 100644 --- a/packages/superdough/helpers.mjs +++ b/packages/superdough/helpers.mjs @@ -1,7 +1,8 @@ import { getAudioContext } from './audioContext.mjs'; -import { clamp, nanFallback, midiToFreq, noteToMidi } from './util.mjs'; -import { getNoiseBuffer } from './noise.mjs'; import { logger } from './logger.mjs'; +import { getNoiseBuffer } from './noise.mjs'; +import { getNodeFromPool } from './nodePools.mjs'; +import { clamp, nanFallback, midiToFreq, noteToMidi } from './util.mjs'; export const noises = ['pink', 'white', 'brown', 'crackle']; @@ -128,6 +129,7 @@ export function getLfo(audioContext, begin, end, properties = {}) { } export function getCompressor(ac, threshold, ratio, knee, attack, release) { + const node = getNodeFromPool('compressor', () => new DynamicsCompressorNode(ac, {})); const options = { threshold: threshold ?? -3, ratio: ratio ?? 10, @@ -135,7 +137,12 @@ export function getCompressor(ac, threshold, ratio, knee, attack, release) { attack: attack ?? 0.005, release: release ?? 0.05, }; - return new DynamicsCompressorNode(ac, options); + node.threshold.value = options.threshold; + node.ratio.value = options.ratio; + node.knee.value = options.knee; + node.attack.value = options.attack; + node.release.value = options.release; + return node; } // changes the default values of the envelope based on what parameters the user has defined @@ -214,7 +221,8 @@ export function createFilter(context, start, end, params, cps, cycle) { filter = getWorklet(context, 'ladder-processor', { frequency, q, drive }); frequencyParam = filter.parameters.get('frequency'); } else { - filter = context.createBiquadFilter(); + const factory = () => context.createBiquadFilter(); + filter = getNodeFromPool('filter', factory); filter.type = type; filter.Q.value = q; filter.frequency.value = frequency; diff --git a/packages/superdough/synth.mjs b/packages/superdough/synth.mjs index b10136ab..6bf7a137 100644 --- a/packages/superdough/synth.mjs +++ b/packages/superdough/synth.mjs @@ -168,7 +168,7 @@ export function registerSynthSounds() { const params = { frequency, begin, - end: end + 0.5, // add a grace period for pooling + end, freqspread: detune, voices, panspread, diff --git a/packages/superdough/wavetable.mjs b/packages/superdough/wavetable.mjs index a74b3747..2cac9fac 100644 --- a/packages/superdough/wavetable.mjs +++ b/packages/superdough/wavetable.mjs @@ -226,7 +226,7 @@ export async function onTriggerSynth(t, value, onended, tables, cps, frameLen) { const envEnd = endWithRelease + 0.01; const params = { begin: t, - end: envEnd + 0.5, // add a grace period for pooling + end: envEnd, frequency, freqspread: value.detune, position: value.wt, diff --git a/packages/superdough/worklets.mjs b/packages/superdough/worklets.mjs index 73fbe945..e6887a3f 100644 --- a/packages/superdough/worklets.mjs +++ b/packages/superdough/worklets.mjs @@ -518,16 +518,16 @@ class SuperSawOscillatorProcessor extends AudioWorkletProcessor { ]; } process(_input, outputs, params) { - if (currentTime >= params.end[0]) { - // should terminate + if (currentTime >= params.end[0] + 0.5) { + // Outside of grace period - should terminate if (this.isAlive) { this.port.postMessage({ type: 'died' }); this.isAlive = false; } return false; } - if (currentTime <= params.begin[0]) { - // keep alive + if (currentTime >= params.end[0] || currentTime <= params.begin[0]) { + // Inside of grace period or not yet started return true; } const output = outputs[0]; @@ -1163,7 +1163,7 @@ class WavetableOscillatorProcessor extends AudioWorkletProcessor { this.frameLen = null; this.numFrames = null; this.phase = []; - if (options?.frames) { + if (options?.key) { const key = options.key; this.frameLen = options.frameLen; if (!tablesCache[key]) { @@ -1317,14 +1317,16 @@ class WavetableOscillatorProcessor extends AudioWorkletProcessor { } process(_inputs, outputs, parameters) { - if (currentTime >= parameters.end[0]) { + if (currentTime >= parameters.end[0] + 0.5) { + // Outside of grace period - should terminate if (this.isAlive) { this.port.postMessage({ type: 'died' }); this.isAlive = false; } return false; } - if (currentTime <= parameters.begin[0]) { + if (currentTime >= parameters.end[0] || currentTime <= parameters.begin[0]) { + // Inside of grace period or not yet started return true; } const outL = outputs[0][0];