File size: 1,434 Bytes
eeb9404
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
'use client';

import { useEffect, useRef } from 'react';
import { cn } from '@/lib/utils';

/**
 * AudioSpectrogram — draws live FFT bars from a recording AnalyserNode.
 * Purely visual feedback while the mic is capturing.
 */
export function AudioSpectrogram({
  analyser,
  className,
}: {
  analyser: AnalyserNode | null;
  className?: string;
}) {
  const canvasRef = useRef<HTMLCanvasElement>(null);

  useEffect(() => {
    const canvas = canvasRef.current;
    if (!analyser || !canvas) return;
    const ctx = canvas.getContext('2d');
    if (!ctx) return;

    const bins = analyser.frequencyBinCount;
    const data = new Uint8Array(bins);
    let raf = 0;

    const draw = () => {
      raf = requestAnimationFrame(draw);
      analyser.getByteFrequencyData(data);
      const w = canvas.width;
      const h = canvas.height;
      ctx.clearRect(0, 0, w, h);
      const barW = w / bins;
      for (let i = 0; i < bins; i++) {
        const v = data[i] / 255;
        const barH = Math.max(2, v * h);
        // primary accent, brighter with level
        ctx.fillStyle = `rgba(255, 91, 30, ${0.3 + v * 0.7})`;
        ctx.fillRect(i * barW, (h - barH) / 2, Math.max(1, barW - 1), barH);
      }
    };
    draw();
    return () => cancelAnimationFrame(raf);
  }, [analyser]);

  return (
    <canvas
      ref={canvasRef}
      width={240}
      height={28}
      className={cn('h-7 w-full', className)}
    />
  );
}