63 lines
1.3 KiB
TypeScript
63 lines
1.3 KiB
TypeScript
import { useEventListener } from '@vueuse/core'
|
|
|
|
export default function useAudioContext(audioTrack: Ref<MediaStreamTrack | undefined>) {
|
|
const ctx = new (window.AudioContext || window.webkitAudioContext)()
|
|
|
|
const stream = new MediaStream()
|
|
const audioEl = new Audio()
|
|
|
|
const sourceNode = shallowRef<MediaStreamAudioSourceNode>()
|
|
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,
|
|
}
|
|
}
|