Correct audio metering and realtime displays
This commit is contained in:
+34
-34
@@ -1,25 +1,12 @@
|
||||
// meters/tp.js — True Peak (dBTP) L/R mit nichtlinearer Skala, Warnschwelle und Glanzkante
|
||||
// meters/tp.js — True Peak (dBTP) L/R mit Übersteuerungsreserve bis +6 dBTP
|
||||
import { createPeakHoldState, stepPeakHold } from '../core/utils.js';
|
||||
import { drawHairlineGrid, METER_HEADER_FONT } from './scale_helpers.js';
|
||||
import { drawCachedStaticLayer } from './static_layer.js';
|
||||
import { TRUE_PEAK_MINOR_TICKS, TRUE_PEAK_SCALE } from './true_peak_scale.js';
|
||||
import { HEADER_BG, LABEL_COLOR, MID_COLOR, WARN_COLOR } from '../core/theme.js';
|
||||
|
||||
export const id = 'tp';
|
||||
|
||||
const TP_PERCENT_SCALE = [
|
||||
{ db: -60, percent: '0,00 %', frac: 0.0000 },
|
||||
{ db: -50, percent: '16,67 %', frac: 0.0373 },
|
||||
{ db: -40, percent: '33,33 %', frac: 0.1429 },
|
||||
{ db: -35, percent: '41,67 %', frac: 0.2112 },
|
||||
{ db: -30, percent: '50,00 %', frac: 0.2857 },
|
||||
{ db: -25, percent: '58,33 %', frac: 0.3851 },
|
||||
{ db: -20, percent: '66,67 %', frac: 0.4783 },
|
||||
{ db: -15, percent: '75,00 %', frac: 0.6087 },
|
||||
{ db: -10, percent: '83,33 %', frac: 0.7391 },
|
||||
{ db: -5, percent: '91,67 %', frac: 0.8696 },
|
||||
{ db: 0, percent: '100,00 %', frac: 1.0000 },
|
||||
];
|
||||
|
||||
export function initShared(CONFIG) {
|
||||
const now = performance.now();
|
||||
return {
|
||||
@@ -42,22 +29,22 @@ export function update(packet, shared) {
|
||||
shared.values.R = R + (shared.offset || 0);
|
||||
}
|
||||
|
||||
const LOG_MIN = TP_PERCENT_SCALE[0].db;
|
||||
const LOG_TOP = TP_PERCENT_SCALE[TP_PERCENT_SCALE.length - 1].db;
|
||||
const LOG_MIN = TRUE_PEAK_SCALE[0].db;
|
||||
const LOG_TOP = TRUE_PEAK_SCALE[TRUE_PEAK_SCALE.length - 1].db;
|
||||
|
||||
function interpolateFrac(db) {
|
||||
if (db <= TP_PERCENT_SCALE[0].db) return TP_PERCENT_SCALE[0].frac;
|
||||
if (db >= TP_PERCENT_SCALE[TP_PERCENT_SCALE.length - 1].db) return TP_PERCENT_SCALE[TP_PERCENT_SCALE.length - 1].frac;
|
||||
for (let i = 1; i < TP_PERCENT_SCALE.length; i++) {
|
||||
const prev = TP_PERCENT_SCALE[i - 1];
|
||||
const curr = TP_PERCENT_SCALE[i];
|
||||
if (db <= TRUE_PEAK_SCALE[0].db) return TRUE_PEAK_SCALE[0].frac;
|
||||
if (db >= TRUE_PEAK_SCALE[TRUE_PEAK_SCALE.length - 1].db) return TRUE_PEAK_SCALE[TRUE_PEAK_SCALE.length - 1].frac;
|
||||
for (let i = 1; i < TRUE_PEAK_SCALE.length; i++) {
|
||||
const prev = TRUE_PEAK_SCALE[i - 1];
|
||||
const curr = TRUE_PEAK_SCALE[i];
|
||||
if (db <= curr.db) {
|
||||
const span = curr.db - prev.db || 1;
|
||||
const t = (db - prev.db) / span;
|
||||
return prev.frac + t * (curr.frac - prev.frac);
|
||||
}
|
||||
}
|
||||
return TP_PERCENT_SCALE[TP_PERCENT_SCALE.length - 1].frac;
|
||||
return TRUE_PEAK_SCALE[TRUE_PEAK_SCALE.length - 1].frac;
|
||||
}
|
||||
|
||||
export function draw(g, rect, CONFIG, shared) {
|
||||
@@ -122,13 +109,30 @@ export function draw(g, rect, CONFIG, shared) {
|
||||
g.font = prevFont;
|
||||
g.restore();
|
||||
const yFloor = mapY(LOG_MIN);
|
||||
const configuredRedStart = Number(CONFIG.TP_RED_START);
|
||||
const redStart = Math.max(LOG_MIN, Math.min(LOG_TOP, Number.isFinite(configuredRedStart) ? configuredRedStart : -1));
|
||||
const yRed = mapY(redStart);
|
||||
const innerW = Math.max(2, barW - 2);
|
||||
const colNorm = CONFIG.TP_COLOR_NORMAL || MID_COLOR;
|
||||
const colWarn = CONFIG.TP_COLOR_WARN || WARN_COLOR;
|
||||
const redOnly = CONFIG.TP_RED_BAR_ONLY !== false;
|
||||
|
||||
const drawBar = (x0, val) => {
|
||||
const yVal = mapY(val);
|
||||
const colNorm = CONFIG.TP_COLOR_NORMAL;
|
||||
g.fillStyle = colNorm;
|
||||
g.fillRect(x0 + 1, yVal, innerW, Math.max(0, yFloor - yVal));
|
||||
if (val > redStart) {
|
||||
if (redOnly) {
|
||||
g.fillStyle = colNorm;
|
||||
g.fillRect(x0 + 1, yRed, innerW, Math.max(0, yFloor - yRed));
|
||||
g.fillStyle = colWarn;
|
||||
g.fillRect(x0 + 1, yVal, innerW, Math.max(0, yRed - yVal));
|
||||
} else {
|
||||
g.fillStyle = colWarn;
|
||||
g.fillRect(x0 + 1, yVal, innerW, Math.max(0, yFloor - yVal));
|
||||
}
|
||||
} else {
|
||||
g.fillStyle = colNorm;
|
||||
g.fillRect(x0 + 1, yVal, innerW, Math.max(0, yFloor - yVal));
|
||||
}
|
||||
// Glanzkante
|
||||
g.globalAlpha = .12;
|
||||
g.fillStyle = '#fff';
|
||||
@@ -211,9 +215,6 @@ function drawTpStaticOverlay(g, shared, rect, CONFIG, geom, mapY) {
|
||||
});
|
||||
}
|
||||
|
||||
// Balken-Overlay-Ticks auf Basis der Vintage-Prozent-Skala
|
||||
const EXTRA_MINOR_TICKS = [-47, -19, -18, -17, -16, -14, -13, -12, -11, -9, -8, -7, -6, -4, -3, -2, -1];
|
||||
|
||||
function drawOverlayTicksLR(g, leftX, rightX, widthPx, mapY, alignmentTick = null) {
|
||||
if (!g) return;
|
||||
|
||||
@@ -254,14 +255,14 @@ function drawOverlayTicksLR(g, leftX, rightX, widthPx, mapY, alignmentTick = nul
|
||||
g.beginPath(); g.moveTo(x1R, yPix); g.lineTo(x2R, yPix); g.stroke();
|
||||
};
|
||||
|
||||
for (const point of TP_PERCENT_SCALE) {
|
||||
for (const point of TRUE_PEAK_SCALE) {
|
||||
const y = Math.round(mapY(point.db)) + 0.5;
|
||||
const isHighlight = highlightValue !== null && approx(point.db, highlightValue);
|
||||
if (isHighlight) highlightMatched = true;
|
||||
drawMajor(y, isHighlight);
|
||||
}
|
||||
|
||||
for (const db of EXTRA_MINOR_TICKS) {
|
||||
for (const db of TRUE_PEAK_MINOR_TICKS) {
|
||||
const y = Math.round(mapY(db)) + 0.5;
|
||||
const isHighlight = highlightValue !== null && approx(db, highlightValue);
|
||||
if (isHighlight) highlightMatched = true;
|
||||
@@ -289,11 +290,10 @@ function drawScale(g, colRect, centerX, mapY, CONFIG) {
|
||||
g.textAlign = 'center';
|
||||
g.textBaseline = 'alphabetic';
|
||||
|
||||
for (const point of TP_PERCENT_SCALE) {
|
||||
for (const point of TRUE_PEAK_SCALE) {
|
||||
const y = mapY(point.db);
|
||||
if (y < colRect.y || y > colRect.y + colRect.h) continue;
|
||||
const value = Math.abs(point.db);
|
||||
const dbLabel = Number.isInteger(value) ? String(value) : value.toFixed(1);
|
||||
const dbLabel = point.db > 0 ? `+${point.db}` : String(point.db);
|
||||
g.fillText(dbLabel, centerX, y + 5);
|
||||
}
|
||||
g.font = prevFont;
|
||||
|
||||
Reference in New Issue
Block a user