Merge pull request '[perf] propagate onceEnded and releaseAudioNode' (#1809) from jeromew/strudel:fix-perf12 into main
Reviewed-on: https://codeberg.org/uzu/strudel/pulls/1809 Reviewed-by: Aria <glossing@noreply.codeberg.org>
This commit is contained in:
commit
765de9daf3
7 changed files with 58 additions and 39 deletions
|
|
@ -7,6 +7,7 @@ import {
|
||||||
getPitchEnvelope,
|
getPitchEnvelope,
|
||||||
getVibratoOscillator,
|
getVibratoOscillator,
|
||||||
onceEnded,
|
onceEnded,
|
||||||
|
releaseAudioNode,
|
||||||
} from '@strudel/webaudio';
|
} from '@strudel/webaudio';
|
||||||
import gm from './gm.mjs';
|
import gm from './gm.mjs';
|
||||||
|
|
||||||
|
|
@ -172,9 +173,8 @@ export function registerSoundfonts() {
|
||||||
bufferSource.stop(envEnd);
|
bufferSource.stop(envEnd);
|
||||||
const stop = (releaseTime) => {};
|
const stop = (releaseTime) => {};
|
||||||
onceEnded(bufferSource, () => {
|
onceEnded(bufferSource, () => {
|
||||||
bufferSource.disconnect();
|
releaseAudioNode(bufferSource);
|
||||||
vibratoOscillator?.stop();
|
releaseAudioNode(vibratoOscillator);
|
||||||
node.disconnect();
|
|
||||||
onended();
|
onended();
|
||||||
});
|
});
|
||||||
return { node, stop };
|
return { node, stop };
|
||||||
|
|
|
||||||
|
|
@ -189,7 +189,7 @@ export function applyParameterModulators(audioContext, param, start, end, envelo
|
||||||
getParamADSR(param, attack, decay, sustain, release, min, max, start, holdEnd, curve);
|
getParamADSR(param, attack, decay, sustain, release, min, max, start, holdEnd, curve);
|
||||||
}
|
}
|
||||||
const lfo = getParamLfo(audioContext, param, start, end, lfoValues);
|
const lfo = getParamLfo(audioContext, param, start, end, lfoValues);
|
||||||
return { lfo, disconnect: () => lfo?.disconnect() };
|
return lfo;
|
||||||
}
|
}
|
||||||
export function createFilter(context, start, end, params, cps, cycle) {
|
export function createFilter(context, start, end, params, cps, cycle) {
|
||||||
let {
|
let {
|
||||||
|
|
@ -283,9 +283,12 @@ export function drywet(dry, wet, wetAmount = 0) {
|
||||||
wet_gain.connect(mix);
|
wet_gain.connect(mix);
|
||||||
return {
|
return {
|
||||||
node: mix,
|
node: mix,
|
||||||
onended: () => {
|
teardown: () => {
|
||||||
dry_gain.disconnect(mix);
|
releaseAudioNode(dry_gain);
|
||||||
wet_gain.disconnect(mix);
|
releaseAudioNode(wet_gain);
|
||||||
|
// it is not the responsability of drywet
|
||||||
|
// to call `releaseAudioNode` on
|
||||||
|
// the 2 external args dry and wet
|
||||||
dry.disconnect(dry_gain);
|
dry.disconnect(dry_gain);
|
||||||
wet.disconnect(wet_gain);
|
wet.disconnect(wet_gain);
|
||||||
},
|
},
|
||||||
|
|
@ -324,10 +327,10 @@ export function getVibratoOscillator(param, value, t) {
|
||||||
gain.gain.value = vibmod * 100;
|
gain.gain.value = vibmod * 100;
|
||||||
vibratoOscillator.connect(gain);
|
vibratoOscillator.connect(gain);
|
||||||
gain.connect(param);
|
gain.connect(param);
|
||||||
vibratoOscillator.onended = () => {
|
onceEnded(vibratoOscillator, () => {
|
||||||
gain.disconnect(param);
|
releaseAudioNode(gain);
|
||||||
vibratoOscillator.disconnect(gain);
|
releaseAudioNode(vibratoOscillator);
|
||||||
};
|
});
|
||||||
vibratoOscillator.start(t);
|
vibratoOscillator.start(t);
|
||||||
return vibratoOscillator;
|
return vibratoOscillator;
|
||||||
}
|
}
|
||||||
|
|
@ -613,6 +616,8 @@ export const releaseAudioNode = (node) => {
|
||||||
// returns true and either its active source flag is true or
|
// returns true and either its active source flag is true or
|
||||||
// any AudioNode connected to one of its inputs is actively processing.
|
// any AudioNode connected to one of its inputs is actively processing.
|
||||||
if (node instanceof AudioWorkletNode) {
|
if (node instanceof AudioWorkletNode) {
|
||||||
|
// while `end` is not native to the web audio API, it is common practice in superdough
|
||||||
|
// to use that param in the worklets to trigger returning false from the processor
|
||||||
node.parameters.get('end')?.setValueAtTime(0, 0);
|
node.parameters.get('end')?.setValueAtTime(0, 0);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { drywet } from './helpers.mjs';
|
import { drywet, onceEnded, releaseAudioNode } from './helpers.mjs';
|
||||||
import { getAudioContext } from './audioContext.mjs';
|
import { getAudioContext } from './audioContext.mjs';
|
||||||
|
|
||||||
let noiseCache = {};
|
let noiseCache = {};
|
||||||
|
|
@ -65,9 +65,12 @@ export function getNoiseOscillator(type = 'white', t, density = 0.02) {
|
||||||
export function getNoiseMix(inputNode, wet, t) {
|
export function getNoiseMix(inputNode, wet, t) {
|
||||||
const noiseOscillator = getNoiseOscillator('pink', t);
|
const noiseOscillator = getNoiseOscillator('pink', t);
|
||||||
const noiseMix = drywet(inputNode, noiseOscillator.node, wet);
|
const noiseMix = drywet(inputNode, noiseOscillator.node, wet);
|
||||||
noiseOscillator.node.onended = () => noiseMix.onended();
|
onceEnded(noiseOscillator.node, () => {
|
||||||
|
releaseAudioNode(noiseOscillator.node);
|
||||||
|
});
|
||||||
return {
|
return {
|
||||||
node: noiseMix.node,
|
node: noiseMix.node,
|
||||||
stop: (time) => noiseOscillator?.stop(time),
|
stop: (time) => noiseOscillator?.stop(time),
|
||||||
|
teardown: noiseMix.teardown,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -323,10 +323,10 @@ export async function onTriggerSample(t, value, onended, bank, resolveUrl) {
|
||||||
const out = ac.createGain(); // we need a separate gain for the cutgroups because firefox...
|
const out = ac.createGain(); // we need a separate gain for the cutgroups because firefox...
|
||||||
node.connect(out);
|
node.connect(out);
|
||||||
onceEnded(bufferSource, function () {
|
onceEnded(bufferSource, function () {
|
||||||
bufferSource.disconnect();
|
releaseAudioNode(bufferSource);
|
||||||
vibratoOscillator?.stop();
|
releaseAudioNode(vibratoOscillator);
|
||||||
node.disconnect();
|
releaseAudioNode(node);
|
||||||
out.disconnect();
|
releaseAudioNode(out);
|
||||||
onended();
|
onended();
|
||||||
});
|
});
|
||||||
let envEnd = holdEnd + release + 0.01;
|
let envEnd = holdEnd + release + 0.01;
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,16 @@ import './reverb.mjs';
|
||||||
import './vowel.mjs';
|
import './vowel.mjs';
|
||||||
import { nanFallback, _mod, cycleToSeconds, pickAndRename } from './util.mjs';
|
import { nanFallback, _mod, cycleToSeconds, pickAndRename } from './util.mjs';
|
||||||
import workletsUrl from './worklets.mjs?audioworklet';
|
import workletsUrl from './worklets.mjs?audioworklet';
|
||||||
import { createFilter, gainNode, getCompressor, getDistortion, getLfo, getWorklet, effectSend } from './helpers.mjs';
|
import {
|
||||||
|
createFilter,
|
||||||
|
gainNode,
|
||||||
|
getCompressor,
|
||||||
|
getDistortion,
|
||||||
|
getLfo,
|
||||||
|
getWorklet,
|
||||||
|
effectSend,
|
||||||
|
releaseAudioNode,
|
||||||
|
} from './helpers.mjs';
|
||||||
import { map } from 'nanostores';
|
import { map } from 'nanostores';
|
||||||
import { logger } from './logger.mjs';
|
import { logger } from './logger.mjs';
|
||||||
import { loadBuffer } from './sampler.mjs';
|
import { loadBuffer } from './sampler.mjs';
|
||||||
|
|
@ -505,7 +514,7 @@ export const superdough = async (value, t, hapDuration, cps = 0.5, cycle = 0.5)
|
||||||
} else if (getSound(s)) {
|
} else if (getSound(s)) {
|
||||||
const { onTrigger } = getSound(s);
|
const { onTrigger } = getSound(s);
|
||||||
const onEnded = () => {
|
const onEnded = () => {
|
||||||
audioNodes.forEach((n) => n?.disconnect());
|
audioNodes.forEach((n) => releaseAudioNode(n));
|
||||||
activeSoundSources.delete(chainID);
|
activeSoundSources.delete(chainID);
|
||||||
};
|
};
|
||||||
const soundHandle = await onTrigger(t, value, onEnded, cps);
|
const soundHandle = await onTrigger(t, value, onEnded, cps);
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import {
|
||||||
getVibratoOscillator,
|
getVibratoOscillator,
|
||||||
getWorklet,
|
getWorklet,
|
||||||
noises,
|
noises,
|
||||||
|
onceEnded,
|
||||||
releaseAudioNode,
|
releaseAudioNode,
|
||||||
webAudioTimeout,
|
webAudioTimeout,
|
||||||
} from './helpers.mjs';
|
} from './helpers.mjs';
|
||||||
|
|
@ -52,7 +53,7 @@ export function registerSynthSounds() {
|
||||||
const g = gainNode(0.3);
|
const g = gainNode(0.3);
|
||||||
|
|
||||||
let sound = getOscillator(s, t, value, () => {
|
let sound = getOscillator(s, t, value, () => {
|
||||||
g.disconnect();
|
releaseAudioNode(g);
|
||||||
onended();
|
onended();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -110,15 +111,15 @@ export function registerSynthSounds() {
|
||||||
|
|
||||||
const mix = gainNode(mixGain);
|
const mix = gainNode(mixGain);
|
||||||
|
|
||||||
o.onended = () => {
|
onceEnded(o, () => {
|
||||||
o.disconnect();
|
releaseAudioNode(o);
|
||||||
g.disconnect();
|
releaseAudioNode(g);
|
||||||
sat.disconnect();
|
releaseAudioNode(sat);
|
||||||
noise.node.disconnect();
|
releaseAudioNode(noise.node);
|
||||||
noiseGain.disconnect();
|
releaseAudioNode(noiseGain);
|
||||||
mix.disconnect();
|
releaseAudioNode(mix);
|
||||||
onended();
|
onended();
|
||||||
};
|
});
|
||||||
|
|
||||||
const node = o.connect(sat).connect(g).connect(mix);
|
const node = o.connect(sat).connect(g).connect(mix);
|
||||||
noise.node.connect(noiseGain).connect(mix);
|
noise.node.connect(noiseGain).connect(mix);
|
||||||
|
|
@ -384,11 +385,11 @@ export function registerSynthSounds() {
|
||||||
|
|
||||||
const { duration } = value;
|
const { duration } = value;
|
||||||
|
|
||||||
o.onended = () => {
|
onceEnded(o, () => {
|
||||||
o.disconnect();
|
releaseAudioNode(o);
|
||||||
g.disconnect();
|
releaseAudioNode(g);
|
||||||
onended();
|
onended();
|
||||||
};
|
});
|
||||||
|
|
||||||
const envGain = gainNode(1);
|
const envGain = gainNode(1);
|
||||||
let node = o.connect(g).connect(envGain);
|
let node = o.connect(g).connect(envGain);
|
||||||
|
|
@ -489,11 +490,12 @@ export function getOscillator(s, t, value, onended) {
|
||||||
noiseMix = getNoiseMix(o, noise, t);
|
noiseMix = getNoiseMix(o, noise, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
o.onended = () => {
|
onceEnded(o, () => {
|
||||||
noiseMix || o.disconnect();
|
noiseMix?.teardown();
|
||||||
noiseMix?.node.disconnect();
|
releaseAudioNode(o);
|
||||||
|
releaseAudioNode(noiseMix?.node);
|
||||||
onended();
|
onended();
|
||||||
};
|
});
|
||||||
o.start(t);
|
o.start(t);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
|
||||||
|
|
@ -320,10 +320,10 @@ export async function onTriggerSynth(t, value, onended, tables, cps, frameLen) {
|
||||||
ac,
|
ac,
|
||||||
() => {
|
() => {
|
||||||
releaseAudioNode(source);
|
releaseAudioNode(source);
|
||||||
vibratoOscillator?.stop();
|
releaseAudioNode(vibratoOscillator);
|
||||||
fm?.stop();
|
fm?.stop();
|
||||||
wtPosModulators?.disconnect();
|
releaseAudioNode(wtPosModulators);
|
||||||
wtWarpModulators?.disconnect();
|
releaseAudioNode(wtWarpModulators);
|
||||||
onended();
|
onended();
|
||||||
},
|
},
|
||||||
t,
|
t,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue