Close derived-bake-window review findings: NaN-guard remaining wire doubles, pin Trigger-span agreement, retire dead quantizer

Guards params_payload.cpp's filter-tail seconds and both keyTrack sites against NaN; pins Voice::start's Trigger-span formula against trigger_seam; retires unused shortestDivisionAtLeast.
This commit is contained in:
2026-08-01 21:32:05 -04:00
parent 65f6070348
commit eb6093e085
7 changed files with 84 additions and 92 deletions
+2 -51
View File
@@ -3,15 +3,13 @@
//
// Covers: the beat length of all 39 divisions against a literal rung table (NOT the module's
// own exponent formula); the 1/64 and 64/1 extremes; the four named example divisions; the
// label notation; picker order and index round-trip; off-ladder clamping of BOTH persisted
// fields, measured through the readers rather than by comparing two clamped values; and
// shortestDivisionAtLeast's never-short contract across the rung boundaries.
// label notation; picker order and index round-trip; and off-ladder clamping of BOTH persisted
// fields, measured through the readers rather than by comparing two clamped values.
#include "../src/core/instrument/note/musical_division.h"
#include <cmath>
#include <cstdio>
#include <limits>
using namespace reasampler::instrument::note;
@@ -206,54 +204,7 @@ static void testOutOfRangeIndexClampsIntoTheSet() {
CHECK(divisionAt(kDivisionCount) == divisionAt(kDivisionCount - 1));
}
// --- shortestDivisionAtLeast --------------------------------------------------
// The contract is never-short: whatever comes back is at least the requested length, and
// nothing shorter on the ladder also is. Swept over every rung and over the gaps between them.
static void testShortestAtLeastIsNeverShortAndNeverLonger() {
for (int i = 0; i < kDivisionCount; ++i) {
const double target = divisionBeats(divisionAt(i));
for (const double want : {target, target * 0.99, target * 0.5}) {
const Division got = shortestDivisionAtLeast(want);
CHECK(divisionBeats(got) >= want - 1e-12);
// Nothing on the ladder is both long enough and shorter than the answer.
for (int j = 0; j < kDivisionCount; ++j) {
const double other = divisionBeats(divisionAt(j));
CHECK(!(other >= want && other < divisionBeats(got) - 1e-12));
}
}
}
}
// Picker order is NOT length order — a rung's triplet is shorter than the previous rung's
// dotted — so the answer is not simply "the next index up".
static void testShortestAtLeastCrossesRungBoundaries() {
// 5 beats: the 2/1 triplet (8 * 2/3 == 5.33) beats the dotted half (6) above it.
CHECK(shortestDivisionAtLeast(5.0) == makeDivision(3, DivisionModifier::Triplet));
// An exact rung length answers with that rung, not the one above it.
CHECK(shortestDivisionAtLeast(4.0) == makeDivision(2, DivisionModifier::Straight));
}
// Degenerate inputs land on an end rather than anywhere in the middle.
static void testShortestAtLeastDegenerateInputs() {
CHECK(shortestDivisionAtLeast(0.0) == divisionAt(0));
CHECK(shortestDivisionAtLeast(-10.0) == divisionAt(0));
// Past the longest programmable note (the dotted top rung), the top rung is the answer.
const Division longest = makeDivision(kMaxQuarterExponent, DivisionModifier::Dotted);
CHECK(almostEqual(divisionBeats(longest), kMaxDivisionBeats));
CHECK(shortestDivisionAtLeast(kMaxDivisionBeats * 2.0) == longest);
// A non-finite request names no length to be at least, so it takes the SAME never-short
// answer as one nothing covers. Landing on the bottom rung instead would turn a corrupt
// value into a near-instant note.
CHECK(shortestDivisionAtLeast(std::nan("")) == longest);
CHECK(shortestDivisionAtLeast(std::numeric_limits<double>::infinity()) == longest);
}
int main() {
testShortestAtLeastIsNeverShortAndNeverLonger();
testShortestAtLeastCrossesRungBoundaries();
testShortestAtLeastDegenerateInputs();
testLadderSpansSixtyfourthToSixtyFourWhole();
testEveryStraightRungHasItsWrittenBeatLength();
testDottedIsHalfAgainAndTripletIsTwoThirds();