delay as global send via orbit

This commit is contained in:
Felix Roos 2022-09-24 21:45:23 +02:00
parent f7e3f7d187
commit f76d03a0dc
2 changed files with 39 additions and 13 deletions

View File

@ -7,6 +7,7 @@ if (typeof DelayNode !== 'undefined') {
const feedbackGain = ac.createGain();
feedbackGain.gain.value = Math.min(Math.abs(feedback), 0.995);
this.feedback = feedbackGain.gain;
const delayGain = ac.createGain();
delayGain.gain.value = wet;

View File

@ -189,6 +189,27 @@ function gainNode(value) {
}
const cutGroups = [];
let delays = {};
function getDelay(orbit, delay, delaytime, delayfeedback, t) {
if (!delays[orbit]) {
const ac = getAudioContext();
const dly = ac.createFeedbackDelay(delay, delaytime, delayfeedback);
dly.start(t);
dly.connect(getDestination());
delays[orbit] = dly;
}
delays[orbit].delayTime.value !== delaytime && delays[orbit].delayTime.setValueAtTime(delaytime, t);
delays[orbit].feedback.value !== delayfeedback && delays[orbit].feedback.setValueAtTime(delayfeedback, t);
return delays[orbit];
}
function effectSend(input, effect, wet) {
const send = gainNode(wet);
input.connect(send);
send.connect(effect);
return send;
}
// export const webaudioOutput = async (t, hap, ct, cps) => {
export const webaudioOutput = async (hap, deadline, hapDuration) => {
try {
@ -228,12 +249,13 @@ export const webaudioOutput = async (hap, deadline, hapDuration) => {
end = 1,
vowel,
delay = 0,
delayfeedback = 0,
delaytime = 0,
delayfeedback = 0.5,
delaytime = 0.25,
unit,
nudge = 0, // TODO: is this in seconds?
cut,
loop,
orbit = 1,
} = hap.value;
const { velocity = 1 } = hap.context;
gain *= velocity; // legacy fix for velocity
@ -327,42 +349,45 @@ export const webaudioOutput = async (hap, deadline, hapDuration) => {
const adsr = getADSR(attack, decay, sustain, release, 1, t, t + duration);
chain.push(adsr);
}
// master out
const master = ac.createGain();
master.gain.value = gain;
chain.push(master);
// gain stage
chain.push(gainNode(gain));
// filters
cutoff !== undefined && chain.push(getFilter('lowpass', cutoff, resonance));
hcutoff !== undefined && chain.push(getFilter('highpass', hcutoff, hresonance));
bandf !== undefined && chain.push(getFilter('bandpass', bandf, bandq));
vowel !== undefined && chain.push(ac.createVowelFilter(vowel));
// effects
coarse !== undefined && chain.push(getWorklet(ac, 'coarse-processor', { coarse }));
crush !== undefined && chain.push(getWorklet(ac, 'crush-processor', { crush }));
shape !== undefined && chain.push(getWorklet(ac, 'shape-processor', { shape }));
// TODO delay / delaytime / delayfeedback
// panning
if (pan !== undefined) {
const panner = ac.createStereoPanner();
panner.pan.value = 2 * pan - 1;
chain.push(panner);
}
// last gain
const post = gainNode(1);
chain.push(post);
post.connect(getDestination());
// delay
let delaySend;
if (delay > 0 && delaytime > 0 && delayfeedback > 0) {
const dly = ac.createFeedbackDelay(delay, delaytime, delayfeedback);
dly.start(t);
post.connect(dly);
dly.connect(getDestination());
const delyNode = getDelay(orbit, 1, delaytime, delayfeedback, t);
delaySend = effectSend(post, delyNode, delay);
}
// connect chain elements together
chain.slice(1).reduce((last, current) => last.connect(current), chain[0]);
// disconnect all nodes when source node has ended:
chain[0].onended = () => chain.forEach((n) => n.disconnect());
chain[0].onended = () => chain.concat([delaySend]).forEach((n) => n?.disconnect());
} catch (e) {
console.warn('.out error:', e);
}