From 8be5e9d2ebf8088998f8996f93c7d9cf7aa47b5d Mon Sep 17 00:00:00 2001 From: "Jade (Rose) Rowland" Date: Thu, 30 May 2024 16:25:15 -0400 Subject: [PATCH 1/8] fixed --- packages/superdough/superdough.mjs | 24 ++++++++++++------------ website/src/repl/Repl.jsx | 11 ++++++++--- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/packages/superdough/superdough.mjs b/packages/superdough/superdough.mjs index 018caa9a..e50f6bb3 100644 --- a/packages/superdough/superdough.mjs +++ b/packages/superdough/superdough.mjs @@ -27,6 +27,7 @@ export function getSound(s) { export const resetLoadedSounds = () => soundMap.set({}); let audioContext; +export const isAudioInitialized = () => audioContext != null; export const setDefaultAudioContext = () => { audioContext = new AudioContext(); @@ -37,17 +38,12 @@ export const getAudioContext = () => { if (!audioContext) { return setDefaultAudioContext(); } + return audioContext; }; -let workletsLoading; - -function loadWorklets() { - if (workletsLoading) { - return workletsLoading; - } - workletsLoading = getAudioContext().audioWorklet.addModule(workletsUrl); - return workletsLoading; +export async function loadWorklets() { + return await getAudioContext().audioWorklet.addModule(workletsUrl); } // this function should be called on first user interaction (to avoid console warning) @@ -56,11 +52,15 @@ export async function initAudio(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); - }); + await loadWorklets() + .catch((err) => { + console.warn('could not load AudioWorklet effects', err); + }) + .finally(() => { + logger('audio worklets loaded'); + }); } else { - console.log('disableWorklets: AudioWorklet effects coarse, crush and shape are skipped!'); + logger('disableWorklets: AudioWorklet effects skipped!'); } } } diff --git a/website/src/repl/Repl.jsx b/website/src/repl/Repl.jsx index d709d058..2dedbd1c 100644 --- a/website/src/repl/Repl.jsx +++ b/website/src/repl/Repl.jsx @@ -10,10 +10,11 @@ import cx from '@src/cx.mjs'; import { transpiler } from '@strudel/transpiler'; import { getAudioContext, - initAudioOnFirstClick, + initAudio, webaudioOutput, resetGlobalEffects, resetLoadedSounds, + isAudioInitialized, } from '@strudel/webaudio'; import { defaultAudioDeviceName } from '../settings.mjs'; import { getAudioDevices, setAudioDevice } from './util.mjs'; @@ -44,7 +45,6 @@ const { latestCode } = settingsMap.get(); let modulesLoading, presets, drawContext, clearCanvas, isIframe; if (typeof window !== 'undefined') { - initAudioOnFirstClick(); modulesLoading = loadModules(); presets = prebake(); drawContext = getDrawContext(); @@ -83,11 +83,16 @@ export function Repl({ embedded = false }) { onUpdateState: (state) => { setReplState({ ...state }); }, - onToggle: (playing) => { + onToggle: async (playing) => { if (!playing) { clearHydra(); } }, + beforeEval: async () => { + if (!isAudioInitialized()) { + await initAudio(); + } + }, afterEval: (all) => { const { code } = all; setLatestCode(code); From c0c54c21e36d3a1332cb2c0d4861ea4595f905b4 Mon Sep 17 00:00:00 2001 From: "Jade (Rose) Rowland" Date: Thu, 30 May 2024 16:30:49 -0400 Subject: [PATCH 2/8] remove unessecary export --- packages/superdough/superdough.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/superdough/superdough.mjs b/packages/superdough/superdough.mjs index e50f6bb3..777735fe 100644 --- a/packages/superdough/superdough.mjs +++ b/packages/superdough/superdough.mjs @@ -42,7 +42,7 @@ export const getAudioContext = () => { return audioContext; }; -export async function loadWorklets() { +async function loadWorklets() { return await getAudioContext().audioWorklet.addModule(workletsUrl); } From af3d32a493bc0068d67132aaa3bf06ef95f910e5 Mon Sep 17 00:00:00 2001 From: "Jade (Rose) Rowland" Date: Thu, 30 May 2024 18:52:28 -0400 Subject: [PATCH 3/8] updated to return promise on first click --- packages/superdough/superdough.mjs | 17 ++++++++++------- website/src/repl/Repl.jsx | 13 ++++++------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/packages/superdough/superdough.mjs b/packages/superdough/superdough.mjs index 777735fe..c882659a 100644 --- a/packages/superdough/superdough.mjs +++ b/packages/superdough/superdough.mjs @@ -64,15 +64,18 @@ export async function initAudio(options = {}) { } } } - +let audioReady = false; 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() { + await initAudio(options); + resolve(); + document.removeEventListener('click', listener); + }); }); - }); + } + return audioReady; } let delays = {}; diff --git a/website/src/repl/Repl.jsx b/website/src/repl/Repl.jsx index 2dedbd1c..e8e1e8de 100644 --- a/website/src/repl/Repl.jsx +++ b/website/src/repl/Repl.jsx @@ -15,6 +15,7 @@ import { resetGlobalEffects, resetLoadedSounds, isAudioInitialized, + initAudioOnFirstClick, } from '@strudel/webaudio'; import { defaultAudioDeviceName } from '../settings.mjs'; import { getAudioDevices, setAudioDevice } from './util.mjs'; @@ -43,8 +44,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') { + audioReady = initAudioOnFirstClick(); modulesLoading = loadModules(); presets = prebake(); drawContext = getDrawContext(); @@ -83,16 +86,12 @@ export function Repl({ embedded = false }) { onUpdateState: (state) => { setReplState({ ...state }); }, - onToggle: async (playing) => { + onToggle: (playing) => { if (!playing) { clearHydra(); } }, - beforeEval: async () => { - if (!isAudioInitialized()) { - await initAudio(); - } - }, + beforeEval: () => audioReady, afterEval: (all) => { const { code } = all; setLatestCode(code); From ff85f2307f249bff1ed12465c6bc4e8f692fcd03 Mon Sep 17 00:00:00 2001 From: "Jade (Rose) Rowland" Date: Thu, 30 May 2024 18:58:41 -0400 Subject: [PATCH 4/8] remove unessecary functions --- packages/superdough/superdough.mjs | 1 - website/src/repl/Repl.jsx | 2 -- 2 files changed, 3 deletions(-) diff --git a/packages/superdough/superdough.mjs b/packages/superdough/superdough.mjs index c882659a..6756bd3d 100644 --- a/packages/superdough/superdough.mjs +++ b/packages/superdough/superdough.mjs @@ -27,7 +27,6 @@ export function getSound(s) { export const resetLoadedSounds = () => soundMap.set({}); let audioContext; -export const isAudioInitialized = () => audioContext != null; export const setDefaultAudioContext = () => { audioContext = new AudioContext(); diff --git a/website/src/repl/Repl.jsx b/website/src/repl/Repl.jsx index e8e1e8de..7a42f71f 100644 --- a/website/src/repl/Repl.jsx +++ b/website/src/repl/Repl.jsx @@ -10,11 +10,9 @@ import cx from '@src/cx.mjs'; import { transpiler } from '@strudel/transpiler'; import { getAudioContext, - initAudio, webaudioOutput, resetGlobalEffects, resetLoadedSounds, - isAudioInitialized, initAudioOnFirstClick, } from '@strudel/webaudio'; import { defaultAudioDeviceName } from '../settings.mjs'; From 07f58c023f8f35c4894b84d69de228b4c20d9125 Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Fri, 31 May 2024 10:36:49 +0200 Subject: [PATCH 5/8] bring back promise cache just in case loadWorklets is called more than once --- packages/superdough/superdough.mjs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/superdough/superdough.mjs b/packages/superdough/superdough.mjs index 6756bd3d..72001150 100644 --- a/packages/superdough/superdough.mjs +++ b/packages/superdough/superdough.mjs @@ -41,8 +41,12 @@ export const getAudioContext = () => { return audioContext; }; -async function loadWorklets() { - return await getAudioContext().audioWorklet.addModule(workletsUrl); +let workletsLoading; +function loadWorklets() { + if (!workletsLoading) { + workletsLoading = getAudioContext().audioWorklet.addModule(workletsUrl); + } + return workletsLoading; } // this function should be called on first user interaction (to avoid console warning) From 5c9a16bc88365402d8b143147a9175bc67d1d63d Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Fri, 31 May 2024 10:40:15 +0200 Subject: [PATCH 6/8] simplify initAudio --- packages/superdough/superdough.mjs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/superdough/superdough.mjs b/packages/superdough/superdough.mjs index 72001150..a3bc85b8 100644 --- a/packages/superdough/superdough.mjs +++ b/packages/superdough/superdough.mjs @@ -53,18 +53,18 @@ function loadWorklets() { 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', err); - }) - .finally(() => { - logger('audio worklets loaded'); - }); - } else { - logger('disableWorklets: AudioWorklet effects skipped!'); - } + return; + } + await getAudioContext().resume(); + if (disableWorklets) { + logger('disableWorklets: AudioWorklet effects skipped!'); + return; + } + try { + await loadWorklets(); + logger('audio worklets loaded'); + } catch (err) { + console.warn('could not load AudioWorklet effects', err); } } let audioReady = false; From c20e84773bf636c2443280072b751090cf42ac96 Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Fri, 31 May 2024 10:40:30 +0200 Subject: [PATCH 7/8] immediately remove click listener --- packages/superdough/superdough.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/superdough/superdough.mjs b/packages/superdough/superdough.mjs index a3bc85b8..b637fffd 100644 --- a/packages/superdough/superdough.mjs +++ b/packages/superdough/superdough.mjs @@ -72,9 +72,9 @@ export async function initAudioOnFirstClick(options) { if (!audioReady) { audioReady = new Promise((resolve) => { document.addEventListener('click', async function listener() { + document.removeEventListener('click', listener); await initAudio(options); resolve(); - document.removeEventListener('click', listener); }); }); } From 7a4902862d75fc53542c6faf691d3a4c2ce4ee41 Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Fri, 31 May 2024 10:45:06 +0200 Subject: [PATCH 8/8] tweaks + logs --- packages/superdough/superdough.mjs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/superdough/superdough.mjs b/packages/superdough/superdough.mjs index b637fffd..b2078b47 100644 --- a/packages/superdough/superdough.mjs +++ b/packages/superdough/superdough.mjs @@ -52,22 +52,23 @@ function loadWorklets() { // 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') { + if (typeof window === 'undefined') { return; } await getAudioContext().resume(); if (disableWorklets) { - logger('disableWorklets: AudioWorklet effects skipped!'); + logger('[superdough]: AudioWorklets disabled with disableWorklets'); return; } try { await loadWorklets(); - logger('audio worklets loaded'); + logger('[superdough] AudioWorklets loaded'); } catch (err) { console.warn('could not load AudioWorklet effects', err); } + logger('[superdough] ready'); } -let audioReady = false; +let audioReady; export async function initAudioOnFirstClick(options) { if (!audioReady) { audioReady = new Promise((resolve) => {