create release audio param method, make volume envelopes consistant

This commit is contained in:
Jade (Rose) Rowland 2023-12-20 00:21:14 -05:00
parent fe60f34015
commit d7fae2620e
2 changed files with 28 additions and 16 deletions

View File

@ -1,6 +1,27 @@
import { getAudioContext } from './superdough.mjs'; import { getAudioContext } from './superdough.mjs';
import { clamp } from './util.mjs'; import { clamp } from './util.mjs';
AudioParam.prototype.setRelease = function (startTime, endTime, endValue, curve = 'linear') {
const ctx = getAudioContext();
const ramp = curve === 'exponential' ? 'exponentialRampToValueAtTime' : 'linearRampToValueAtTime';
const param = this;
if (AudioParam.prototype.cancelAndHoldAtTime == null) {
//this replicates cancelAndHoldAtTime behavior for Firefox
setTimeout(() => {
//sustain at current value
const currValue = param.value;
param.cancelScheduledValues(0);
param.setValueAtTime(currValue, 0);
//release
param[ramp](endValue, endTime);
}, (startTime - ctx.currentTime) * 1000);
} else {
param.cancelAndHoldAtTime(startTime);
//release
param[ramp](endValue, endTime);
}
};
export function gainNode(value) { export function gainNode(value) {
const node = getAudioContext().createGain(); const node = getAudioContext().createGain();
node.gain.value = value; node.gain.value = value;
@ -21,13 +42,10 @@ export const getEnvelope = (attack, decay, sustain, release, velocity, begin) =>
return { return {
node: gainNode, node: gainNode,
stop: (t) => { stop: (t) => {
// to make sure the release won't begin before sustain is reached const endTime = t + release;
phase = Math.max(t, phase); gainNode.gain.setRelease(t, endTime, 0);
// see https://github.com/tidalcycles/strudel/issues/522 // helps prevent pops from overlapping sounds
gainNode.gain.setValueAtTime(sustainLevel, phase); return endTime - 0.01;
phase += release;
gainNode.gain.linearRampToValueAtTime(0, phase); // release
return phase;
}, },
}; };
}; };
@ -97,14 +115,8 @@ export const getParamADSR = (
const sustainLevel = min + sustain * range; const sustainLevel = min + sustain * range;
//decay //decay
param[ramp](sustainLevel, phase); param[ramp](sustainLevel, phase);
//this timeout can be replaced with cancelAndHoldAtTime once it is implemented in Firefox phase += Math.max(release, 0.1);
setTimeout(() => { param.setRelease(end, phase, min, curve);
//sustain at current value
param.cancelScheduledValues(0);
phase += Math.max(release, 0.1);
//release
param[ramp](min, phase);
}, (end - context.currentTime) * 1000);
}; };
export function getCompressor(ac, threshold, ratio, knee, attack, release) { export function getCompressor(ac, threshold, ratio, knee, attack, release) {

View File

@ -42,7 +42,7 @@ export function registerSynthSounds() {
let { density } = value; let { density } = value;
sound = getNoiseOscillator(s, t, density); sound = getNoiseOscillator(s, t, density);
} }
console.log(sound);
let { node: o, stop, triggerRelease } = sound; let { node: o, stop, triggerRelease } = sound;
// turn down // turn down