fix(audio-analyzer): improve stability and typings (#551)
This commit is contained in:
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user