diff --git a/packages/superdough/superdough.mjs b/packages/superdough/superdough.mjs index 5488b404..f0475d77 100644 --- a/packages/superdough/superdough.mjs +++ b/packages/superdough/superdough.mjs @@ -83,42 +83,49 @@ export const getAudioContext = () => { if (!audioContext) { return setDefaultAudioContext(); } + return audioContext; }; let workletsLoading; - function loadWorklets() { - if (workletsLoading) { - return workletsLoading; + if (!workletsLoading) { + workletsLoading = getAudioContext().audioWorklet.addModule(workletsUrl); } - workletsLoading = getAudioContext().audioWorklet.addModule(workletsUrl); return workletsLoading; } // this function should be called on first user interaction (to avoid console warning) export async function initAudio(options = {}) { const { disableWorklets = false } = options; - if (typeof window !== 'undefined') { - await getAudioContext().resume(); - if (!disableWorklets) { - await loadWorklets().catch((err) => { - console.warn('could not load AudioWorklet effects coarse, crush and shape', err); - }); - } else { - console.log('disableWorklets: AudioWorklet effects coarse, crush and shape are skipped!'); - } + if (typeof window === 'undefined') { + return; } + await getAudioContext().resume(); + if (disableWorklets) { + logger('[superdough]: AudioWorklets disabled with disableWorklets'); + return; + } + try { + await loadWorklets(); + logger('[superdough] AudioWorklets loaded'); + } catch (err) { + console.warn('could not load AudioWorklet effects', err); + } + logger('[superdough] ready'); } - +let audioReady; export async function initAudioOnFirstClick(options) { - return new Promise((resolve) => { - document.addEventListener('click', async function listener() { - await initAudio(options); - resolve(); - document.removeEventListener('click', listener); + if (!audioReady) { + audioReady = new Promise((resolve) => { + document.addEventListener('click', async function listener() { + document.removeEventListener('click', listener); + await initAudio(options); + resolve(); + }); }); - }); + } + return audioReady; } let delays = {}; diff --git a/website/src/repl/Repl.jsx b/website/src/repl/Repl.jsx index a22089bb..7ce3c61e 100644 --- a/website/src/repl/Repl.jsx +++ b/website/src/repl/Repl.jsx @@ -10,10 +10,10 @@ import cx from '@src/cx.mjs'; import { transpiler } from '@strudel/transpiler'; import { getAudioContext, - initAudioOnFirstClick, webaudioOutput, resetGlobalEffects, resetLoadedSounds, + initAudioOnFirstClick, } from '@strudel/webaudio'; import { defaultAudioDeviceName } from '../settings.mjs'; import { getAudioDevices, setAudioDevice } from './util.mjs'; @@ -42,9 +42,10 @@ import { getMetadata } from '../metadata_parser'; const { latestCode } = settingsMap.get(); -let modulesLoading, presets, drawContext, clearCanvas, isIframe; +let modulesLoading, presets, drawContext, clearCanvas, isIframe, audioReady; + if (typeof window !== 'undefined') { - initAudioOnFirstClick(); + audioReady = initAudioOnFirstClick(); modulesLoading = loadModules(); presets = prebake(); drawContext = getDrawContext(); @@ -88,6 +89,7 @@ export function Repl({ embedded = false }) { clearHydra(); } }, + beforeEval: () => audioReady, afterEval: (all) => { const { code } = all; setLatestCode(code);