RecordingInterface.tsx
1 import React, { useEffect, useRef } from 'react'; 2 3 interface RecordingInterfaceProps { 4 onStopRecording: () => void; 5 } 6 7 const RecordingInterface: React.FC<RecordingInterfaceProps> = () => { 8 const canvasRef = useRef<HTMLCanvasElement>(null); 9 10 useEffect(() => { 11 let animationFrameId: number; 12 let analyser: AnalyserNode; 13 let dataArray: Uint8Array; 14 15 const startVisualization = async () => { 16 try { 17 const stream = await navigator.mediaDevices.getUserMedia({ audio: true }); 18 console.log('Microphone access granted'); 19 20 const audioContext = new (window.AudioContext || (window as any).webkitAudioContext)(); 21 const source = audioContext.createMediaStreamSource(stream); 22 analyser = audioContext.createAnalyser(); 23 source.connect(analyser); 24 25 analyser.fftSize = 2048; // Further increased fftSize for more data points 26 const bufferLength = analyser.frequencyBinCount; 27 dataArray = new Uint8Array(bufferLength); 28 29 const canvas = canvasRef.current; 30 const ctx = canvas?.getContext('2d'); 31 32 if (canvas && ctx) { 33 const draw = () => { 34 animationFrameId = requestAnimationFrame(draw); 35 analyser.getByteTimeDomainData(dataArray); 36 37 ctx.clearRect(0, 0, canvas.width, canvas.height); 38 39 ctx.strokeStyle = 'rgba(255, 255, 255, 0.5)'; 40 ctx.lineWidth = 2; 41 ctx.beginPath(); 42 43 const sliceWidth = canvas.width / bufferLength; 44 let x = 0; 45 let hasAudio = false; 46 47 for (let i = 0; i < bufferLength; i++) { 48 const v = dataArray[i] / 128.0; 49 const y = (v * canvas.height) / 2; 50 51 if (v > 0.001) { // Further lowered threshold for more sensitivity 52 hasAudio = true; 53 } 54 55 if (i === 0) { 56 ctx.moveTo(x, y); 57 } else { 58 ctx.lineTo(x, y); 59 } 60 61 x += sliceWidth; 62 } 63 64 if (!hasAudio) { 65 ctx.moveTo(0, canvas.height / 2); 66 ctx.lineTo(canvas.width, canvas.height / 2); 67 } 68 69 ctx.stroke(); 70 }; 71 72 draw(); 73 } 74 } catch (error) { 75 console.error('Error accessing microphone:', error); 76 } 77 }; 78 79 startVisualization(); 80 81 return () => { 82 cancelAnimationFrame(animationFrameId); 83 if (analyser) { 84 analyser.disconnect(); 85 } 86 }; 87 }, []); 88 89 return ( 90 <div className="w-full"> 91 <canvas ref={canvasRef} className="w-full h-8 rounded" /> 92 </div> 93 ); 94 }; 95 96 export default RecordingInterface;