import React from 'react'; import type { SpectralDetail } from '../../services/audioService'; interface SpectrogramViewProps { spectralDetail: SpectralDetail; aiScore: number; } interface Band { label: string; key: keyof SpectralDetail; range: string; invert?: boolean; // true = lower value = more AI maxVal: number; } const BANDS: Band[] = [ { label: 'HF Energy', key: 'hf_energy_ratio', range: '6–8 kHz', invert: false, maxVal: 0.25 }, { label: 'Mel Smoothness', key: 'mel_frame_diff', range: 'Full Band', invert: false, maxVal: 5.0 }, { label: 'MFCC Δ Std', key: 'mfcc_delta_std', range: 'Cepstral', invert: false, maxVal: 10.0 }, { label: 'Flatness Var', key: 'flatness_variance', range: 'Full Band', invert: false, maxVal: 0.015}, { label: 'Centroid Var', key: 'centroid_variance', range: 'Spectral', invert: false, maxVal: 0.005}, ]; const SpectrogramView: React.FC = ({ spectralDetail, aiScore }) => { const isAI = aiScore > 60; return (
Spectral Fingerprint
{isAI ? 'Vocoder Signature' : 'Natural Spectrum'}
{/* Pseudo-spectrogram frequency bands */}
{BANDS.map(({ label, key, range, maxVal }) => { const rawVal = spectralDetail[key] as number | undefined; const val = rawVal ?? 0; const pct = Math.min(100, Math.max(0, (val / maxVal) * 100)); // Low values on invert=false metrics = suspicious const suspicion = 100 - pct; const isSuspicious = suspicion > 65; const barColor = isSuspicious ? 'var(--accent-orange)' : pct > 60 ? '#00E5CC' : 'var(--accent-yellow)'; return (
{label} {typeof rawVal === 'number' ? rawVal.toFixed(4) : '—'} / {range}
{/* Background gradient showing expected human range */}
); })}

{isAI ? 'Frequency distribution shows neural vocoder characteristics — reduced high-frequency content and over-smoothed transitions.' : 'Frequency distribution shows natural acoustic properties — normal high-frequency energy and realistic spectral variation.'}

); }; export default SpectrogramView;