import { useEventListener } from '@vueuse/core' export default function useAudioContext(audioTrack: Ref) { const ctx = new (window.AudioContext || window.webkitAudioContext)() const stream = new MediaStream() const audioEl = new Audio() const sourceNode = shallowRef() const gainNode = ctx.createGain() watch(audioTrack, async (track, prevTrack) => { if (prevTrack) stream.removeTrack(prevTrack) if (!track) return stream.addTrack(track) if (!audioEl.srcObject) { audioEl.srcObject = stream audioEl.muted = true } sourceNode.value = ctx.createMediaStreamSource(stream) await connect() }, { immediate: true }) useEventListener(document, 'click', async () => { if (ctx.state === 'suspended') { await ctx.resume() } await connect() }, { once: true }) onScopeDispose(() => { audioEl.pause() audioEl.srcObject = null ctx.close() }) async 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, } }