fix: apply dB compression to waveform thumbnail display

Linear amplitude-to-pixel mapping made -20 dBFS content reach only
10% of cell height and -40 dBFS round to zero. Replace with a dB
scale (floor kDisplayFloorDb = -60 dB, in bank_grid.h) so quiet
content is visible. Pure helper compressAmplitudeForDisplay() lives
in bank_grid; drawThumbnail() calls it. Five new unit tests cover
full-scale, zero, mid-levels, floor clamping, and sign preservation.
This commit is contained in:
2026-07-23 20:21:55 -04:00
parent b9046b2842
commit b3be9799e0
4 changed files with 100 additions and 2 deletions
+53
View File
@@ -15,6 +15,7 @@
#include "../src/bank_grid.h"
#include <cmath>
#include <cstdio>
#include <string>
#include <vector>
@@ -322,6 +323,52 @@ static void testNavDegenerate() {
CHECK(selEq(navigate(Selection{{0}, 0, 0}, NavKey::Down, 0, 4, false), {1}, 1, 1));
}
// --- compressAmplitudeForDisplay ----------------------------------------------
// Full scale: magnitude 1.0 must reach the full display fraction exactly.
static void testCompressFullScale() {
CHECK(compressAmplitudeForDisplay(1.0f) == 1.0f);
CHECK(compressAmplitudeForDisplay(-1.0f) == -1.0f);
}
// Exact zero must stay on the midline (no log of zero; guards the singularity).
static void testCompressZeroIsMidline() {
CHECK(compressAmplitudeForDisplay(0.0f) == 0.0f);
}
// -20 dB (0.1 linear) and -40 dB (0.01 linear) must both produce clearly visible
// (non-zero) fractions, with -20 dB > -40 dB (monotonic), and both well above
// the midline (arbitrary threshold of 0.15 chosen conservatively — at a -60 dB
// floor, -20 dB normalizes to 2/3 and -40 dB to 1/3).
static void testCompressMidValuesVisible() {
const float f20 = compressAmplitudeForDisplay(0.1f); // -20 dBFS
const float f40 = compressAmplitudeForDisplay(0.01f); // -40 dBFS
CHECK(f20 > 0.15f); // clearly non-zero
CHECK(f40 > 0.15f); // clearly non-zero
CHECK(f20 > f40); // monotonic: louder -> taller bar
}
// At and below the floor (-60 dB = 0.001 linear) the result is ~0 (silence).
// We test at exactly the floor magnitude and well below it.
static void testCompressAtAndBelowFloor() {
// 0.001 == 10^(-60/20) is the floor ratio. Magnitude at or below it -> 0.
const float floorMag = std::pow(10.0f, kDisplayFloorDb / 20.0f); // ~0.001
CHECK(compressAmplitudeForDisplay(floorMag) == 0.0f);
CHECK(compressAmplitudeForDisplay(floorMag * 0.5f) == 0.0f);
CHECK(compressAmplitudeForDisplay(0.0001f) == 0.0f);
}
// Sign is preserved: negative input produces a negative fraction of the same
// magnitude as its positive counterpart.
static void testCompressSignPreserved() {
const float pos = compressAmplitudeForDisplay(0.1f);
const float neg = compressAmplitudeForDisplay(-0.1f);
CHECK(neg < 0.0f);
// Magnitudes must be equal (sign-symmetric).
const float diff = pos + neg; // pos - |neg|
CHECK(diff > -0.001f && diff < 0.001f);
}
int main() {
testColumnsForWidth();
testTooNarrowClampsToOneColumn();
@@ -355,6 +402,12 @@ int main() {
testNavFromEmptyFocusesFirst();
testNavDegenerate();
testCompressFullScale();
testCompressZeroIsMidline();
testCompressMidValuesVisible();
testCompressAtAndBelowFloor();
testCompressSignPreserved();
if (g_fail == 0) std::printf("All tests passed.\n");
return g_fail ? 1 : 0;
}