Recover analyzer DSP and realtime pipeline corrections
This commit is contained in:
+60
-25
@@ -51,20 +51,20 @@ const CONFIG = {
|
||||
REALTIME_BAR_DECAY_DB_PER_S: 20,
|
||||
RTA_ENGINE: 'iir', // 'fft' | 'iir'
|
||||
RTA_FREQ_RANGE: 'norm', // 'norm' | 'lf'
|
||||
RTA_BPO_MODE: '1_6',
|
||||
RTA_BPO_MODE: '1_3',
|
||||
RTA_WEIGHTING: 'z', // 'z' | 'a' | 'c'
|
||||
RTA_DISPLAY_GAIN_FFT_DB: 20,
|
||||
RTA_DISPLAY_GAIN_IIR_DB: 20,
|
||||
RTA_BAR_LAYOUT: 'rtw', // 'iec' | 'rtw'
|
||||
RTA_BAR_BASE_COLOR: '#ffe066',
|
||||
HEADER_TEXT_COLOR: '#ffe066',
|
||||
RTA_INTEGRATION: 'fast', // 'impulse' | 'fast' | 'slow' | 'peak'
|
||||
RTA_INTEGRATION: 'fast', // 'impulse' | 'fast' | 'medium' | 'slow' | 'average' | 'peak'
|
||||
RTA_BALLISTICS_MODE: 'average', // 'average' | 'peak' | 'both'
|
||||
RTA_PEAK_HOLD_MODE: 'auto', // 'off' | 'auto' | 'manual'
|
||||
RTA_PEAK_HOLD_SEC: 2,
|
||||
RTA_PEAK_HOLD_SEC: 2.5,
|
||||
RTA_PEAK_DECAY_DB_PER_S: 20,
|
||||
RTA_DISPLAY_HOLD_SEC: 0,
|
||||
RTA_IIR_ORDER: 4,
|
||||
RTA_IIR_ORDER: 6,
|
||||
RTA_IIR_TAU_FAST: 0.12,
|
||||
RTA_IIR_TAU_SLOW: 1.0,
|
||||
SPECTRO_GAMMA: 0.4,
|
||||
@@ -156,20 +156,19 @@ const CONFIG = {
|
||||
PPM_DIN_TOP: +5,
|
||||
PPM_DIN_BOTTOM: -50,
|
||||
PPM_DIN_RED_START: 0,
|
||||
// DIN PPM attack and decay times: 5 ms integration and 20 dB in 1.7 s
|
||||
// (≈11.8 dB/s) return, per IEC 60268‑10 Type I.
|
||||
PPM_DIN_ATTACK_MS: 5,
|
||||
// Fixed RTW/DIN profile: 10 ms integration and 20 dB return in 1.5 s.
|
||||
PPM_DIN_ATTACK_MS: 10,
|
||||
// Non-normative: when enabled, PPM DIN attack becomes instant (no integration).
|
||||
// Useful to compensate perceived meter lag caused by device / pipeline latency.
|
||||
PPM_DIN_FAST_ATTACK: false,
|
||||
PPM_DIN_DECAY_DB_PER_S: 11.8,
|
||||
PPM_DIN_DECAY_DB_PER_S: 20 / 1.5,
|
||||
// Hold time for DIN PPM: verlängert auf 1000 ms (1 s), damit der Peak‑Hold
|
||||
// auch bei kurzen Transienten deutlich sichtbar bleibt. Gemäß
|
||||
// Rundfunkpraxis werden Peak‑Hold‑Striche häufig 1–2 Sekunden gehalten.
|
||||
PPM_DIN_HOLD_MS: 1000,
|
||||
// Decay rate for the DIN PPM hold. When the held peak decays, it uses
|
||||
// the same slope as the main meter (≈11.8 dB/s).
|
||||
PPM_DIN_HOLD_DECAY_DB_PER_S: 11.8,
|
||||
// the same slope as the main meter (≈13.33 dB/s).
|
||||
PPM_DIN_HOLD_DECAY_DB_PER_S: 20 / 1.5,
|
||||
|
||||
// Offsets für die PPM-Meter (DIN/EBU-spezifisch). Die EBU/DIN Offsets
|
||||
// ersetzen den früheren globalen PPM_OFFSET.
|
||||
@@ -178,16 +177,18 @@ const CONFIG = {
|
||||
PPM_REF_DBFS_PEAK_FOR_0_DBU: -15.0,
|
||||
|
||||
// Ballistic parameters for the EBU PPM (Type IIb). Attack ~10 ms and
|
||||
// decay 24 dB in 2.8 s (≈8.6 dB/s), per IEC 60268‑10 Type II. A short
|
||||
// decay 24 dB in 2.8 s (≈8.57 dB/s), per EBU Tech 3205-E Type IIb. A short
|
||||
// peak-hold (~750 ms) helps visualise transients. Hold decay matches
|
||||
// the main decay rate.
|
||||
PPM_EBU_ATTACK_MS: 10,
|
||||
PPM_EBU_DECAY_DB_PER_S: 8.6,
|
||||
PPM_EBU_DECAY_DB_PER_S: 24 / 2.8,
|
||||
PPM_EBU_HOLD_MS: 750,
|
||||
PPM_EBU_HOLD_DECAY_DB_PER_S: 8.6,
|
||||
PPM_EBU_HOLD_DECAY_DB_PER_S: 24 / 2.8,
|
||||
CORR_SMOOTH: 0.85,
|
||||
CORR_ZERO_ON_SILENCE: false,
|
||||
CORR_SILENCE_THRESHOLD_RMS_DBFS: -75,
|
||||
CORR_RESPONSE_S: 1.0,
|
||||
CORR_RESET_TOKEN: 0,
|
||||
XY_POINTS: 1024,
|
||||
XY_STYLE: 'lines',
|
||||
XY_SILENCE_GATE_ENABLED: true,
|
||||
@@ -198,6 +199,7 @@ const CONFIG = {
|
||||
GONIO_MANUAL_GAIN_DB: -5,
|
||||
GONIO_AGC_ENABLED: false,
|
||||
GONIO_LINE_FADE_MS: 50,
|
||||
GONIO_PERSISTENCE_MODE: 'fast',
|
||||
PHASE_DISPLAY_GAIN_DB: 0,
|
||||
PHASE_AGC_ENABLED: false,
|
||||
PHASE_TRAIL_ENABLED: true,
|
||||
@@ -599,6 +601,8 @@ const PHOENIX_GLOBAL_OPTION_KEYS = Object.freeze([
|
||||
'CLOCK_LED_COLOR',
|
||||
'HEADER_TEXT_COLOR',
|
||||
'RTA_BAR_BASE_COLOR',
|
||||
'SPECTRO_GAMMA',
|
||||
'SPECTRO_SCROLL_MODE',
|
||||
'PEAK_HISTORY_SCROLL_MODE',
|
||||
'PEAK_HISTORY_FILL_ENABLED',
|
||||
'PEAK_HISTORY_FILL_INVERT',
|
||||
@@ -774,6 +778,14 @@ function loadConfig(opts = {}) {
|
||||
if (typeof saved.PPM_DIN_DECAY_DB_PER_S === 'number') CONFIG.PPM_DIN_DECAY_DB_PER_S = saved.PPM_DIN_DECAY_DB_PER_S;
|
||||
if (typeof saved.PPM_DIN_HOLD_MS === 'number') CONFIG.PPM_DIN_HOLD_MS = saved.PPM_DIN_HOLD_MS;
|
||||
if (CONFIG.RTA_BAR_LAYOUT === 'classic') CONFIG.RTA_BAR_LAYOUT = 'rtw';
|
||||
if (CONFIG.RTA_BAR_LAYOUT === 'rtw') {
|
||||
CONFIG.RTA_ENGINE = 'iir';
|
||||
CONFIG.RTA_BPO_MODE = '1_3';
|
||||
CONFIG.RTA_IIR_ORDER = 6;
|
||||
CONFIG.RTA_FREQ_RANGE = 'norm';
|
||||
const hold = Number(CONFIG.RTA_PEAK_HOLD_SEC);
|
||||
CONFIG.RTA_PEAK_HOLD_SEC = hold >= 3.25 ? 4.0 : 2.5;
|
||||
}
|
||||
if (!Number.isFinite(CONFIG.DBFS_TOP)) CONFIG.DBFS_TOP = CONFIG_DEFAULTS.DBFS_TOP;
|
||||
if (!Number.isFinite(CONFIG.DBFS_BOTTOM)) CONFIG.DBFS_BOTTOM = CONFIG_DEFAULTS.DBFS_BOTTOM;
|
||||
// Clamp to sensible bounds while keeping the user-selected display range.
|
||||
@@ -827,6 +839,14 @@ function loadConfig(opts = {}) {
|
||||
CONFIG.LR_FRACTIONAL_DELAY_SAMPLES = Math.max(-1.5, Math.min(1.5, Number(CONFIG.LR_FRACTIONAL_DELAY_SAMPLES)));
|
||||
CONFIG.PHOENIX_BASE_URL = normalizePhoenixBaseUrlForCurrentClient(CONFIG.PHOENIX_BASE_URL || CONFIG_DEFAULTS.PHOENIX_BASE_URL || DEFAULT_PHOENIX_BASE_URL);
|
||||
CONFIG.PPM_DIN_FAST_ATTACK = !!CONFIG.PPM_DIN_FAST_ATTACK;
|
||||
// Migrate stale profiles: detector ballistics are standards profiles,
|
||||
// not user-adjustable display preferences.
|
||||
CONFIG.PPM_DIN_ATTACK_MS = 10;
|
||||
CONFIG.PPM_DIN_DECAY_DB_PER_S = 20 / 1.5;
|
||||
CONFIG.PPM_DIN_HOLD_DECAY_DB_PER_S = 20 / 1.5;
|
||||
CONFIG.PPM_EBU_ATTACK_MS = 10;
|
||||
CONFIG.PPM_EBU_DECAY_DB_PER_S = 24 / 2.8;
|
||||
CONFIG.PPM_EBU_HOLD_DECAY_DB_PER_S = 24 / 2.8;
|
||||
CONFIG.HIFI_PEAK_ALIGNMENT = (CONFIG.HIFI_PEAK_ALIGNMENT === 'ppm_din_zero' || CONFIG.HIFI_PEAK_ALIGNMENT === 'dbfs_zero')
|
||||
? 'ppm_din_zero'
|
||||
: 'ppm_din_minus5';
|
||||
@@ -969,6 +989,10 @@ function buildPhoenixGlobalConfigPayload() {
|
||||
if (raw === 'stopwatch') return 'stopwatch';
|
||||
return fallback;
|
||||
};
|
||||
const normalizeSpectroScroll = (value) => {
|
||||
const number = Number(value);
|
||||
return [0.5, 1, 2, 4, 6].includes(number) ? number : 1;
|
||||
};
|
||||
const normalizePeakHistoryScroll = (value) => {
|
||||
const allowed = new Set([0.5, 1, 2, 4, 6]);
|
||||
const num = Number(value);
|
||||
@@ -990,11 +1014,11 @@ function buildPhoenixGlobalConfigPayload() {
|
||||
monoInput: !!CONFIG.MONO_INPUT,
|
||||
lrFractionalDelayEnabled: !!CONFIG.LR_FRACTIONAL_DELAY_ENABLED,
|
||||
lrFractionalDelaySamples: Number.isFinite(CONFIG.LR_FRACTIONAL_DELAY_SAMPLES) ? CONFIG.LR_FRACTIONAL_DELAY_SAMPLES : (CONFIG_DEFAULTS.LR_FRACTIONAL_DELAY_SAMPLES ?? 0.996),
|
||||
ppmDinAttackMs: Number.isFinite(CONFIG.PPM_DIN_ATTACK_MS) ? CONFIG.PPM_DIN_ATTACK_MS : (CONFIG_DEFAULTS.PPM_DIN_ATTACK_MS ?? 5),
|
||||
ppmDinDecayDbPerS: Number.isFinite(CONFIG.PPM_DIN_DECAY_DB_PER_S) ? CONFIG.PPM_DIN_DECAY_DB_PER_S : (CONFIG_DEFAULTS.PPM_DIN_DECAY_DB_PER_S ?? 11.8),
|
||||
ppmDinAttackMs: 10,
|
||||
ppmDinDecayDbPerS: 20 / 1.5,
|
||||
ppmDinFastAttack: !!CONFIG.PPM_DIN_FAST_ATTACK,
|
||||
ppmEbuAttackMs: Number.isFinite(CONFIG.PPM_EBU_ATTACK_MS) ? CONFIG.PPM_EBU_ATTACK_MS : (CONFIG_DEFAULTS.PPM_EBU_ATTACK_MS ?? 10),
|
||||
ppmEbuDecayDbPerS: Number.isFinite(CONFIG.PPM_EBU_DECAY_DB_PER_S) ? CONFIG.PPM_EBU_DECAY_DB_PER_S : (CONFIG_DEFAULTS.PPM_EBU_DECAY_DB_PER_S ?? 8.6),
|
||||
ppmEbuAttackMs: 10,
|
||||
ppmEbuDecayDbPerS: 24 / 2.8,
|
||||
lufsIWindowMin: Number.isFinite(CONFIG.LUFS_I_WINDOW_MIN) ? CONFIG.LUFS_I_WINDOW_MIN : (CONFIG_DEFAULTS.LUFS_I_WINDOW_MIN ?? 4),
|
||||
lufsINormEnabled: !!CONFIG.LUFS_I_NORM_ENABLED,
|
||||
ppmDinLoudnessBoxes: !!CONFIG.PPM_DIN_LOUDNESS_BOXES,
|
||||
@@ -1016,6 +1040,8 @@ function buildPhoenixGlobalConfigPayload() {
|
||||
clockLedColor: normalizeColor(CONFIG.CLOCK_LED_COLOR, CONFIG_DEFAULTS.CLOCK_LED_COLOR || '#ff0000'),
|
||||
headerTextColor: normalizeColor(CONFIG.HEADER_TEXT_COLOR, CONFIG_DEFAULTS.HEADER_TEXT_COLOR || '#ffe066'),
|
||||
rtaBarBaseColor: normalizeColor(CONFIG.RTA_BAR_BASE_COLOR, CONFIG_DEFAULTS.RTA_BAR_BASE_COLOR || '#ffe066'),
|
||||
spectroGamma: Number.isFinite(CONFIG.SPECTRO_GAMMA) ? Math.max(0.3, Math.min(1.2, CONFIG.SPECTRO_GAMMA)) : 0.9,
|
||||
spectroScrollMode: normalizeSpectroScroll(CONFIG.SPECTRO_SCROLL_MODE),
|
||||
peakHistoryScrollMode: normalizePeakHistoryScroll(CONFIG.PEAK_HISTORY_SCROLL_MODE),
|
||||
peakHistoryFillEnabled: !!CONFIG.PEAK_HISTORY_FILL_ENABLED,
|
||||
peakHistoryFillInvert: !!CONFIG.PEAK_HISTORY_FILL_INVERT,
|
||||
@@ -1063,6 +1089,10 @@ function applyPhoenixGlobalConfig(payload = {}) {
|
||||
if (raw === 'stopwatch') return 'stopwatch';
|
||||
return fallback;
|
||||
};
|
||||
const normalizeSpectroScroll = (value) => {
|
||||
const number = Number(value);
|
||||
return [0.5, 1, 2, 4, 6].includes(number) ? number : 1;
|
||||
};
|
||||
const fft = Number(payload.fftSize);
|
||||
if (Number.isFinite(fft)) {
|
||||
CONFIG.FFT_SIZE = (fft === 2048 || fft === 4096 || fft === 8192 || fft === 16384)
|
||||
@@ -1073,15 +1103,20 @@ function applyPhoenixGlobalConfig(payload = {}) {
|
||||
const mode = String(payload.rtaBpoMode || '').trim();
|
||||
CONFIG.RTA_BPO_MODE = (mode === '1_3' || mode === '1_6' || mode === '1_12') ? mode : '1_6';
|
||||
}
|
||||
const dinAttack = Number(payload.ppmDinAttackMs);
|
||||
if (Number.isFinite(dinAttack)) CONFIG.PPM_DIN_ATTACK_MS = Math.max(0.1, Math.min(100, dinAttack));
|
||||
const dinDecay = Number(payload.ppmDinDecayDbPerS);
|
||||
if (Number.isFinite(dinDecay)) CONFIG.PPM_DIN_DECAY_DB_PER_S = Math.max(0.1, Math.min(120, dinDecay));
|
||||
if (CONFIG.RTA_BAR_LAYOUT === 'rtw') {
|
||||
CONFIG.RTA_ENGINE = 'iir';
|
||||
CONFIG.RTA_BPO_MODE = '1_3';
|
||||
CONFIG.RTA_IIR_ORDER = 6;
|
||||
CONFIG.RTA_FREQ_RANGE = 'norm';
|
||||
}
|
||||
const spectroGamma = Number(payload.spectroGamma);
|
||||
if (Number.isFinite(spectroGamma)) CONFIG.SPECTRO_GAMMA = Math.max(0.3, Math.min(1.2, spectroGamma));
|
||||
if ('spectroScrollMode' in payload) CONFIG.SPECTRO_SCROLL_MODE = normalizeSpectroScroll(payload.spectroScrollMode);
|
||||
CONFIG.PPM_DIN_ATTACK_MS = 10;
|
||||
CONFIG.PPM_DIN_DECAY_DB_PER_S = 20 / 1.5;
|
||||
if ('ppmDinFastAttack' in payload) CONFIG.PPM_DIN_FAST_ATTACK = !!payload.ppmDinFastAttack;
|
||||
const ebuAttack = Number(payload.ppmEbuAttackMs);
|
||||
if (Number.isFinite(ebuAttack)) CONFIG.PPM_EBU_ATTACK_MS = Math.max(0.1, Math.min(100, ebuAttack));
|
||||
const ebuDecay = Number(payload.ppmEbuDecayDbPerS);
|
||||
if (Number.isFinite(ebuDecay)) CONFIG.PPM_EBU_DECAY_DB_PER_S = Math.max(0.1, Math.min(120, ebuDecay));
|
||||
CONFIG.PPM_EBU_ATTACK_MS = 10;
|
||||
CONFIG.PPM_EBU_DECAY_DB_PER_S = 24 / 2.8;
|
||||
const lufsWin = Number(payload.lufsIWindowMin);
|
||||
if (Number.isFinite(lufsWin)) CONFIG.LUFS_I_WINDOW_MIN = Math.max(1, Math.min(10, Math.round(lufsWin)));
|
||||
if ('lufsINormEnabled' in payload) CONFIG.LUFS_I_NORM_ENABLED = !!payload.lufsINormEnabled;
|
||||
|
||||
Reference in New Issue
Block a user