From 130ad4451b7af054371992220342a0658b9543d7 Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Sun, 8 Oct 2023 00:30:12 +0200 Subject: [PATCH 1/7] add compressor + postgain --- packages/core/controls.mjs | 6 ++++++ packages/superdough/helpers.mjs | 11 +++++++++++ packages/superdough/superdough.mjs | 15 +++++++++++++-- 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/packages/core/controls.mjs b/packages/core/controls.mjs index 88c2c072..832b09dc 100644 --- a/packages/core/controls.mjs +++ b/packages/core/controls.mjs @@ -86,6 +86,7 @@ const generic_params = [ * */ ['gain'], + ['postgain'], /** * Like {@link gain}, but linear. * @@ -1051,6 +1052,11 @@ const generic_params = [ * */ ['shape'], + [['compressor', 'compressorRatio', 'compressorKnee', 'compressorAttack', 'compressorRelease']], + ['compressorKnee'], + ['compressorRatio'], + ['compressorAttack'], + ['compressorRelease'], /** * Changes the speed of sample playback, i.e. a cheap way of changing pitch. * diff --git a/packages/superdough/helpers.mjs b/packages/superdough/helpers.mjs index 576ec3f1..d87ea94d 100644 --- a/packages/superdough/helpers.mjs +++ b/packages/superdough/helpers.mjs @@ -78,6 +78,17 @@ export const getParamADSR = (param, attack, decay, sustain, release, min, max, b param.linearRampToValueAtTime(min, end + Math.max(release, 0.1)); }; +export function getCompressor(ac, threshold, ratio, knee, attack, release) { + const options = { + threshold: threshold ?? -3, + ratio: ratio ?? 10, + knee: knee ?? 10, + attack: attack ?? 0.005, + release: release ?? 0.05, + }; + return new DynamicsCompressorNode(ac, options); +} + export function createFilter( context, type, diff --git a/packages/superdough/superdough.mjs b/packages/superdough/superdough.mjs index 730e495d..410b7b96 100644 --- a/packages/superdough/superdough.mjs +++ b/packages/superdough/superdough.mjs @@ -9,7 +9,7 @@ import './reverb.mjs'; import './vowel.mjs'; import { clamp } from './util.mjs'; import workletsUrl from './worklets.mjs?url'; -import { createFilter, gainNode } from './helpers.mjs'; +import { createFilter, gainNode, getCompressor } from './helpers.mjs'; import { map } from 'nanostores'; import { logger } from './logger.mjs'; @@ -192,6 +192,7 @@ export const superdough = async (value, deadline, hapDuration) => { bank, source, gain = 0.8, + postgain = 1, // filters ftype = '12db', fanchor = 0.5, @@ -237,6 +238,11 @@ export const superdough = async (value, deadline, hapDuration) => { velocity = 1, analyze, // analyser wet fft = 8, // fftSize 0 - 10 + compressor: compressorThreshold, + compressorRatio, + compressorKnee, + compressorAttack, + compressorRelease, } = value; gain *= velocity; // legacy fix for velocity let toDisconnect = []; // audio nodes that will be disconnected when the source has ended @@ -351,6 +357,11 @@ export const superdough = async (value, deadline, hapDuration) => { crush !== undefined && chain.push(getWorklet(ac, 'crush-processor', { crush })); shape !== undefined && chain.push(getWorklet(ac, 'shape-processor', { shape })); + compressorThreshold !== undefined && + chain.push( + getCompressor(ac, compressorThreshold, compressorRatio, compressorKnee, compressorAttack, compressorRelease), + ); + // panning if (pan !== undefined) { const panner = ac.createStereoPanner(); @@ -359,7 +370,7 @@ export const superdough = async (value, deadline, hapDuration) => { } // last gain - const post = gainNode(1); + const post = gainNode(postgain); chain.push(post); post.connect(getDestination()); From 444d583a49065648af5d4c2cc6b1c2bf82532d26 Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Sun, 8 Oct 2023 13:23:13 +0200 Subject: [PATCH 2/7] fix: hashes in urls --- packages/superdough/sampler.mjs | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/superdough/sampler.mjs b/packages/superdough/sampler.mjs index 76b6a542..a7e9c3a3 100644 --- a/packages/superdough/sampler.mjs +++ b/packages/superdough/sampler.mjs @@ -64,6 +64,7 @@ export const getSampleBufferSource = async (s, n, note, speed, freq, bank, resol export const loadBuffer = (url, ac, s, n = 0) => { const label = s ? `sound "${s}:${n}"` : 'sample'; + url = url.replace('#', '%23'); if (!loadCache[url]) { logger(`[sampler] load ${label}..`, 'load-sample', { url }); const timestamp = Date.now(); From 0a3692e459ca2eb807b71f55ee6698d36dfd2aa3 Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Sun, 8 Oct 2023 13:37:39 +0200 Subject: [PATCH 3/7] compressor docs --- packages/core/controls.mjs | 19 +++++++++++++++++++ website/src/pages/learn/effects.mdx | 9 +++++++++ 2 files changed, 28 insertions(+) diff --git a/packages/core/controls.mjs b/packages/core/controls.mjs index 832b09dc..3abeb504 100644 --- a/packages/core/controls.mjs +++ b/packages/core/controls.mjs @@ -86,6 +86,15 @@ const generic_params = [ * */ ['gain'], + /** + * Gain applied after all effects have been processed. + * + * @name postgain + * @example + * s("bd sd,hh*4") + * .compressor("-20:20:10:.002:.02").postgain(1.5) + * + */ ['postgain'], /** * Like {@link gain}, but linear. @@ -1052,6 +1061,16 @@ const generic_params = [ * */ ['shape'], + /** + * Dynamics Compressor. The params are `compressor("threshold:ratio:knee:attack:release")` + * More info [here](https://developer.mozilla.org/en-US/docs/Web/API/DynamicsCompressorNode?retiredLocale=de#instance_properties) + * + * @name compressor + * @example + * s("bd sd,hh*4") + * .compressor("-20:20:10:.002:.02") + * + */ [['compressor', 'compressorRatio', 'compressorKnee', 'compressorAttack', 'compressorRelease']], ['compressorKnee'], ['compressorRatio'], diff --git a/website/src/pages/learn/effects.mdx b/website/src/pages/learn/effects.mdx index 2ee6c44a..11b74646 100644 --- a/website/src/pages/learn/effects.mdx +++ b/website/src/pages/learn/effects.mdx @@ -144,6 +144,15 @@ There is one filter envelope for each filter type and thus one set of envelope f +## compressor + + + +## postgain + + + + # Panning ## jux From 08ce8213fcb09eb2dd709650b1f5339138a774bc Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Sun, 8 Oct 2023 13:37:56 +0200 Subject: [PATCH 4/7] format --- website/src/pages/learn/effects.mdx | 1 - 1 file changed, 1 deletion(-) diff --git a/website/src/pages/learn/effects.mdx b/website/src/pages/learn/effects.mdx index 11b74646..0bb9da9e 100644 --- a/website/src/pages/learn/effects.mdx +++ b/website/src/pages/learn/effects.mdx @@ -152,7 +152,6 @@ There is one filter envelope for each filter type and thus one set of envelope f - # Panning ## jux From 56c14414946796436db34f4f565a9c9ec437674d Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Sun, 8 Oct 2023 13:38:18 +0200 Subject: [PATCH 5/7] snapshot --- test/__snapshots__/examples.test.mjs.snap | 58 +++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/test/__snapshots__/examples.test.mjs.snap b/test/__snapshots__/examples.test.mjs.snap index 18370903..f351a5a0 100644 --- a/test/__snapshots__/examples.test.mjs.snap +++ b/test/__snapshots__/examples.test.mjs.snap @@ -1185,6 +1185,35 @@ exports[`runs examples > example "compress" example index 0 1`] = ` ] `; +exports[`runs examples > example "compressor" example index 0 1`] = ` +[ + "[ 0/1 → 1/4 | s:hh compressor:-20 compressorRatio:20 compressorKnee:10 compressorAttack:0.002 compressorRelease:0.02 ]", + "[ 0/1 → 1/2 | s:bd compressor:-20 compressorRatio:20 compressorKnee:10 compressorAttack:0.002 compressorRelease:0.02 ]", + "[ 1/4 → 1/2 | s:hh compressor:-20 compressorRatio:20 compressorKnee:10 compressorAttack:0.002 compressorRelease:0.02 ]", + "[ 1/2 → 3/4 | s:hh compressor:-20 compressorRatio:20 compressorKnee:10 compressorAttack:0.002 compressorRelease:0.02 ]", + "[ 1/2 → 1/1 | s:sd compressor:-20 compressorRatio:20 compressorKnee:10 compressorAttack:0.002 compressorRelease:0.02 ]", + "[ 3/4 → 1/1 | s:hh compressor:-20 compressorRatio:20 compressorKnee:10 compressorAttack:0.002 compressorRelease:0.02 ]", + "[ 1/1 → 5/4 | s:hh compressor:-20 compressorRatio:20 compressorKnee:10 compressorAttack:0.002 compressorRelease:0.02 ]", + "[ 1/1 → 3/2 | s:bd compressor:-20 compressorRatio:20 compressorKnee:10 compressorAttack:0.002 compressorRelease:0.02 ]", + "[ 5/4 → 3/2 | s:hh compressor:-20 compressorRatio:20 compressorKnee:10 compressorAttack:0.002 compressorRelease:0.02 ]", + "[ 3/2 → 7/4 | s:hh compressor:-20 compressorRatio:20 compressorKnee:10 compressorAttack:0.002 compressorRelease:0.02 ]", + "[ 3/2 → 2/1 | s:sd compressor:-20 compressorRatio:20 compressorKnee:10 compressorAttack:0.002 compressorRelease:0.02 ]", + "[ 7/4 → 2/1 | s:hh compressor:-20 compressorRatio:20 compressorKnee:10 compressorAttack:0.002 compressorRelease:0.02 ]", + "[ 2/1 → 9/4 | s:hh compressor:-20 compressorRatio:20 compressorKnee:10 compressorAttack:0.002 compressorRelease:0.02 ]", + "[ 2/1 → 5/2 | s:bd compressor:-20 compressorRatio:20 compressorKnee:10 compressorAttack:0.002 compressorRelease:0.02 ]", + "[ 9/4 → 5/2 | s:hh compressor:-20 compressorRatio:20 compressorKnee:10 compressorAttack:0.002 compressorRelease:0.02 ]", + "[ 5/2 → 11/4 | s:hh compressor:-20 compressorRatio:20 compressorKnee:10 compressorAttack:0.002 compressorRelease:0.02 ]", + "[ 5/2 → 3/1 | s:sd compressor:-20 compressorRatio:20 compressorKnee:10 compressorAttack:0.002 compressorRelease:0.02 ]", + "[ 11/4 → 3/1 | s:hh compressor:-20 compressorRatio:20 compressorKnee:10 compressorAttack:0.002 compressorRelease:0.02 ]", + "[ 3/1 → 13/4 | s:hh compressor:-20 compressorRatio:20 compressorKnee:10 compressorAttack:0.002 compressorRelease:0.02 ]", + "[ 3/1 → 7/2 | s:bd compressor:-20 compressorRatio:20 compressorKnee:10 compressorAttack:0.002 compressorRelease:0.02 ]", + "[ 13/4 → 7/2 | s:hh compressor:-20 compressorRatio:20 compressorKnee:10 compressorAttack:0.002 compressorRelease:0.02 ]", + "[ 7/2 → 15/4 | s:hh compressor:-20 compressorRatio:20 compressorKnee:10 compressorAttack:0.002 compressorRelease:0.02 ]", + "[ 7/2 → 4/1 | s:sd compressor:-20 compressorRatio:20 compressorKnee:10 compressorAttack:0.002 compressorRelease:0.02 ]", + "[ 15/4 → 4/1 | s:hh compressor:-20 compressorRatio:20 compressorKnee:10 compressorAttack:0.002 compressorRelease:0.02 ]", +] +`; + exports[`runs examples > example "cosine" example index 0 1`] = ` [ "[ 0/1 → 1/8 | note:Eb4 ]", @@ -3293,6 +3322,35 @@ exports[`runs examples > example "polymeterSteps" example index 0 1`] = ` ] `; +exports[`runs examples > example "postgain" example index 0 1`] = ` +[ + "[ 0/1 → 1/4 | s:hh compressor:-20 compressorRatio:20 compressorKnee:10 compressorAttack:0.002 compressorRelease:0.02 postgain:1.5 ]", + "[ 0/1 → 1/2 | s:bd compressor:-20 compressorRatio:20 compressorKnee:10 compressorAttack:0.002 compressorRelease:0.02 postgain:1.5 ]", + "[ 1/4 → 1/2 | s:hh compressor:-20 compressorRatio:20 compressorKnee:10 compressorAttack:0.002 compressorRelease:0.02 postgain:1.5 ]", + "[ 1/2 → 3/4 | s:hh compressor:-20 compressorRatio:20 compressorKnee:10 compressorAttack:0.002 compressorRelease:0.02 postgain:1.5 ]", + "[ 1/2 → 1/1 | s:sd compressor:-20 compressorRatio:20 compressorKnee:10 compressorAttack:0.002 compressorRelease:0.02 postgain:1.5 ]", + "[ 3/4 → 1/1 | s:hh compressor:-20 compressorRatio:20 compressorKnee:10 compressorAttack:0.002 compressorRelease:0.02 postgain:1.5 ]", + "[ 1/1 → 5/4 | s:hh compressor:-20 compressorRatio:20 compressorKnee:10 compressorAttack:0.002 compressorRelease:0.02 postgain:1.5 ]", + "[ 1/1 → 3/2 | s:bd compressor:-20 compressorRatio:20 compressorKnee:10 compressorAttack:0.002 compressorRelease:0.02 postgain:1.5 ]", + "[ 5/4 → 3/2 | s:hh compressor:-20 compressorRatio:20 compressorKnee:10 compressorAttack:0.002 compressorRelease:0.02 postgain:1.5 ]", + "[ 3/2 → 7/4 | s:hh compressor:-20 compressorRatio:20 compressorKnee:10 compressorAttack:0.002 compressorRelease:0.02 postgain:1.5 ]", + "[ 3/2 → 2/1 | s:sd compressor:-20 compressorRatio:20 compressorKnee:10 compressorAttack:0.002 compressorRelease:0.02 postgain:1.5 ]", + "[ 7/4 → 2/1 | s:hh compressor:-20 compressorRatio:20 compressorKnee:10 compressorAttack:0.002 compressorRelease:0.02 postgain:1.5 ]", + "[ 2/1 → 9/4 | s:hh compressor:-20 compressorRatio:20 compressorKnee:10 compressorAttack:0.002 compressorRelease:0.02 postgain:1.5 ]", + "[ 2/1 → 5/2 | s:bd compressor:-20 compressorRatio:20 compressorKnee:10 compressorAttack:0.002 compressorRelease:0.02 postgain:1.5 ]", + "[ 9/4 → 5/2 | s:hh compressor:-20 compressorRatio:20 compressorKnee:10 compressorAttack:0.002 compressorRelease:0.02 postgain:1.5 ]", + "[ 5/2 → 11/4 | s:hh compressor:-20 compressorRatio:20 compressorKnee:10 compressorAttack:0.002 compressorRelease:0.02 postgain:1.5 ]", + "[ 5/2 → 3/1 | s:sd compressor:-20 compressorRatio:20 compressorKnee:10 compressorAttack:0.002 compressorRelease:0.02 postgain:1.5 ]", + "[ 11/4 → 3/1 | s:hh compressor:-20 compressorRatio:20 compressorKnee:10 compressorAttack:0.002 compressorRelease:0.02 postgain:1.5 ]", + "[ 3/1 → 13/4 | s:hh compressor:-20 compressorRatio:20 compressorKnee:10 compressorAttack:0.002 compressorRelease:0.02 postgain:1.5 ]", + "[ 3/1 → 7/2 | s:bd compressor:-20 compressorRatio:20 compressorKnee:10 compressorAttack:0.002 compressorRelease:0.02 postgain:1.5 ]", + "[ 13/4 → 7/2 | s:hh compressor:-20 compressorRatio:20 compressorKnee:10 compressorAttack:0.002 compressorRelease:0.02 postgain:1.5 ]", + "[ 7/2 → 15/4 | s:hh compressor:-20 compressorRatio:20 compressorKnee:10 compressorAttack:0.002 compressorRelease:0.02 postgain:1.5 ]", + "[ 7/2 → 4/1 | s:sd compressor:-20 compressorRatio:20 compressorKnee:10 compressorAttack:0.002 compressorRelease:0.02 postgain:1.5 ]", + "[ 15/4 → 4/1 | s:hh compressor:-20 compressorRatio:20 compressorKnee:10 compressorAttack:0.002 compressorRelease:0.02 postgain:1.5 ]", +] +`; + exports[`runs examples > example "press" example index 0 1`] = ` [ "[ 0/1 → 1/2 | s:hh ]", From f34937d4aef4a89497f5cffdb5ba1bcaaa288130 Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Mon, 9 Oct 2023 21:31:49 +0200 Subject: [PATCH 6/7] fix: roomsize not required --- packages/superdough/superdough.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/superdough/superdough.mjs b/packages/superdough/superdough.mjs index 410b7b96..9f11b983 100644 --- a/packages/superdough/superdough.mjs +++ b/packages/superdough/superdough.mjs @@ -382,7 +382,7 @@ export const superdough = async (value, deadline, hapDuration) => { } // reverb let reverbSend; - if (room > 0 && roomsize > 0) { + if (room > 0) { const reverbNode = getReverb(orbit, roomsize, roomfade, roomlp, roomdim); reverbSend = effectSend(post, reverbNode, room); } From 6544e8135cf8b40eaa751cd13fdabeb5baa489a1 Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Mon, 9 Oct 2023 21:40:38 +0200 Subject: [PATCH 7/7] fix: reverb sampleRate --- packages/superdough/reverb.mjs | 4 +--- packages/superdough/reverbGen.mjs | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/superdough/reverb.mjs b/packages/superdough/reverb.mjs index 3d54203c..ff4cb78a 100644 --- a/packages/superdough/reverb.mjs +++ b/packages/superdough/reverb.mjs @@ -1,14 +1,12 @@ import reverbGen from './reverbGen.mjs'; if (typeof AudioContext !== 'undefined') { - AudioContext.prototype.generateReverb = reverbGen.generateReverb; AudioContext.prototype.createReverb = function (duration, fade, lp, dim) { const convolver = this.createConvolver(); convolver.generate = (d = 2, fade = 0.1, lp = 15000, dim = 1000) => { - this.generateReverb( + reverbGen.generateReverb( { audioContext: this, - sampleRate: 44100, numChannels: 2, decayTime: d, fadeInTime: fade, diff --git a/packages/superdough/reverbGen.mjs b/packages/superdough/reverbGen.mjs index 49429937..eed63792 100644 --- a/packages/superdough/reverbGen.mjs +++ b/packages/superdough/reverbGen.mjs @@ -23,7 +23,7 @@ var reverbGen = {}; immediately within the current execution context, or later. */ reverbGen.generateReverb = function (params, callback) { var audioContext = params.audioContext || new AudioContext(); - var sampleRate = params.sampleRate || 44100; + var sampleRate = audioContext.sampleRate; var numChannels = params.numChannels || 2; // params.decayTime is the -60dB fade time. We let it go 50% longer to get to -90dB. var totalTime = params.decayTime * 1.5;