fix: pin the waveform arbitration in a testable predicate, close round-4 review minors
Extracts resolveWaveformClaim (core/instrument/ui/spline_edit) so the shell's node/tab/marker click resolution is unit-tested directly, not just its input geometry; folds the staged-envelope node into it; fixes comment accuracy, a cost regression, and test fidelity issues.
This commit is contained in:
@@ -363,6 +363,33 @@ static void testFlatZeroFinalSegmentStillFreesTheVoiceEarly() {
|
||||
CHECK(!v.soundingNote()); // a genuine permanent terminus, not a mid-contour dip
|
||||
}
|
||||
|
||||
// The timing, not just the fact: the case above is trivially "early" (a wholly-flat contour
|
||||
// frees on frame 0), which can't distinguish "frees early" from "frees at the right frame." This
|
||||
// fixture's final segment starts MID-sample, so the free must land there, not at frame 0 and not
|
||||
// at the sample's natural end. The breakpoint (phase 0.5495) is deliberately off every sampled
|
||||
// frame's exact phase (k/1000), so no sampled frame lands on the segment boundary itself and
|
||||
// which segment "owns" that frame is never ambiguous.
|
||||
static void testFlatZeroFinalSegmentFreesTheVoiceWhereItBeginsNotAtFrameZero() {
|
||||
const double breakpointPhase = 0.5495;
|
||||
const VelocityCurve contour = VelocityCurve::fromPoints(
|
||||
{{xAt(0.0), 1.0}, {xAt(breakpointPhase), 0.0}, {xAt(1.0), 0.0}}, CurveDomain::Unipolar);
|
||||
const std::size_t frames = 1000;
|
||||
const SampleData s = splineAmpSample(frames, contour);
|
||||
|
||||
Voice v;
|
||||
v.start(60, 100, s);
|
||||
// Frames 0..549 (phase < breakpoint) sit on the declining first segment: still sounding.
|
||||
for (std::size_t i = 0; i < 550; ++i) {
|
||||
v.renderFrame();
|
||||
CHECK(v.soundingNote());
|
||||
}
|
||||
// Frame 550 (phase 0.55) is the first sampled frame past the breakpoint, on the flat-zero
|
||||
// final segment — this is where the early-free fires.
|
||||
const double y550 = v.renderFrame();
|
||||
CHECK(near(y550, 0.0, 1e-9));
|
||||
CHECK(!v.soundingNote());
|
||||
}
|
||||
|
||||
// --- 9. A fresh spline EG opens on the smooth y = 1 - x ----------------------
|
||||
|
||||
static void testAFreshSplineEgDefaultsToTheSmoothDownwardSlope() {
|
||||
@@ -532,6 +559,7 @@ int main() {
|
||||
testAContourReplaysProportionallyOnADifferentLengthSample();
|
||||
testTwoPointContourRisingFromZeroSoundsForItsFullSpan();
|
||||
testFlatZeroFinalSegmentStillFreesTheVoiceEarly();
|
||||
testFlatZeroFinalSegmentFreesTheVoiceWhereItBeginsNotAtFrameZero();
|
||||
testAFreshSplineEgDefaultsToTheSmoothDownwardSlope();
|
||||
testGateIsUnavailableWhileASplineEgIsActiveAndReturnsAfterwards();
|
||||
testEnforceGateUnavailableWhileDrawnForcesTriggerOnBothRepresentations();
|
||||
|
||||
Reference in New Issue
Block a user