From 5be78985227ede43217fd848f44c3ea2e19e5e88 Mon Sep 17 00:00:00 2001 From: Raphael Forment Date: Mon, 4 Sep 2023 21:17:16 +0200 Subject: [PATCH] New technique using ADSR envelope --- packages/superdough/helpers.mjs | 16 ++++--- packages/superdough/superdough.mjs | 76 +++++++++++++++++++++++++----- 2 files changed, 72 insertions(+), 20 deletions(-) diff --git a/packages/superdough/helpers.mjs b/packages/superdough/helpers.mjs index 9ce197e1..4fda54eb 100644 --- a/packages/superdough/helpers.mjs +++ b/packages/superdough/helpers.mjs @@ -66,18 +66,20 @@ export const getADSR = (attack, decay, sustain, release, velocity, begin, end) = return gainNode; }; -export function createFilter(context, type, frequency, Q, curve, to, over, t) { +export function createFilter(context, type, frequency, Q, attack, decay, sustain, release, fenvmod, t) { const filter = context.createBiquadFilter(); filter.type = type; filter.frequency.value = frequency; filter.Q.value = Q; - if (to !== null && over !== null) { - if (curve === 'lin') { - filter.frequency.linearRampToValueAtTime(to, t + over); - } else { - filter.frequency.exponentialRampToValueAtTime(to, t + over); - } + // Apply ADSR to filter frequency + if (fenvmod > 0) { + const sustainFreq = sustain * frequency; + filter.frequency.linearRampToValueAtTime(frequency * fenvmod, t + attack); + filter.frequency.linearRampToValueAtTime(sustainFreq, t + attack + decay); + filter.frequency.setValueAtTime(sustainFreq, end); + filter.frequency.linearRampToValueAtTime(frequency, end + release); } + return filter; } diff --git a/packages/superdough/superdough.mjs b/packages/superdough/superdough.mjs index cf3c231e..6605662a 100644 --- a/packages/superdough/superdough.mjs +++ b/packages/superdough/superdough.mjs @@ -178,18 +178,32 @@ export const superdough = async (value, deadline, hapDuration) => { source, gain = 0.8, // filters - order = 12, - to, - filtenv = 'lin', - over, + order = '12db', + fenvmod = 2, // low pass + lpattack, + lpdecay, + lpsustain, + lprelease, cutoff, resonance = 1, // high pass + hpattack, + hpdecay, + hpsustain, + hprelease, hcutoff, hresonance = 1, + // full adsr for filter + lpadsr, + hpadsr, + bpadsr, // band pass bandf, + bpattack, + bpdecay, + bpsustain, + bprelease, bandq = 1, // coarse, @@ -215,6 +229,9 @@ export const superdough = async (value, deadline, hapDuration) => { if (bank && s) { s = `${bank}_${s}`; } + lpadsr && (lpattack = lpadsr[0]) && (lpdecay = lpadsr[1]) && (lpsustain = lpadsr[2]) && (lprelease = lpadsr[3]); + bpadsr && (bpattack = bpadsr[0]) && (bpdecay = bpadsr[1]) && (bpsustain = bpadsr[2]) && (bprelease = bpadsr[3]); + hpadsr && (hpattack = hpadsr[0]) && (hpdecay = hpadsr[1]) && (hpsustain = hpadsr[2]) && (hprelease = hpadsr[3]); // get source AudioNode let sourceNode; if (source) { @@ -245,28 +262,61 @@ export const superdough = async (value, deadline, hapDuration) => { chain.push(gainNode(gain)); if (cutoff !== undefined) { - const filter1 = createFilter(ac, 'lowpass', cutoff, resonance, filtenv, to || cutoff, over || hapDuration, t); + const filter1 = createFilter(ac, 'lowpass', cutoff, resonance, lpattack, lpdecay, lpsustain, lprelease, fmodenv, t); chain.push(filter1); - if (order === 24) { - const filter2 = createFilter(ac, 'lowpass', cutoff, resonance, filtenv, to || cutoff, over || hapDuration, t); + if (order === '24db') { + const filter2 = createFilter( + ac, + 'lowpass', + cutoff, + resonance, + lpattack, + lpdecay, + lpsustain, + lprelease, + fmodenv, + t, + ); chain.push(filter2); } } if (hcutoff !== undefined) { - const filter1 = createFilter(ac, 'highpass', hcutoff, hresonance, filtenv, to || hcutoff, over || hapDuration, t); + const filter1 = createFilter( + ac, + 'highpass', + hcutoff, + hresonance, + hpattack, + hpdecay, + hpsustain, + hprelease, + fenvmod, + t, + ); chain.push(filter1); - if (order === 24) { - const filter2 = createFilter(ac, 'highpass', hcutoff, hresonance, filtenv, to || hcutoff, over || hapDuration, t); + if (order === '24db') { + const filter2 = createFilter( + ac, + 'highpass', + hcutoff, + hresonance, + hpattack, + hpdecay, + hpsustain, + hprelease, + fenvmod, + t, + ); chain.push(filter2); } } if (bandf !== undefined) { - const filter1 = createFilter(ac, 'bandpass', bandf, bandq, filtenv, to || bandf, over || hapDuration, t); + const filter1 = createFilter(ac, 'bandpass', bandf, bandq, bpattack, bpdecay, bpsustain, bprelease, fenvmod, t); chain.push(filter1); - if (order === 24) { - const filter2 = createFilter(ac, 'bandpass', bandf, bandq, filtenv, to || bandf, over || hapDuration, t); + if (order === '24db') { + const filter2 = createFilter(ac, 'bandpass', bandf, bandq, bpattack, bpdecay, bpsustain, bprelease, fenvmod, t); chain.push(filter2); } }