import { createSharedComposable } from '@vueuse/core' import { Howl } from 'howler' const CONNECTION_SOUNDS = Object.keys(import.meta.glob('@/../public/sfx/connection/*.ogg')).map(path => path.replace('../public', '')) console.log('CONNECTION_SOUNDS', CONNECTION_SOUNDS) function hashStringToNumber(str: string, cap: number): number { let hash = 0 for (let i = 0; i < str.length; i++) { hash = (hash * 31 + str.charCodeAt(i)) | 0 } return Math.abs(hash) % cap } const oneShots: Howl[] = [] type SfxEvent = 'mic-on' | 'mic-off' | 'stream-on' | 'stream-off' | 'connection' const EVENT_VOLUME: Record = { 'mic-on': 0.2, 'mic-off': 0.2, 'stream-on': 0.03, 'stream-off': 0.03, 'connection': 0.1, } // TODO: refactor this shit export const useSfx = createSharedComposable(() => { const { outputMuted } = useApp() async function play(src: string, volume = 0.2): Promise { return new Promise((resolve) => { const howl = new Howl({ src, autoplay: true, loop: false, volume, }) howl.on('end', () => { resolve() }) }) } async function playOneShot(src: string, volume = 0.2): Promise { for (const oneShot of oneShots) { oneShot.stop() } oneShots.length = 0 return new Promise((resolve) => { const howl = new Howl({ src, autoplay: true, loop: false, volume, }) oneShots.push(howl) howl.on('end', () => { resolve() }) }) } async function playEvent(event: SfxEvent) { switch (event) { default: await playOneShot(`/sfx/${event}.ogg`, EVENT_VOLUME[event]) break } } async function playRandomConnectionSound(seed: string) { await playEvent('stream-on') if (outputMuted.value) return await play(CONNECTION_SOUNDS[hashStringToNumber(seed, CONNECTION_SOUNDS.length)]!, 0.1) } return { playOneShot, play, playRandomConnectionSound, playEvent, } })