diff --git a/packages/superdough/modulators.mjs b/packages/superdough/modulators.mjs index ea9067102..7d119a06b 100644 --- a/packages/superdough/modulators.mjs +++ b/packages/superdough/modulators.mjs @@ -62,7 +62,10 @@ const getTargetParamsForControl = (control, nodes, subControl) => { const lookupKey = subControl ? `${control}_${subControl}` : control; const targetInfo = getControlData(lookupKey) ?? getControlData(control); if (!targetInfo) { - errorLogger(new Error(`Could not find control data for target '${control}'`), 'superdough'); + errorLogger( + new Error(`Could not find control data for target '${control}'. It may not be modulatable.`), + 'superdough', + ); return { targetParams: [], paramName: control }; } const paramName = targetInfo.param; diff --git a/packages/superdough/superdough.mjs b/packages/superdough/superdough.mjs index 7546bfab4..2e46b2d7e 100644 --- a/packages/superdough/superdough.mjs +++ b/packages/superdough/superdough.mjs @@ -597,6 +597,7 @@ export const superdough = async (value, t, hapDuration, cps = 0.5, cycle = 0.5) delaysync = getDefaultValue('delaysync'), delaytime, stretch = getDefaultValue('stretch'), + i = getDefaultValue('i'), } = fx; gain = applyGainCurve(nanFallback(gain, 1)); shapevol = applyGainCurve(shapevol); @@ -744,9 +745,9 @@ export const superdough = async (value, t, hapDuration, cps = 0.5, cycle = 0.5) } if (fx.vowel !== undefined) { - const vowelFilter = ac.createVowelFilter(fx.vowel); - fxNodes['vowel'] = [vowelFilter]; - chain.connect(vowelFilter); + const vowelNode = ac.createVowelFilter(fx.vowel); + fxNodes['vowel'] = vowelNode.filters; + chain.connect(vowelNode); } // effects @@ -839,7 +840,7 @@ export const superdough = async (value, t, hapDuration, cps = 0.5, cycle = 0.5) chain.audioNodes.push(lfo); } // delay - if (delay > 0 && delaytime > 0 && delayfeedback > 0) { + if (key !== 'main' && delay > 0 && delaytime > 0 && delayfeedback > 0) { const dry = gainNode(1); delayfeedback = clamp(delayfeedback, 0, 0.98); const delayNode = ac.createFeedbackDelay(1, delaytime, delayfeedback); @@ -856,7 +857,7 @@ export const superdough = async (value, t, hapDuration, cps = 0.5, cycle = 0.5) fxNodes['delay_mix'] = [wetDelay]; } // reverb - if (fx.room > 0) { + if (key !== 'main' && fx.room > 0) { let roomIR; if (fx.ir !== undefined) { let url; @@ -864,7 +865,7 @@ export const superdough = async (value, t, hapDuration, cps = 0.5, cycle = 0.5) if (Array.isArray(sample)) { url = sample.data.samples[fx.i % sample.data.samples.length]; } else if (typeof sample === 'object') { - url = Object.values(sample.data.samples).flat()[fx.i % Object.values(sample.data.samples).length]; + url = Object.values(sample.data.samples).flat()[i % Object.values(sample.data.samples).length]; } roomIR = await loadBuffer(url, ac, fx.ir, 0); } diff --git a/packages/superdough/superdoughdata.mjs b/packages/superdough/superdoughdata.mjs index 2dac194f1..e43df9eef 100644 --- a/packages/superdough/superdoughdata.mjs +++ b/packages/superdough/superdoughdata.mjs @@ -87,7 +87,7 @@ const CONTROL_TARGETS = { compressorRelease: { node: 'compressor', param: 'release' }, // PHASER - phaserrate: { node: 'phaser_lfo', param: 'rate' }, + phaserrate: { node: 'phaser_lfo', param: 'frequency' }, phasersweep: { node: 'phaser_lfo', param: 'depth' }, phasercenter: { node: 'phaser', param: 'frequency' }, phaserdepth: { node: 'phaser', param: 'Q' }, diff --git a/packages/superdough/vowel.mjs b/packages/superdough/vowel.mjs index bfc1c9fcd..8ecbf9d5c 100644 --- a/packages/superdough/vowel.mjs +++ b/packages/superdough/vowel.mjs @@ -1,3 +1,5 @@ +import { releaseAudioNode } from './helpers.mjs'; + // credits to webdirt: https://github.com/dktr0/WebDirt/blob/41342e81d6ad694a2310d491fef7b7e8b0929efe/js-src/Graph.js#L597 export var vowelFormant = { a: { freqs: [660, 1120, 2750, 3000, 3350], gains: [1, 0.5012, 0.0708, 0.0631, 0.0126], qs: [80, 90, 120, 130, 140] }, @@ -46,7 +48,8 @@ if (typeof GainNode !== 'undefined') { } const { gains, qs, freqs } = vowelFormant[letter]; this.makeupGain = ac.createGain(); - this.audioNodes = []; + this.filters = []; + this.gains = []; for (let i = 0; i < 5; i++) { const gain = ac.createGain(); gain.gain.value = gains[i]; @@ -56,9 +59,9 @@ if (typeof GainNode !== 'undefined') { filter.frequency.value = freqs[i]; super.connect(filter); filter.connect(gain); - this.audioNodes.push(filter); + this.filters.push(filter); gain.connect(this.makeupGain); - this.audioNodes.push(gain); + this.gains.push(gain); } this.makeupGain.gain.value = 8; // how much makeup gain to add? return this; @@ -67,11 +70,13 @@ if (typeof GainNode !== 'undefined') { this.makeupGain.connect(target); } disconnect() { - this.makeupGain.disconnect(); - this.audioNodes.forEach((n) => n.disconnect()); + releaseAudioNode(this.makeupGain); + this.filters.forEach(releaseAudioNode); + this.gains.forEach(releaseAudioNode); super.disconnect(); this.makeupGain = null; - this.audioNodes = null; + this.filters = null; + this.gains = null; } }