Bake window: derived note lengths carry exact durations, not ladder rungs — a long take is no longer cut at 384 beats
Hold keeps its picker. Also: one home for the %-fold, duration-ordered Hold travel, and a corrupt tail degrades to absent rather than fabricating one.
This commit is contained in:
+16
-40
@@ -2,13 +2,16 @@
|
||||
// Same fast assert loop as the sibling pure tests.
|
||||
//
|
||||
// Covers triggerPlayLength: zero play length, startFrame set, startFrame past frameCount,
|
||||
// rounding, and the Finding 1 regression (start-point set — the case that was broken before
|
||||
// this module existed); plus effectiveLengthFraction, the spline fold every consumer of the
|
||||
// span must go through.
|
||||
// rounding, the out-of-domain clamps that keep it identical to Voice::start's inline copy of
|
||||
// the same formula, and the Finding 1 regression (start-point set — the case that was broken
|
||||
// before this module existed). The spline fold that used to live here is now beside its
|
||||
// siblings in play_params.h, and pinned with them in test_spline_egs.
|
||||
|
||||
#include "../src/core/instrument/map/trigger_seam.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdio>
|
||||
#include <limits>
|
||||
|
||||
using namespace reasampler;
|
||||
using namespace reasampler::instrument::map;
|
||||
@@ -58,46 +61,19 @@ static void testPlayLengthRounding() {
|
||||
CHECK(triggerPlayLength(0.6, 3, 0) == 2);
|
||||
}
|
||||
|
||||
// --- effectiveLengthFraction --------------------------------------------------
|
||||
|
||||
// A drawn contour covers the FULL sample length, so the stored %-knob goes inert. It is not
|
||||
// cleared, though — a pre-spline value survives in the record, and every reader that takes it
|
||||
// raw plays, draws or bakes a fraction of the take.
|
||||
static void testDrawnEnvelopeFoldsTheFractionToOne() {
|
||||
PlayParams p;
|
||||
p.trigger.lengthFraction = 0.25;
|
||||
CHECK(effectiveLengthFraction(p) == 0.25); // staged: the knob is what it says
|
||||
|
||||
p.ampSpline.mode = EnvMode::Spline;
|
||||
CHECK(effectiveLengthFraction(p) == 1.0); // drawn: the whole take
|
||||
CHECK(p.trigger.lengthFraction == 0.25); // …and the stored value is untouched
|
||||
|
||||
// Flipping back restores the stored fraction, which is why the fold cannot be a write.
|
||||
p.ampSpline.mode = EnvMode::Staged;
|
||||
CHECK(effectiveLengthFraction(p) == 0.25);
|
||||
}
|
||||
|
||||
// The fold reads the SAME predicate the engine's Gate refusal does, gating flags included: a
|
||||
// Spline mode on a DISABLED pitch/filter envelope binds no cursor, so it must not fold.
|
||||
static void testDisabledEnvelopesDoNotFoldTheFraction() {
|
||||
PlayParams p;
|
||||
p.trigger.lengthFraction = 0.5;
|
||||
|
||||
p.pitchSpline.mode = EnvMode::Spline;
|
||||
CHECK(effectiveLengthFraction(p) == 0.5); // pitchEnv.enabled is still false
|
||||
p.pitchEnv.enabled = true;
|
||||
CHECK(effectiveLengthFraction(p) == 1.0);
|
||||
|
||||
p.pitchEnv.enabled = false;
|
||||
p.filterSpline.mode = EnvMode::Spline;
|
||||
CHECK(effectiveLengthFraction(p) == 0.5); // filter.enabled is still false
|
||||
p.filter.enabled = true;
|
||||
CHECK(effectiveLengthFraction(p) == 1.0);
|
||||
// The stored fraction is a wire double with no codec-side range check beyond finiteness, and
|
||||
// Voice::start clamps every one of these the same way. A span that ran past the source would
|
||||
// read off the end of the PCM; one derived from NaN would reach an undefined narrowing.
|
||||
static void testOutOfDomainFractionsClampToTheSpan() {
|
||||
CHECK(triggerPlayLength(1.5, 1000, 0) == 1000); // never past the post-start span
|
||||
CHECK(triggerPlayLength(1.5, 1000, 200) == 800);
|
||||
CHECK(triggerPlayLength(-0.5, 1000, 0) == 0);
|
||||
CHECK(triggerPlayLength(std::nan(""), 1000, 0) == 0);
|
||||
CHECK(triggerPlayLength(std::numeric_limits<double>::infinity(), 1000, 0) == 1000);
|
||||
}
|
||||
|
||||
int main() {
|
||||
testDrawnEnvelopeFoldsTheFractionToOne();
|
||||
testDisabledEnvelopesDoNotFoldTheFraction();
|
||||
testOutOfDomainFractionsClampToTheSpan();
|
||||
testPlayLengthNoStartPoint();
|
||||
testPlayLengthWithStartPoint();
|
||||
testPlayLengthZeroFrameCount();
|
||||
|
||||
Reference in New Issue
Block a user