diff --git a/sfm/event_browser.html b/sfm/event_browser.html index 5d7a493..1ef883b 100644 --- a/sfm/event_browser.html +++ b/sfm/event_browser.html @@ -289,7 +289,12 @@ - + + @@ -328,6 +333,29 @@ const CHANNEL_COLORS = { }; const CHANNEL_ORDER = ['MicL', 'Long', 'Vert', 'Tran']; +// Reference pressure for dB(L) — 20 µPa expressed in psi (≈ 2.9e-9 psi). +const DBL_REF = 2.9e-9; + +// User-toggleable mic display unit: 'dBL' (default, matches BW printout +// + the rest of SFM) or 'psi' (raw sample unit). +function _getMicUnit() { + return localStorage.getItem('sfm_mic_unit') === 'psi' ? 'psi' : 'dBL'; +} +function _setMicUnit(u) { + localStorage.setItem('sfm_mic_unit', u === 'psi' ? 'psi' : 'dBL'); + _refreshMicUnitToggle(); + if (currentEventId) loadEvent(currentEventId); +} +function _refreshMicUnitToggle() { + const b = document.getElementById('mic-unit-toggle'); + if (b) b.textContent = `Mic: ${_getMicUnit()}`; +} +// psi → dB(L). Null for non-positive (log undefined; Chart.js renders as a gap). +function _psiToDbl(psi) { + if (psi == null || !(psi > 0)) return null; + return 20 * Math.log10(psi / DBL_REF); +} + // Adaptive decimal formatter — scientific notation only for truly extreme // values. Normal-range peaks render as plain decimals with sensible // precision (was previously forcing toExponential(3) which produced ugly @@ -502,6 +530,19 @@ function renderMeta(data, ev) { ['Vert', ev?.vert_ppv], ['Long', ev?.long_ppv], ]; + // Mic display honors the current user preference (dBL default). + // mic_ppv is stored as raw psi on series3 events; convert when needed. + const micPsi = ev?.mic_ppv; + const micUnitDisplay = _getMicUnit(); + let micStr; + if (micPsi == null) { + micStr = '—'; + } else if (micUnitDisplay === 'dBL') { + const d = _psiToDbl(Number(micPsi)); + micStr = (d != null ? d.toFixed(1) : '—') + ' dBL'; + } else { + micStr = Number(micPsi).toExponential(2) + ' psi'; + } const statsHtml = ` @@ -509,7 +550,7 @@ function renderMeta(data, ev) { ${rows.map(([ch, ppv]) => ``).join('')} - +
${ch}${fmt(ppv)}
MicL${fmt(ev?.mic_ppv)} psi
MicL${micStr}
`; @@ -560,11 +601,11 @@ function renderWaveform(data) { ); const lastDataCh = channelsWithData[channelsWithData.length - 1]; + const micUnit = _getMicUnit(); for (const ch of CHANNEL_ORDER) { const chData = channels[ch]; if (!chData) continue; - const values = chData.values || []; - if (values.length === 0) { + if ((chData.values || []).length === 0) { // Render an empty card so user sees the channel exists but is missing const wrap = document.createElement('div'); wrap.className = 'chart-wrap'; @@ -579,9 +620,19 @@ function renderWaveform(data) { continue; } - const unit = chData.unit || 'unit'; - const peak = chData.peak; + // Mic channel: convert from raw psi to dB(L) when the user prefers dBL + // (the default). We mutate `values`, `peak`, and `unit` locally so the + // chart datasets + axis title + tooltip + peak label all stay aligned. + let values = chData.values || []; + let unit = chData.unit || 'unit'; + let peak = chData.peak; const peakT = chData.peak_t_ms; + if (ch === 'MicL' && unit === 'psi' && micUnit === 'dBL') { + values = values.map(_psiToDbl); + peak = _psiToDbl(peak); + unit = 'dB(L)'; + } + const peakLabel = peak != null ? `peak ${_fmtPeak(peak, unit)}` + (!isHistogram && peakT != null ? ` @ ${peakT.toFixed(1)} ms` : '') @@ -781,6 +832,9 @@ document.getElementById('serial-select').addEventListener('change', e => { }); document.getElementById('event-filter').addEventListener('input', applyFilter); +// Reflect any persisted mic-unit preference in the header pill on load +_refreshMicUnitToggle(); + // Initial load loadSerials(); diff --git a/sfm/sfm_webapp.html b/sfm/sfm_webapp.html index 2c4a912..ad2b6e9 100644 --- a/sfm/sfm_webapp.html +++ b/sfm/sfm_webapp.html @@ -818,6 +818,12 @@ Force refresh +
+