1495a9a5c5
Have tested it with a 5 minute long audio file Bigger files and different formats still needs testing
74 lines
2.1 KiB
TypeScript
Executable File
74 lines
2.1 KiB
TypeScript
Executable File
import { useRef, useState, useCallback } from 'react';
|
|
|
|
export interface AudioData {
|
|
leftChannel: Float32Array;
|
|
rightChannel: Float32Array;
|
|
sampleRate: number;
|
|
duration: number;
|
|
}
|
|
|
|
export function useAudioAnalyzer() {
|
|
const [audioData, setAudioData] = useState<AudioData | null>(null);
|
|
const [isLoading, setIsLoading] = useState(false);
|
|
const [error, setError] = useState<string | null>(null);
|
|
const [fileName, setFileName] = useState<string | null>(null);
|
|
const [originalFile, setOriginalFile] = useState<File | null>(null);
|
|
const audioContextRef = useRef<AudioContext | null>(null);
|
|
|
|
const loadAudioFile = useCallback(async (file: File) => {
|
|
setIsLoading(true);
|
|
setError(null);
|
|
setFileName(file.name);
|
|
setOriginalFile(file);
|
|
|
|
try {
|
|
// Create or reuse AudioContext
|
|
if (!audioContextRef.current) {
|
|
audioContextRef.current = new AudioContext();
|
|
}
|
|
const audioContext = audioContextRef.current;
|
|
|
|
// Read file as ArrayBuffer
|
|
const arrayBuffer = await file.arrayBuffer();
|
|
|
|
// Decode audio data
|
|
const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);
|
|
|
|
// Extract channel data
|
|
const leftChannel = audioBuffer.getChannelData(0);
|
|
const rightChannel = audioBuffer.numberOfChannels > 1
|
|
? audioBuffer.getChannelData(1)
|
|
: audioBuffer.getChannelData(0); // Mono: duplicate left channel
|
|
|
|
setAudioData({
|
|
leftChannel: new Float32Array(leftChannel),
|
|
rightChannel: new Float32Array(rightChannel),
|
|
sampleRate: audioBuffer.sampleRate,
|
|
duration: audioBuffer.duration,
|
|
});
|
|
} catch (err) {
|
|
setError(err instanceof Error ? err.message : 'Failed to load audio file');
|
|
setAudioData(null);
|
|
} finally {
|
|
setIsLoading(false);
|
|
}
|
|
}, []);
|
|
|
|
const reset = useCallback(() => {
|
|
setAudioData(null);
|
|
setFileName(null);
|
|
setOriginalFile(null);
|
|
setError(null);
|
|
}, []);
|
|
|
|
return {
|
|
audioData,
|
|
isLoading,
|
|
error,
|
|
fileName,
|
|
originalFile,
|
|
loadAudioFile,
|
|
reset,
|
|
};
|
|
}
|