Fix NaN drift in VU

This commit is contained in:
Boof2015
2026-05-07 15:52:47 -04:00
parent 7fe64db788
commit 1de3e9eced
3 changed files with 48 additions and 8 deletions
+3 -2
View File
@@ -606,7 +606,7 @@ export class VUMeter {
x: number, y: number, _w: number, h: number,
db: number
): void {
const displayDb = Math.max(VU_METER_MIN_DB, Math.min(0, db))
const displayDb = Number.isFinite(db) ? Math.max(VU_METER_MIN_DB, Math.min(0, db)) : VU_METER_MIN_DB
const text = displayDb <= VU_METER_MIN_DB + 1 ? '-∞' : `${displayDb.toFixed(1)}`
ctx.fillStyle = alphaColor(this.options.labelColor, 0.8)
ctx.font = `${Math.min(20, Math.max(9, h * 0.55))}px "JetBrains Mono", monospace`
@@ -620,7 +620,7 @@ export class VUMeter {
x: number, y: number, w: number, h: number,
db: number
): void {
const displayDb = Math.max(VU_METER_MIN_DB, Math.min(0, db))
const displayDb = Number.isFinite(db) ? Math.max(VU_METER_MIN_DB, Math.min(0, db)) : VU_METER_MIN_DB
const text = displayDb <= VU_METER_MIN_DB + 1 ? '-∞' : `${displayDb.toFixed(1)}`
ctx.fillStyle = alphaColor(this.options.labelColor, 0.8)
ctx.font = `${Math.min(16, Math.max(8, h * 0.5))}px "JetBrains Mono", monospace`
@@ -1088,6 +1088,7 @@ export class VUMeter {
}
private formatNeedleDb(db: number): string {
if (!Number.isFinite(db)) return '-∞'
const displayDb = clamp(db, VU_METER_MIN_DB, VU_METER_MAX_DB)
return displayDb <= VU_METER_MIN_DB + 1 ? '-∞' : displayDb.toFixed(1)
}
+11 -5
View File
@@ -36,6 +36,9 @@ function clampSampleRate(sampleRate: number): number {
}
function amplitudeToDb(amplitude: number): number {
if (!Number.isFinite(amplitude) || amplitude <= 0) {
return VU_METER_MIN_DB
}
const db = 20 * Math.log10(Math.max(amplitude, 1e-10))
return Math.max(VU_METER_MIN_DB, Math.min(VU_METER_MAX_DB, db))
}
@@ -119,8 +122,11 @@ export class VUMeterBallistics {
const cross = left * right
if (this.sampleCount === this.integrationWindowSamples) {
this.sumSqL -= this.sqL[this.writeIndex]
this.sumSqR -= this.sqR[this.writeIndex]
// Clamp running sums to non-negative: floating-point cancellation in
// the slide-out subtraction can drift them by ~1e-15 below zero on
// near-silent content, which would propagate as NaN through sqrt.
this.sumSqL = Math.max(0, this.sumSqL - this.sqL[this.writeIndex])
this.sumSqR = Math.max(0, this.sumSqR - this.sqR[this.writeIndex])
this.sumCross -= this.cross[this.writeIndex]
} else {
this.sampleCount += 1
@@ -163,9 +169,9 @@ export class VUMeterBallistics {
return
}
const meanSqL = this.sumSqL / this.sampleCount
const meanSqR = this.sumSqR / this.sampleCount
const denominator = Math.sqrt(this.sumSqL * this.sumSqR)
const meanSqL = Math.max(0, this.sumSqL) / this.sampleCount
const meanSqR = Math.max(0, this.sumSqR) / this.sampleCount
const denominator = Math.sqrt(Math.max(0, this.sumSqL) * Math.max(0, this.sumSqR))
this.snapshot.vuLDb = amplitudeToDb(Math.sqrt(meanSqL))
this.snapshot.vuRDb = amplitudeToDb(Math.sqrt(meanSqR))