Spaces:
Running
on
A100
Running
on
A100
File size: 2,631 Bytes
ae238b3 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
import { useRef, useEffect, useState } from 'react';
interface UseAudioAnalyzerReturn {
audioData: Uint8Array;
analyser: AnalyserNode | null;
connectToStream: (stream: MediaStream) => void;
disconnect: () => void;
}
export const useAudioAnalyzer = (fftSize: number = 256): UseAudioAnalyzerReturn => {
const [audioData, setAudioData] = useState<Uint8Array>(new Uint8Array(fftSize / 2));
const [analyser, setAnalyser] = useState<AnalyserNode | null>(null);
const audioContextRef = useRef<AudioContext | null>(null);
const sourceRef = useRef<MediaStreamAudioSourceNode | null>(null);
const animationFrameRef = useRef<number | null>(null);
const connectToStream = (stream: MediaStream) => {
try {
// Clean up existing connections
disconnect();
// Create new audio context and analyser
const audioContext = new (window.AudioContext || (window as any).webkitAudioContext)();
const analyserNode = audioContext.createAnalyser();
analyserNode.fftSize = fftSize;
analyserNode.smoothingTimeConstant = 0.8;
// Connect stream to analyser
const source = audioContext.createMediaStreamSource(stream);
source.connect(analyserNode);
// Store references
audioContextRef.current = audioContext;
sourceRef.current = source;
setAnalyser(analyserNode);
// Start updating audio data
const bufferLength = analyserNode.frequencyBinCount;
const dataArray = new Uint8Array(bufferLength);
const updateAudioData = () => {
if (analyserNode) {
analyserNode.getByteFrequencyData(dataArray);
setAudioData(new Uint8Array(dataArray));
animationFrameRef.current = requestAnimationFrame(updateAudioData);
}
};
updateAudioData();
} catch (error) {
console.error('Error setting up audio analyzer:', error);
}
};
const disconnect = () => {
// Cancel animation frame
if (animationFrameRef.current) {
cancelAnimationFrame(animationFrameRef.current);
animationFrameRef.current = null;
}
// Disconnect audio nodes
if (sourceRef.current) {
sourceRef.current.disconnect();
sourceRef.current = null;
}
// Close audio context
if (audioContextRef.current) {
audioContextRef.current.close();
audioContextRef.current = null;
}
setAnalyser(null);
setAudioData(new Uint8Array(fftSize / 2));
};
// Cleanup on unmount
useEffect(() => {
return () => {
disconnect();
};
}, []);
return {
audioData,
analyser,
connectToStream,
disconnect,
};
};
|