funkwhale/front/src/composables/audio/visualizer.ts

86 wiersze
2.1 KiB
TypeScript
Czysty Zwykły widok Historia

2022-11-03 09:37:56 +00:00
import type { Ref } from 'vue'
import { AUDIO_CONTEXT, GAIN_NODE } from './audio-api'
2022-11-06 09:58:15 +00:00
import { useResizeObserver, useStorage } from '@vueuse/core'
import { watchEffect, ref, markRaw } from 'vue'
2022-11-03 09:37:56 +00:00
2023-09-01 12:09:58 +00:00
import useLogger from '~/composables/useLogger'
2022-11-03 09:37:56 +00:00
// @ts-expect-error butterchurn has no typings
import butterchurnPresets from 'butterchurn-presets'
// @ts-expect-error butterchurn has no typings
import butterchurn from 'butterchurn'
export const useMilkDrop = (canvas: Ref<HTMLCanvasElement>) => {
2023-09-01 12:09:58 +00:00
const logger = useLogger()
2022-11-06 09:58:15 +00:00
const presets = Object.keys(butterchurnPresets)
2022-11-03 09:37:56 +00:00
const visualizer = ref()
2022-11-06 09:58:15 +00:00
const getRandomPreset = () => {
2022-11-03 09:37:56 +00:00
const index = (presets.length * Math.random()) | 0
2022-11-06 09:58:15 +00:00
return presets[index]
}
const presetName = useStorage<string | undefined>('milk-drop:preset', undefined)
watchEffect(() => {
const name = presetName.value
if (name === undefined) return
2023-09-01 12:09:58 +00:00
logger.log(`Switching to preset: '${name}'`)
2022-11-06 09:58:15 +00:00
visualizer.value?.loadPreset(butterchurnPresets[name], 1)
})
const loadRandomPreset = () => {
const name = getRandomPreset()
presetName.value = name
2022-11-03 09:37:56 +00:00
}
const initialize = (canvas: HTMLCanvasElement, width: number, height: number) => {
visualizer.value = markRaw(butterchurn.createVisualizer(AUDIO_CONTEXT, canvas, {
width,
height
}))
2022-11-06 09:58:15 +00:00
if (presetName.value === undefined) {
presetName.value = getRandomPreset()
}
2022-11-03 09:37:56 +00:00
visualizer.value.connectAudio(GAIN_NODE)
2022-11-04 00:11:51 +00:00
visualizer.value.setInternalMeshSize(128, 96)
2022-11-03 09:37:56 +00:00
}
2022-11-06 09:58:15 +00:00
const isVisible = ref(false)
2022-11-03 09:37:56 +00:00
useResizeObserver(canvas, ([entry]) => {
const { width, height } = entry.contentRect
canvas.value.width = width
canvas.value.height = height
2022-11-06 09:58:15 +00:00
isVisible.value = !!(width * height)
2022-11-03 09:37:56 +00:00
if (visualizer.value === undefined) {
initialize(entry.target as HTMLCanvasElement, width, height)
return
}
visualizer.value.setRendererSize(width, height)
})
const render = () => {
try {
visualizer.value?.render()
} catch (error) {
2023-09-01 12:09:58 +00:00
logger.error(error)
2022-11-06 09:58:15 +00:00
loadRandomPreset()
2022-11-03 09:37:56 +00:00
}
}
return {
visualizer,
loadRandomPreset,
2022-11-06 09:58:15 +00:00
render,
isVisible
2022-11-03 09:37:56 +00:00
}
}