import { midiHz, midiName } from '../params'; import type { RenderResult } from '../hooks/useRenderer'; export default function DiagnosticsPanel({ result }: { result: RenderResult }) { const d = result.diag; const pitches = Array.from(result.noteMidi).map((m) => midiName(m)); const shown = pitches.slice(0, 12); const cents = 1200 * Math.log2(d.fundHz / midiHz(result.noteMidi[0])); return (
Notes {shown.join(', ')} {pitches.length > shown.length ? `, … (${pitches.length} total)` : ''} {` · mean pluck ${d.meanForce.toFixed(1)} N`}
Fundamental {d.fundHz.toFixed(2)} Hz ({cents >= 0 ? '+' : ''}{cents.toFixed(0)} cents) · T60{' '} {d.fundT60.toFixed(1)} s
Modes {d.modesNote1} coupled (note 1) · {d.modesTotal} across {d.fingerings} fingering {d.fingerings === 1 ? '' : 's'}
Body A0 {result.bodyF[0]?.toFixed(1)} Hz · {result.bodyF.length} modes to{' '} {result.bodyF[result.bodyF.length - 1]?.toFixed(0)} Hz
Listener {(d.listenerDistM * 100).toFixed(0)} cm from the bridge
Peak pressure {d.peakPa.toFixed(3)} Pa ({d.peakSplDb.toFixed(1)} dB SPL)
Length {d.durationS.toFixed(2)} s · {result.quality} · oversample {d.oversample}
eigensolves: {d.solveCached ? 'cached' : `${(d.solveMs / 1000).toFixed(2)} s`} · radiation:{' '} {d.radiateCached ? 'cached' : `${(d.radiateMs / 1000).toFixed(2)} s`}
{d.warnings.map((w, i) => (
⚠ {w}
))}
); }