60 lines
1.2 KiB
TypeScript
60 lines
1.2 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 sourceNode = shallowRef<MediaStreamAudioSourceNode>()
|
|
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,
|
|
}
|
|
}
|