import { useMemo } from "react"; import { Card, CardContent, CardHeader, CardTitle, } from "../../../shared/ui/card"; type Props = { rmsDb: number | null; peakHoldDb3s: number | null; }; function clamp(v: number, min: number, max: number) { return Math.max(min, Math.min(max, v)); } function colorByDb(db: number): string { // default thresholds from spec: // green: < -20, yellow: < -10, red: >= -10 if (db < -20) return "bg-emerald-500"; if (db < -10) return "bg-amber-500"; return "bg-rose-500"; } export function AudioMeter({ rmsDb, peakHoldDb3s }: Props) { const minDb = -50; const maxDb = 0; const fillPct = useMemo(() => { if (rmsDb === null) return 0; const v = clamp(rmsDb, minDb, maxDb); return ((v - minDb) / (maxDb - minDb)) * 100; }, [rmsDb]); const peakTopPct = useMemo(() => { if (peakHoldDb3s === null) return null; const v = clamp(peakHoldDb3s, minDb, maxDb); const pct = ((v - minDb) / (maxDb - minDb)) * 100; return 100 - pct; // from top }, [peakHoldDb3s]); const barColor = rmsDb === null ? "bg-slate-300" : colorByDb(rmsDb); return ( Аудио измеритель {/* Scale + meter */}
{/* ticks */}
0 дБ
-10
-20
-30
-40
-50
{peakTopPct !== null && (
)}
{/* Values */}
Сейчас
{rmsDb === null ? "—" : `${rmsDb.toFixed(1)} dB`}
Пик (3с)
{peakHoldDb3s === null ? "—" : `${peakHoldDb3s.toFixed(1)} dB`}
); }