fix(audio-analyzer): improve stability and typings (#551)

This commit is contained in:
Iro
2025-09-04 19:03:56 +08:00
committed by GitHub
parent cda0ec1221
commit 7af5013307
@@ -1,4 +1,4 @@
import { ref } from 'vue'
import { onUnmounted, ref } from 'vue'
export function useAudioAnalyzer() {
const analyzer = ref<AnalyserNode>()
@@ -8,14 +8,22 @@ export function useAudioAnalyzer() {
const onAnalyzerUpdateHooks = ref<Array<(volumeLevel: number) => void | Promise<void>>>([])
const volumeLevel = ref(0) // 0-100
const error = ref<string>()
const amplification = 3 // Amplification factor for volume visualization
function onAnalyzerUpdate(callback: (volumeLevel: number) => void | Promise<void>) {
onAnalyzerUpdateHooks.value.push(callback)
return () => {
// optional cleanup if consumer wants to unsubscribe
onAnalyzerUpdateHooks.value = onAnalyzerUpdateHooks.value.filter(cb => cb !== callback)
}
}
function start() {
if (animationFrame.value)
return // prevent multiple loops
const analyze = () => {
if (!analyzer.value || !dataArray.value)
return
@@ -29,7 +37,7 @@ export function useAudioAnalyzer() {
sum += dataArray.value[i] * dataArray.value[i]
}
const rms = Math.sqrt(sum / dataArray.value.length)
volumeLevel.value = Math.min(100, (rms / 255) * 100 * 3) // Amplify for better visualization
volumeLevel.value = Math.min(100, (rms / 255) * 100 * amplification) // Amplify for better visualization
for (const hook of onAnalyzerUpdateHooks.value) {
hook(volumeLevel.value)
@@ -47,14 +55,14 @@ export function useAudioAnalyzer() {
}
try {
// Create analyser for volume detection
// Create analyser for volume detection
analyzer.value = audioContext.createAnalyser()
analyzer.value.fftSize = 256
analyzer.value.smoothingTimeConstant = 0.3
// Set up data array for analysis
const bufferLength = analyzer.value.frequencyBinCount
dataArray.value = new Uint8Array(bufferLength)
dataArray.value = new Uint8Array(bufferLength) as Uint8Array<ArrayBuffer>
// Start audio analysis loop
start()
@@ -68,7 +76,7 @@ export function useAudioAnalyzer() {
}
function stopAnalyzer() {
// Stop animation frame
// Stop animation frame
if (animationFrame.value) {
cancelAnimationFrame(animationFrame.value)
animationFrame.value = undefined
@@ -78,9 +86,14 @@ export function useAudioAnalyzer() {
dataArray.value = undefined
}
// Auto-cleanup when used in a component
onUnmounted(() => {
stopAnalyzer()
})
return {
volumeLevel,
error,
startAnalyzer,
stopAnalyzer,
onAnalyzerUpdate,