169 lines
5.7 KiB
Vue
169 lines
5.7 KiB
Vue
<template>
|
|
<div>
|
|
<h1>Test Fall 4</h1>
|
|
<h3>Howler als Stream mit der HowlWebAudioBridge (createMediaElementSource)</h3>
|
|
<KeyboardPlayHandler />
|
|
<button @click="play">Play</button>
|
|
<div v-if="false" id="statistics">
|
|
{{ Object.keys(gains).length }}
|
|
{{ Object.keys(nodes).length }}
|
|
</div>
|
|
<HowlWebAudioBridge
|
|
:src="source[0]"
|
|
:audio-context="audioContext"
|
|
:on-ready="(node, howl) => registerAudioNode(node, howl, 63)"
|
|
/>
|
|
<HowlWebAudioBridge
|
|
:src="source[1]"
|
|
:audio-context="audioContext"
|
|
:on-ready="(node, howl) => registerAudioNode(node, howl, 125)"
|
|
/>
|
|
<HowlWebAudioBridge
|
|
:src="source[2]"
|
|
:audio-context="audioContext"
|
|
:on-ready="(node, howl) => registerAudioNode(node, howl, 250)"
|
|
/>
|
|
<HowlWebAudioBridge
|
|
:src="source[3]"
|
|
:audio-context="audioContext"
|
|
:on-ready="(node, howl) => registerAudioNode(node, howl, 500)"
|
|
/>
|
|
<HowlWebAudioBridge
|
|
:src="source[4]"
|
|
:audio-context="audioContext"
|
|
:on-ready="(node, howl) => registerAudioNode(node, howl, 1000)"
|
|
/>
|
|
<HowlWebAudioBridge
|
|
:src="source[5]"
|
|
:audio-context="audioContext"
|
|
:on-ready="(node, howl) => registerAudioNode(node, howl, 2000)"
|
|
/>
|
|
<HowlWebAudioBridge
|
|
:src="source[6]"
|
|
:audio-context="audioContext"
|
|
:on-ready="(node, howl) => registerAudioNode(node, howl, 4000)"
|
|
/>
|
|
<HowlWebAudioBridge
|
|
:src="source[7]"
|
|
:audio-context="audioContext"
|
|
:on-ready="(node, howl) => registerAudioNode(node, howl, 8000)"
|
|
/>
|
|
<HowlWebAudioBridge
|
|
:src="source[8]"
|
|
:audio-context="audioContext"
|
|
:on-ready="(node, howl) => registerAudioNode(node, howl, 16000)"
|
|
/>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import type { Logger } from 'pino'
|
|
import { useAudioStore } from '~/stores/audio'
|
|
import tracksConfig from '~/tracks.config'
|
|
import HowlWebAudioBridge from '~/components/Player/HowlWebAudioBridge.vue'
|
|
import KeyboardPlayHandler from '~/archive/components/KeyboardPlayHandler.vue'
|
|
|
|
const source = ref([tracksConfig['63_src'], tracksConfig['125_src'], tracksConfig['250_src'], tracksConfig['500_src'], tracksConfig['1000_src'], tracksConfig['2000_src'], tracksConfig['4000_src'], tracksConfig['8000_src'], tracksConfig['16000_src']])
|
|
const audioContext = ref(useAudioStore().getContext()as AudioContext)
|
|
const nodes = ref([] as Record<number, AudioNode>)
|
|
const gains = ref([] as Record<number, GainNode>)
|
|
const howls = ref([] as Array<Howl>)
|
|
const masterGain = ref(null as (GainNode | null))
|
|
const lastAction = audioContext.value.currentTime
|
|
const logger = useNuxtApp().$logger as Logger
|
|
|
|
const registerAudioNode = (node:AudioNode | null, howl: Howl| null, freq: number) => {
|
|
if (howl) {
|
|
logger.info('register new Node push it', howl.state)
|
|
howls.value.push(howl)
|
|
const mediaElement = (howl as any)._sounds[0]._node as HTMLAudioElement
|
|
mediaElement.muted = false
|
|
logger.info('mediaElement muted')
|
|
}
|
|
if (node) {
|
|
const gainNode = node.context.createGain()
|
|
const pannerNode = audioContext.value.createStereoPanner()
|
|
pannerNode.pan.value = 1
|
|
|
|
gainNode.gain.setValueAtTime(0, audioContext.value.currentTime)
|
|
gainNode.gain.linearRampToValueAtTime(0.5, audioContext.value.currentTime + 2)
|
|
const master = masterGain.value || useAudioStore().getMasterGainNoise()
|
|
nodes.value[freq] = node
|
|
gains.value[freq] = gainNode
|
|
node.connect(gainNode)
|
|
gainNode.connect(master)
|
|
pannerNode.connect(master)
|
|
|
|
logger.info('mediaElement nicht mehr gemutet')
|
|
logger.info('AudioNode ready, but not connected to destination', { node })
|
|
logger.info('Number of GainNodes', Object.keys(gains.value).length)
|
|
logger.info('Number of AudioNodes', Object.keys(nodes.value).length)
|
|
}
|
|
}
|
|
|
|
watch(() => useAudioStore().playing, // Überwache explizit den state
|
|
(newState) => {
|
|
if (newState) {
|
|
play()
|
|
} else {
|
|
pause()
|
|
}
|
|
}
|
|
)
|
|
|
|
watch(() => lastAction, // Überwache explizit den state
|
|
(lastTimestamp) => {
|
|
if (lastTimestamp > 50) {
|
|
play() // Overlay anzeigen
|
|
} else {
|
|
pause()
|
|
}
|
|
}
|
|
)
|
|
|
|
const pause = () => {
|
|
logger.info('pause')
|
|
const master = masterGain.value
|
|
const currentTime = audioContext.value.currentTime
|
|
// master?.gain.cancelScheduledValues(currentTime)
|
|
master?.gain.linearRampToValueAtTime(0, currentTime + 5)
|
|
const lastAction = currentTime
|
|
howls.value.forEach((howl) => {
|
|
howl.pause()
|
|
}
|
|
)
|
|
master?.disconnect()
|
|
// if (gainNode) {
|
|
// gainNode.connect(audioContext.value.destination)
|
|
// gainNode.gain.cancelScheduledValues(audioContext.value.currentTime)
|
|
// gainNode.gain.setValueAtTime(0, audioContext.value.currentTime)
|
|
// gainNode.gain.linearRampToValueAtTime(2, audioContext.value.currentTime + 4)
|
|
// } else {
|
|
// logger.info('GAINNODE NOT CREATED WE WILL NOT START')
|
|
// }
|
|
}
|
|
|
|
const play = () => {
|
|
const newHowls = howls.value
|
|
const master = masterGain.value || useAudioStore().getMasterGainNoise()
|
|
logger.info('Start this', { newHowls })
|
|
howls.value.forEach(async (howl) => {
|
|
howl.play()
|
|
logger.info('Start this', { newHowls })
|
|
masterGain?.value?.gain.linearRampToValueAtTime(1, audioContext.value.currentTime + 3)
|
|
const mediaElement = await (howl as any)._sounds[0]._node as HTMLAudioElement
|
|
mediaElement.muted = false
|
|
}
|
|
)
|
|
master.connect(audioContext.value.destination)
|
|
// if (gainNode) {
|
|
// gainNode.connect(audioContext.value.destination)
|
|
// gainNode.gain.cancelScheduledValues(audioContext.value.currentTime)
|
|
// gainNode.gain.setValueAtTime(0, audioContext.value.currentTime)
|
|
// gainNode.gain.linearRampToValueAtTime(2, audioContext.value.currentTime + 4)
|
|
// } else {
|
|
// logger.info('GAINNODE NOT CREATED WE WILL NOT START')
|
|
// }
|
|
}
|
|
</script>
|