diff --git a/app/composables/useAssets.ts.in b/app/composables/useAssets.ts.in index 1c71e88..fedbdcb 100644 --- a/app/composables/useAssets.ts.in +++ b/app/composables/useAssets.ts.in @@ -7,24 +7,45 @@ type Rect = [number, number, number, number]; let atlasImage: HTMLImageElement | null = null; const modelCache = new Map(); -const createAudio = (path: string) => { - const source = import.meta.client ? new Audio(path) : null; - return { - play: (volume = 1) => { - if (!source) return; - const app = useAppStore(); - const audio = source.cloneNode() as HTMLAudioElement; - audio.volume = Math.min(1, volume * app.settings.volume); - audio.addEventListener("ended", () => audio.remove(), { once: true }); - audio.play().catch(() => {}); - }, - }; -}; +const audioContext = import.meta.client ? new AudioContext() : null; const loaded = ref(0); const total = ref({{TOTAL}}); const isReady = computed(() => loaded.value === total.value); +const createAudio = (path: string) => { + let buffer: AudioBuffer | null = null; + + if (audioContext) { + total.value += 1; + fetch(path) + .then((r) => r.arrayBuffer()) + .then((buf) => audioContext.decodeAudioData(buf)) + .then((buf) => { + buffer = buf; + loaded.value += 1; + }) + .catch(() => { + loaded.value += 1; + }); + } + + return { + play: (volume = 1) => { + if (!audioContext || !buffer) return; + + const app = useAppStore(); + const gain = audioContext.createGain(); + gain.gain.value = Math.min(1, volume * app.settings.volume); + + const node = audioContext.createBufferSource(); + node.buffer = buffer; + node.connect(gain).connect(audioContext.destination); + node.start(); + }, + }; +}; + if (import.meta.client) { atlasImage = document.createElement('img'); atlasImage.src = '/nds/atlas.webp?v={{ATLAS_HASH}}';