[perf] release unused AudioBufferSourceNode + releaseAudioNode
This commit is contained in:
parent
7a3e0fd3fe
commit
68b1cb87ca
5 changed files with 48 additions and 26 deletions
|
|
@ -554,10 +554,33 @@ export const getFrequencyFromValue = (value, defaultNote = 36) => {
|
|||
return Number(freq);
|
||||
};
|
||||
|
||||
export const destroyAudioWorkletNode = (node) => {
|
||||
if (node == null) {
|
||||
return;
|
||||
export const releaseAudioNode = (node) => {
|
||||
// check we received an AudioNode
|
||||
if (!(node instanceof AudioNode)) {
|
||||
throw new Error('releaseAudioNode can only release an AudioNode');
|
||||
}
|
||||
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/AudioNode/disconnect
|
||||
node.disconnect();
|
||||
node.parameters.get('end')?.setValueAtTime(0, 0);
|
||||
|
||||
// make sure all AudioScheduledSourceNode is in a stopped state
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/AudioScheduledSourceNode
|
||||
if (node instanceof AudioScheduledSourceNode) {
|
||||
try {
|
||||
node.stop();
|
||||
} catch (e) {
|
||||
if (e instanceof DOMException && e.name === 'InvalidStateError') {
|
||||
node.start(node.context.currentTime + 5); // will never happen
|
||||
node.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// https://www.w3.org/TR/webaudio-1.1/#AudioNode-actively-processing
|
||||
// An AudioWorkletNode is actively processing when its AudioWorkletProcessor's [[callable process]]
|
||||
// returns true and either its active source flag is true or
|
||||
// any AudioNode connected to one of its inputs is actively processing.
|
||||
if (node instanceof AudioWorkletNode) {
|
||||
node.parameters.get('end')?.setValueAtTime(0, 0);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { getBaseURL, getCommonSampleInfo } from './util.mjs';
|
||||
import { registerSound, registerWaveTable } from './index.mjs';
|
||||
import { getAudioContext } from './audioContext.mjs';
|
||||
import { getADSRValues, getParamADSR, getPitchEnvelope, getVibratoOscillator } from './helpers.mjs';
|
||||
import { getADSRValues, getParamADSR, getPitchEnvelope, getVibratoOscillator, releaseAudioNode } from './helpers.mjs';
|
||||
import { logger } from './logger.mjs';
|
||||
|
||||
const bufferCache = {}; // string: Promise<ArrayBuffer>
|
||||
|
|
@ -286,17 +286,19 @@ export async function onTriggerSample(t, value, onended, bank, resolveUrl) {
|
|||
|
||||
const { bufferSource, sliceDuration, offset } = await getSampleBufferSource(value, bank, resolveUrl);
|
||||
|
||||
// asny stuff above took too long?
|
||||
if (ac.currentTime > t) {
|
||||
logger(`[sampler] still loading sound "${s}:${n}"`, 'highlight');
|
||||
// console.warn('sample still loading:', s, n);
|
||||
return;
|
||||
}
|
||||
if (!bufferSource) {
|
||||
logger(`[sampler] could not load "${s}:${n}"`, 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
// async stuff above took too long?
|
||||
if (ac.currentTime > t) {
|
||||
logger(`[sampler] loading sound "${s}:${n}" took too long`, 'highlight');
|
||||
// AudioBufferSourceNode will never be used. discard it
|
||||
releaseAudioNode(bufferSource);
|
||||
return;
|
||||
}
|
||||
|
||||
// vibrato
|
||||
let vibratoOscillator = getVibratoOscillator(bufferSource.detune, value, t);
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ import { registerSound, soundMap } from './superdough.mjs';
|
|||
import { getAudioContext } from './audioContext.mjs';
|
||||
import {
|
||||
applyFM,
|
||||
destroyAudioWorkletNode,
|
||||
gainNode,
|
||||
getADSRValues,
|
||||
getFrequencyFromValue,
|
||||
|
|
@ -13,6 +12,7 @@ import {
|
|||
getVibratoOscillator,
|
||||
getWorklet,
|
||||
noises,
|
||||
releaseAudioNode,
|
||||
webAudioTimeout,
|
||||
} from './helpers.mjs';
|
||||
import { logger } from './logger.mjs';
|
||||
|
|
@ -192,8 +192,7 @@ export function registerSynthSounds() {
|
|||
let timeoutNode = webAudioTimeout(
|
||||
ac,
|
||||
() => {
|
||||
destroyAudioWorkletNode(o);
|
||||
envGain.disconnect();
|
||||
releaseAudioNode(o);
|
||||
onended();
|
||||
fm?.stop();
|
||||
vibratoOscillator?.stop();
|
||||
|
|
@ -270,8 +269,7 @@ export function registerSynthSounds() {
|
|||
let timeoutNode = webAudioTimeout(
|
||||
ac,
|
||||
() => {
|
||||
destroyAudioWorkletNode(o);
|
||||
envGain.disconnect();
|
||||
releaseAudioNode(o);
|
||||
onended();
|
||||
},
|
||||
begin,
|
||||
|
|
@ -344,9 +342,8 @@ export function registerSynthSounds() {
|
|||
let timeoutNode = webAudioTimeout(
|
||||
ac,
|
||||
() => {
|
||||
destroyAudioWorkletNode(o);
|
||||
destroyAudioWorkletNode(lfo);
|
||||
envGain.disconnect();
|
||||
releaseAudioNode(o);
|
||||
lfo && releaseAudioNode(lfo);
|
||||
onended();
|
||||
fm?.stop();
|
||||
vibratoOscillator?.stop();
|
||||
|
|
|
|||
|
|
@ -3,13 +3,13 @@ import { getBaseURL, getCommonSampleInfo } from './util.mjs';
|
|||
import {
|
||||
applyFM,
|
||||
applyParameterModulators,
|
||||
destroyAudioWorkletNode,
|
||||
getADSRValues,
|
||||
getFrequencyFromValue,
|
||||
getParamADSR,
|
||||
getPitchEnvelope,
|
||||
getVibratoOscillator,
|
||||
getWorklet,
|
||||
releaseAudioNode,
|
||||
webAudioTimeout,
|
||||
} from './helpers.mjs';
|
||||
import { logger } from './logger.mjs';
|
||||
|
|
@ -319,10 +319,9 @@ export async function onTriggerSynth(t, value, onended, tables, cps, frameLen) {
|
|||
const timeoutNode = webAudioTimeout(
|
||||
ac,
|
||||
() => {
|
||||
destroyAudioWorkletNode(source);
|
||||
releaseAudioNode(source);
|
||||
vibratoOscillator?.stop();
|
||||
fm?.stop();
|
||||
node.disconnect();
|
||||
wtPosModulators?.disconnect();
|
||||
wtWarpModulators?.disconnect();
|
||||
onended();
|
||||
|
|
|
|||
|
|
@ -508,13 +508,14 @@ class SuperSawOscillatorProcessor extends AudioWorkletProcessor {
|
|||
];
|
||||
}
|
||||
process(_input, outputs, params) {
|
||||
if (currentTime <= params.begin[0]) {
|
||||
return true;
|
||||
}
|
||||
if (currentTime >= params.end[0]) {
|
||||
// this.port.postMessage({ type: 'onended' });
|
||||
// should terminate
|
||||
return false;
|
||||
}
|
||||
if (currentTime <= params.begin[0]) {
|
||||
// keep alive
|
||||
return true;
|
||||
}
|
||||
const output = outputs[0];
|
||||
const voices = params.voices[0]; // k-rate
|
||||
for (let i = 0; i < output[0].length; i++) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue