From 08aab9d4d80099d4330549ee732c0ba9ec701297 Mon Sep 17 00:00:00 2001 From: Raphael Forment Date: Wed, 20 Sep 2023 19:44:32 +0200 Subject: [PATCH 1/5] Adding vibrato to Superdough sampler Modulating the `playbackRate` to simulate a vibrato! --- packages/superdough/sampler.mjs | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/packages/superdough/sampler.mjs b/packages/superdough/sampler.mjs index 76b6a542c..365d397c2 100644 --- a/packages/superdough/sampler.mjs +++ b/packages/superdough/sampler.mjs @@ -22,7 +22,7 @@ function humanFileSize(bytes, si) { return bytes.toFixed(1) + ' ' + units[u]; } -export const getSampleBufferSource = async (s, n, note, speed, freq, bank, resolveUrl) => { +export const getSampleBufferSource = async (s, n, note, speed, freq, vib, vibmod, bank, resolveUrl) => { let transpose = 0; if (freq !== undefined && note !== undefined) { logger('[sampler] hap has note and freq. ignoring note', 'warning'); @@ -57,8 +57,20 @@ export const getSampleBufferSource = async (s, n, note, speed, freq, bank, resol const bufferSource = ac.createBufferSource(); bufferSource.buffer = buffer; const playbackRate = 1.0 * Math.pow(2, transpose / 12); - // bufferSource.playbackRate.value = Math.pow(2, transpose / 12); - bufferSource.playbackRate.value = playbackRate; + if (vib > 0) { + let vibrato_oscillator = getAudioContext().createOscillator(); + vibrato_oscillator.frequency.value = vib; + const gain = getAudioContext().createGain(); + // Vibmod is the amount of vibrato, in semitones + bufferSource.playbackRate.value = Math.pow(2, transpose / 12); + gain.gain.value = vibmod / 4; + vibrato_oscillator.connect(gain); + gain.connect(bufferSource.playbackRate); + vibrato_oscillator.start(0); + } else { + bufferSource.playbackRate.value = Math.pow(2, transpose / 12); + bufferSource.playbackRate.value = playbackRate; + } return bufferSource; }; @@ -211,6 +223,8 @@ export async function onTriggerSample(t, value, onended, bank, resolveUrl) { begin = 0, loopEnd = 1, end = 1, + vib, + vibmod = 0.5, } = value; // load sample if (speed === 0) { @@ -224,7 +238,7 @@ export async function onTriggerSample(t, value, onended, bank, resolveUrl) { //const soundfont = getSoundfontKey(s); const time = t + nudge; - const bufferSource = await getSampleBufferSource(s, n, note, speed, freq, bank, resolveUrl); + const bufferSource = await getSampleBufferSource(s, n, note, speed, freq, vib, vibmod, bank, resolveUrl); // asny stuff above took too long? if (ac.currentTime > t) { @@ -255,7 +269,7 @@ export async function onTriggerSample(t, value, onended, bank, resolveUrl) { bufferSource.connect(envelope); const out = ac.createGain(); // we need a separate gain for the cutgroups because firefox... envelope.connect(out); - bufferSource.onended = function () { + bufferSource.onended = function() { bufferSource.disconnect(); envelope.disconnect(); out.disconnect(); From 85835087ba0c55ac6e028de6c76812c20bb26018 Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Thu, 9 Nov 2023 08:48:23 +0100 Subject: [PATCH 2/5] format --- packages/superdough/sampler.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/superdough/sampler.mjs b/packages/superdough/sampler.mjs index ed73eeb8a..d278913a3 100644 --- a/packages/superdough/sampler.mjs +++ b/packages/superdough/sampler.mjs @@ -298,7 +298,7 @@ export async function onTriggerSample(t, value, onended, bank, resolveUrl) { bufferSource.connect(envelope); const out = ac.createGain(); // we need a separate gain for the cutgroups because firefox... envelope.connect(out); - bufferSource.onended = function() { + bufferSource.onended = function () { bufferSource.disconnect(); envelope.disconnect(); out.disconnect(); From 7c8a8b8b7044b8a3e422717bd6a928486940dbb3 Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Thu, 9 Nov 2023 08:59:23 +0100 Subject: [PATCH 3/5] simplify --- packages/superdough/sampler.mjs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/superdough/sampler.mjs b/packages/superdough/sampler.mjs index d278913a3..7127d891a 100644 --- a/packages/superdough/sampler.mjs +++ b/packages/superdough/sampler.mjs @@ -57,19 +57,16 @@ export const getSampleBufferSource = async (s, n, note, speed, freq, vib, vibmod const bufferSource = ac.createBufferSource(); bufferSource.buffer = buffer; const playbackRate = 1.0 * Math.pow(2, transpose / 12); + bufferSource.playbackRate.value = playbackRate; if (vib > 0) { let vibrato_oscillator = getAudioContext().createOscillator(); vibrato_oscillator.frequency.value = vib; const gain = getAudioContext().createGain(); // Vibmod is the amount of vibrato, in semitones - bufferSource.playbackRate.value = Math.pow(2, transpose / 12); gain.gain.value = vibmod / 4; vibrato_oscillator.connect(gain); gain.connect(bufferSource.playbackRate); vibrato_oscillator.start(0); - } else { - bufferSource.playbackRate.value = Math.pow(2, transpose / 12); - bufferSource.playbackRate.value = playbackRate; } return bufferSource; }; From 0052d349d925275e5f14d89bf49e01c4629b952f Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Thu, 9 Nov 2023 09:06:50 +0100 Subject: [PATCH 4/5] refactor: move vibrato up + cleanup oscillator --- packages/superdough/sampler.mjs | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/packages/superdough/sampler.mjs b/packages/superdough/sampler.mjs index 7127d891a..6da8b1d12 100644 --- a/packages/superdough/sampler.mjs +++ b/packages/superdough/sampler.mjs @@ -22,7 +22,7 @@ function humanFileSize(bytes, si) { return bytes.toFixed(1) + ' ' + units[u]; } -export const getSampleBufferSource = async (s, n, note, speed, freq, vib, vibmod, bank, resolveUrl) => { +export const getSampleBufferSource = async (s, n, note, speed, freq, bank, resolveUrl) => { let transpose = 0; if (freq !== undefined && note !== undefined) { logger('[sampler] hap has note and freq. ignoring note', 'warning'); @@ -58,16 +58,6 @@ export const getSampleBufferSource = async (s, n, note, speed, freq, vib, vibmod bufferSource.buffer = buffer; const playbackRate = 1.0 * Math.pow(2, transpose / 12); bufferSource.playbackRate.value = playbackRate; - if (vib > 0) { - let vibrato_oscillator = getAudioContext().createOscillator(); - vibrato_oscillator.frequency.value = vib; - const gain = getAudioContext().createGain(); - // Vibmod is the amount of vibrato, in semitones - gain.gain.value = vibmod / 4; - vibrato_oscillator.connect(gain); - gain.connect(bufferSource.playbackRate); - vibrato_oscillator.start(0); - } return bufferSource; }; @@ -264,7 +254,20 @@ export async function onTriggerSample(t, value, onended, bank, resolveUrl) { //const soundfont = getSoundfontKey(s); const time = t + nudge; - const bufferSource = await getSampleBufferSource(s, n, note, speed, freq, vib, vibmod, bank, resolveUrl); + const bufferSource = await getSampleBufferSource(s, n, note, speed, freq, bank, resolveUrl); + + // vibrato + let vibratoOscillator; + if (vib > 0) { + vibratoOscillator = getAudioContext().createOscillator(); + vibratoOscillator.frequency.value = vib; + const gain = getAudioContext().createGain(); + // Vibmod is the amount of vibrato, in semitones + gain.gain.value = vibmod * 100; + vibratoOscillator.connect(gain); + gain.connect(bufferSource.detune); + vibratoOscillator.start(0); + } // asny stuff above took too long? if (ac.currentTime > t) { @@ -297,6 +300,7 @@ export async function onTriggerSample(t, value, onended, bank, resolveUrl) { envelope.connect(out); bufferSource.onended = function () { bufferSource.disconnect(); + vibratoOscillator.stop(); envelope.disconnect(); out.disconnect(); onended(); From 2a09f9ef0b51a8006efd745275eb48ac128516ba Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Thu, 9 Nov 2023 09:21:40 +0100 Subject: [PATCH 5/5] fix: sampler broke without vibrato --- packages/superdough/sampler.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/superdough/sampler.mjs b/packages/superdough/sampler.mjs index 6da8b1d12..b8f10d5da 100644 --- a/packages/superdough/sampler.mjs +++ b/packages/superdough/sampler.mjs @@ -300,7 +300,7 @@ export async function onTriggerSample(t, value, onended, bank, resolveUrl) { envelope.connect(out); bufferSource.onended = function () { bufferSource.disconnect(); - vibratoOscillator.stop(); + vibratoOscillator?.stop(); envelope.disconnect(); out.disconnect(); onended();