Merge pull request #861 from tidalcycles/envelope-fix

fix: finally repair envelopes
This commit is contained in:
Felix Roos 2023-12-12 21:49:22 +01:00 committed by GitHub
commit 1d3f87a431
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 19 additions and 17 deletions

View File

@ -139,8 +139,8 @@ export function registerSoundfonts() {
const { node: envelope, stop: releaseEnvelope } = getEnvelope(attack, decay, sustain, release, 0.3, time); const { node: envelope, stop: releaseEnvelope } = getEnvelope(attack, decay, sustain, release, 0.3, time);
bufferSource.connect(envelope); bufferSource.connect(envelope);
const stop = (releaseTime) => { const stop = (releaseTime) => {
bufferSource.stop(releaseTime + release); const silentAt = releaseEnvelope(releaseTime);
releaseEnvelope(releaseTime); bufferSource.stop(silentAt);
}; };
bufferSource.onended = () => { bufferSource.onended = () => {
bufferSource.disconnect(); bufferSource.disconnect();

View File

@ -10,21 +10,24 @@ export function gainNode(value) {
// alternative to getADSR returning the gain node and a stop handle to trigger the release anytime in the future // alternative to getADSR returning the gain node and a stop handle to trigger the release anytime in the future
export const getEnvelope = (attack, decay, sustain, release, velocity, begin) => { export const getEnvelope = (attack, decay, sustain, release, velocity, begin) => {
const gainNode = getAudioContext().createGain(); const gainNode = getAudioContext().createGain();
let phase = begin;
gainNode.gain.setValueAtTime(0, begin); gainNode.gain.setValueAtTime(0, begin);
gainNode.gain.linearRampToValueAtTime(velocity, begin + attack); // attack phase += attack;
gainNode.gain.linearRampToValueAtTime(sustain * velocity, begin + attack + decay); // sustain start gainNode.gain.linearRampToValueAtTime(velocity, phase); // attack
phase += decay;
let sustainLevel = sustain * velocity;
gainNode.gain.linearRampToValueAtTime(sustainLevel, phase); // decay / sustain
// sustain end // sustain end
return { return {
node: gainNode, node: gainNode,
stop: (t) => { stop: (t) => {
//if (typeof gainNode.gain.cancelAndHoldAtTime === 'function') { // to make sure the release won't begin before sustain is reached
// gainNode.gain.cancelAndHoldAtTime(t); // this seems to release instantly.... phase = Math.max(t, phase);
// see https://discord.com/channels/779427371270275082/937365093082079272/1086053607360712735 // see https://github.com/tidalcycles/strudel/issues/522
//} else { gainNode.gain.setValueAtTime(sustainLevel, phase);
// firefox: this will glitch when the sustain has not been reached yet at the time of release phase += release;
gainNode.gain.setValueAtTime(sustain * velocity, t); gainNode.gain.linearRampToValueAtTime(0, phase); // release
//} return phase;
gainNode.gain.linearRampToValueAtTime(0, t + release);
}, },
}; };
}; };

View File

@ -312,8 +312,8 @@ export async function onTriggerSample(t, value, onended, bank, resolveUrl) {
const bufferDuration = bufferSource.buffer.duration / bufferSource.playbackRate.value; const bufferDuration = bufferSource.buffer.duration / bufferSource.playbackRate.value;
releaseTime = t + (end - begin) * bufferDuration; releaseTime = t + (end - begin) * bufferDuration;
} }
bufferSource.stop(releaseTime + release); const silentAt = releaseEnvelope(releaseTime);
releaseEnvelope(releaseTime); bufferSource.stop(silentAt);
}; };
const handle = { node: out, bufferSource, stop }; const handle = { node: out, bufferSource, stop };

View File

@ -56,10 +56,9 @@ export function registerSynthSounds() {
return { return {
node: o.connect(g).connect(envelope), node: o.connect(g).connect(envelope),
stop: (releaseTime) => { stop: (releaseTime) => {
releaseEnvelope(releaseTime); const silentAt = releaseEnvelope(releaseTime);
triggerRelease?.(releaseTime); triggerRelease?.(releaseTime);
let end = releaseTime + release; stop(silentAt);
stop(end);
}, },
}; };
}, },