import { useEventListener } from '@vueuse/core' export default function useAudioContext(audioTrack: Ref) { const ctx = new (window.AudioContext || window.webkitAudioContext)() const stream = new MediaStream() const sourceNode = shallowRef() const gainNode = ctx.createGain() let hackExecuted = false watch(audioTrack, (track, prevTrack) => { if (prevTrack) stream.removeTrack(prevTrack) if (!track) return stream.addTrack(track) if (!hackExecuted) { const audioEl = new Audio() audioEl.srcObject = stream audioEl.muted = true hackExecuted = true } sourceNode.value = ctx.createMediaStreamSource(stream) connect() }, { immediate: true }) useEventListener(document, 'click', async () => { if (ctx.state === 'suspended') { await ctx.resume() } connect() }, { once: true }) function connect() { if (!sourceNode.value || ctx.state === 'suspended') return sourceNode.value.connect(gainNode) gainNode.connect(ctx.destination) ctx.resume() } function setGain(value: number) { gainNode.gain.value = value } return { setGain, } }