Correct audio metering and realtime displays
This commit is contained in:
+11
-57
@@ -1,6 +1,7 @@
|
||||
// views/peak_history.js - Meter-Verlauf (rechter Slot) mit RTA-Layout
|
||||
|
||||
import { FRAME_COLOR, GRID_MAJOR_COLOR, GRID_MINOR_COLOR, LABEL_COLOR, MID_COLOR, PANEL_BG, WARN_COLOR } from '../core/theme.js';
|
||||
import { TRUE_PEAK_SCALE } from '../meters/true_peak_scale.js';
|
||||
|
||||
const PLOT = { left: 43, top: 70, right: 0, bottom: 18 };
|
||||
const METER_WIDTH = 140;
|
||||
@@ -47,24 +48,10 @@ const DIN_SCALE = [
|
||||
{ db: +5, pos: 1.0000 },
|
||||
];
|
||||
|
||||
const TP_PERCENT_SCALE = [
|
||||
{ db: -60, frac: 0.0000 },
|
||||
{ db: -50, frac: 0.0373 },
|
||||
{ db: -40, frac: 0.1429 },
|
||||
{ db: -35, frac: 0.2112 },
|
||||
{ db: -30, frac: 0.2857 },
|
||||
{ db: -25, frac: 0.3851 },
|
||||
{ db: -20, frac: 0.4783 },
|
||||
{ db: -15, frac: 0.6087 },
|
||||
{ db: -10, frac: 0.7391 },
|
||||
{ db: -5, frac: 0.8696 },
|
||||
{ db: 0, frac: 1.0000 },
|
||||
];
|
||||
|
||||
const VU_TICKS = [-20, -10, -7, -5, -3, 0, 1, 2, 3];
|
||||
const PPM_DIN_TICKS = [-50, -40, -30, -20, -10, -5, 0, 5];
|
||||
const PPM_EBU_TICKS = [-12, -8, -4, 0, 4, 8, 12];
|
||||
const TP_TICKS = [-60, -50, -40, -30, -20, -10, 0];
|
||||
const TP_TICKS = [-60, -50, -40, -30, -20, -10, 0, 3, 6];
|
||||
const RMS_DBFS_TICKS = [0, -6, -12, -18, -24, -30, -40, -60];
|
||||
const RMS_DBU_TICKS = [24, 20, 10, 0, -10, -20, -30, -40, -50, -60];
|
||||
const LUFS_TICKS = [-50, -40, -30, -23, -18, -10, -5];
|
||||
@@ -91,7 +78,6 @@ export function init() {
|
||||
meterLabel: '',
|
||||
neutralNorm: 0,
|
||||
neutralValue: 0,
|
||||
rmsSmooth: null,
|
||||
staticLayer: null,
|
||||
};
|
||||
}
|
||||
@@ -605,7 +591,6 @@ async function drawMeter(env, plotX, plotY, plotW, plotH, meterRects = null) {
|
||||
function resolveMeterInfo(env, state, meterId) {
|
||||
const cfg = env.config || {};
|
||||
const shared = env.meters?.getState?.(meterId) || null;
|
||||
if (meterId !== 'rms') state.rmsSmooth = null;
|
||||
|
||||
switch (meterId) {
|
||||
case 'ppm-din':
|
||||
@@ -615,7 +600,7 @@ function resolveMeterInfo(env, state, meterId) {
|
||||
case 'tp':
|
||||
return sampleTp(cfg, shared);
|
||||
case 'rms':
|
||||
return sampleRms(cfg, shared, state);
|
||||
return sampleRms(cfg, shared);
|
||||
case 'lufs':
|
||||
return sampleLufs(cfg, shared);
|
||||
case 'vu':
|
||||
@@ -715,8 +700,8 @@ function samplePpmEbu(cfg, shared) {
|
||||
}
|
||||
|
||||
function sampleTp(cfg, shared) {
|
||||
const bottom = TP_PERCENT_SCALE[0].db;
|
||||
const top = TP_PERCENT_SCALE[TP_PERCENT_SCALE.length - 1].db;
|
||||
const bottom = TRUE_PEAK_SCALE[0].db;
|
||||
const top = TRUE_PEAK_SCALE[TRUE_PEAK_SCALE.length - 1].db;
|
||||
const effOff = Number(cfg?.TP_OFFSET_DB) || 0;
|
||||
const offCorr = effOff - (shared?.offset || 0);
|
||||
const warnVal = Number.isFinite(cfg?.TP_RED_START) ? cfg.TP_RED_START : -1;
|
||||
@@ -740,21 +725,21 @@ function sampleTp(cfg, shared) {
|
||||
});
|
||||
}
|
||||
|
||||
function sampleRms(cfg, shared, state) {
|
||||
function sampleRms(cfg, shared) {
|
||||
const mode = String(cfg?.RMS_MODE || 'dbfs').toLowerCase();
|
||||
const isDBU = mode === 'dbu';
|
||||
const bottom = -60;
|
||||
const top = isDBU ? 24 : 0;
|
||||
const refDbfs = Number.isFinite(cfg?.RMS_REF_DBFS_FOR_REF_DBU) ? cfg.RMS_REF_DBFS_FOR_REF_DBU : -18;
|
||||
const refDbu = Number.isFinite(cfg?.RMS_REF_DBU) ? cfg.RMS_REF_DBU : 0;
|
||||
const offset = Number.isFinite(cfg?.RMS_OFFSET_DB) ? cfg.RMS_OFFSET_DB : 0;
|
||||
const warnVal = Number.isFinite(cfg?.RMS_RED_START)
|
||||
? cfg.RMS_RED_START
|
||||
: (isDBU ? 20 : 0);
|
||||
const vL = Number.isFinite(shared?.values?.L) ? shared.values.L : bottom;
|
||||
const vR = Number.isFinite(shared?.values?.R) ? shared.values.R : bottom;
|
||||
const base = Math.max(vL, vR);
|
||||
const smoothed = applyRmsSmoothing(state, base, cfg);
|
||||
const display = isDBU ? (smoothed - refDbfs + refDbu) : smoothed;
|
||||
const base = Math.max(vL, vR) + offset;
|
||||
const display = isDBU ? (base - refDbfs + refDbu) : base;
|
||||
const val = clamp(display, bottom, top);
|
||||
const toNorm = (db) => {
|
||||
const c = clamp(db, bottom, top);
|
||||
@@ -778,43 +763,12 @@ function sampleRms(cfg, shared, state) {
|
||||
toNorm,
|
||||
range: { bottom, top },
|
||||
ticks: isDBU ? RMS_DBU_TICKS : RMS_DBFS_TICKS,
|
||||
signature: ['rms', mode, refDbfs, refDbu, cfg?.RMS_TC_MODE, cfg?.RMS_TC_MS].join('|'),
|
||||
signature: ['rms', mode, refDbfs, refDbu, offset, cfg?.RMS_TC_MODE].join('|'),
|
||||
hasValue: !!shared,
|
||||
warnValue: warnVal,
|
||||
});
|
||||
}
|
||||
|
||||
function applyRmsSmoothing(state, value, cfg) {
|
||||
const tauMs = resolveRmsTau(cfg);
|
||||
if (!Number.isFinite(tauMs) || tauMs <= 0) {
|
||||
state.rmsSmooth = null;
|
||||
return value;
|
||||
}
|
||||
const now = performance.now();
|
||||
if (!state.rmsSmooth || !Number.isFinite(state.rmsSmooth.value)) {
|
||||
state.rmsSmooth = { value, lastTs: now };
|
||||
return value;
|
||||
}
|
||||
const dt = Math.max(1 / 240, (now - (state.rmsSmooth.lastTs || now)) / 1000);
|
||||
state.rmsSmooth.lastTs = now;
|
||||
const alpha = 1 - Math.exp(-dt / (tauMs / 1000));
|
||||
state.rmsSmooth.value += alpha * (value - state.rmsSmooth.value);
|
||||
return state.rmsSmooth.value;
|
||||
}
|
||||
|
||||
function resolveRmsTau(cfg = {}) {
|
||||
const mode = String(cfg.RMS_TC_MODE || 'fast').toLowerCase();
|
||||
const custom = Number(cfg.RMS_TC_MS);
|
||||
if (Number.isFinite(custom) && custom > 0) return custom;
|
||||
switch (mode) {
|
||||
case 'impulse': return 35;
|
||||
case 'slow': return 1000;
|
||||
case 'none': return 0;
|
||||
case 'fast':
|
||||
default: return 125;
|
||||
}
|
||||
}
|
||||
|
||||
function sampleLufs(cfg, shared) {
|
||||
const bottom = -50;
|
||||
const top = -5;
|
||||
@@ -888,7 +842,7 @@ function interpolateScale(table, db) {
|
||||
}
|
||||
|
||||
function interpolateTp(db) {
|
||||
return interpolateScale(TP_PERCENT_SCALE, db);
|
||||
return interpolateScale(TRUE_PEAK_SCALE, db);
|
||||
}
|
||||
|
||||
function deflectionFrac(db) {
|
||||
|
||||
Reference in New Issue
Block a user