diff --git a/client/app/composables/use-app.ts b/client/app/composables/use-app.ts index 49f4207..380085d 100644 --- a/client/app/composables/use-app.ts +++ b/client/app/composables/use-app.ts @@ -53,7 +53,7 @@ export const useApp = createGlobalState(() => { await mediasoup.pauseProducer(mediasoup.micProducer.value) - sfx.play('/sfx/off_micr.ogg').then() + sfx.playEvent('mic-off').then() toast.add({ severity: 'info', summary: 'Microphone muted', closable: false, life: 1000 }) } @@ -67,7 +67,7 @@ export const useApp = createGlobalState(() => { await mediasoup.resumeProducer(mediasoup.micProducer.value) - sfx.play('/sfx/on_micr.ogg').then() + sfx.playEvent('mic-on').then() toast.add({ severity: 'info', summary: 'Microphone activated', closable: false, life: 1000 }) } @@ -118,22 +118,22 @@ export const useApp = createGlobalState(() => { async function toggleVideo() { if (!mediasoup.videoProducer.value) { await mediasoup.enableVideo() - await sfx.play('/sfx/on_trans.ogg', 0.03) + await sfx.playEvent('stream-on') } else { await mediasoup.disableProducer(mediasoup.videoProducer.value) - await sfx.play('/sfx/off_trans.ogg', 0.03) + await sfx.playEvent('stream-off') } } async function toggleShare() { if (!mediasoup.shareProducer.value) { await mediasoup.enableShare() - await sfx.play('/sfx/on_trans.ogg', 0.03) + await sfx.playEvent('stream-on') } else { await mediasoup.disableProducer(mediasoup.shareProducer.value) - await sfx.play('/sfx/off_trans.ogg', 0.03) + await sfx.playEvent('stream-off') } } diff --git a/client/app/composables/use-mediasoup.ts b/client/app/composables/use-mediasoup.ts index 3edf241..e44935e 100644 --- a/client/app/composables/use-mediasoup.ts +++ b/client/app/composables/use-mediasoup.ts @@ -203,7 +203,7 @@ export const useMediasoup = createSharedComposable(() => { }) if (kind === 'video') - sfx.play('/sfx/on_trans.ogg', 0.03).then() + sfx.playEvent('stream-on').then() if (producerPaused) consumer.pause() @@ -225,7 +225,7 @@ export const useMediasoup = createSharedComposable(() => { consumer.observer.on('close', () => { if (kind === 'video') - sfx.play('/sfx/off_trans.ogg', 0.03).then() + sfx.playEvent('stream-off').then() delete consumers.value[consumer.id] }) diff --git a/client/app/composables/use-sfx.ts b/client/app/composables/use-sfx.ts index 4e1b960..84b11ec 100644 --- a/client/app/composables/use-sfx.ts +++ b/client/app/composables/use-sfx.ts @@ -1,5 +1,5 @@ import { createSharedComposable } from '@vueuse/core' -import { Howl, Howler } from 'howler' +import { Howl } from 'howler' const CONNECTION_SOUNDS = Object.keys(import.meta.glob('@/../public/sfx/connection/*.ogg')).map(path => path.replace('../public', '')) @@ -13,10 +13,20 @@ function hashStringToNumber(str: string, cap: number): number { 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, +} + export const useSfx = createSharedComposable(() => { async function play(src: string, volume = 0.2): Promise { - Howler.stop() - return new Promise((resolve) => { const howl = new Howl({ src, @@ -31,13 +41,46 @@ export const useSfx = createSharedComposable(() => { }) } + 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 play('/sfx/on_trans.ogg', 0.03) + await playEvent('stream-on') await play(CONNECTION_SOUNDS[hashStringToNumber(seed, CONNECTION_SOUNDS.length + 1)]!, 0.1) } return { + playOneShot, play, playRandomConnectionSound, + playEvent, } }) diff --git a/client/public/sfx/off_micr.ogg b/client/public/sfx/mic-off.ogg similarity index 100% rename from client/public/sfx/off_micr.ogg rename to client/public/sfx/mic-off.ogg diff --git a/client/public/sfx/on_micr.ogg b/client/public/sfx/mic-on.ogg similarity index 100% rename from client/public/sfx/on_micr.ogg rename to client/public/sfx/mic-on.ogg diff --git a/client/public/sfx/off_trans.ogg b/client/public/sfx/stream-off.ogg similarity index 100% rename from client/public/sfx/off_trans.ogg rename to client/public/sfx/stream-off.ogg diff --git a/client/public/sfx/on_trans.ogg b/client/public/sfx/stream-on.ogg similarity index 100% rename from client/public/sfx/on_trans.ogg rename to client/public/sfx/stream-on.ogg