instrument: the filter's velocity depth knob returns and multiplies the bipolar curve; the pre-v12 lift is a pure domain re-tag
This commit is contained in:
@@ -4,8 +4,8 @@
|
||||
// * eval — flat y=1 unipolar default (EVERY velocity -> 1.0), linear ramp, curved shape
|
||||
// between points, box-clamp of an out-of-range velocity, monotonic-in-x over the whole domain.
|
||||
// * the BIPOLAR domain — zero() is exactly 0 everywhere, the negative half evaluates and clamps
|
||||
// at -1, eval is homogeneous in y (what the pre-v12 filter lift rests on), and the pixel maps
|
||||
// put value 0 on the box's centre line rather than its floor.
|
||||
// at -1, knots inside [0,1] evaluate identically in either domain (what the codec's v12
|
||||
// re-tag rests on), and the pixel maps put value 0 on the box's centre line, not its floor.
|
||||
// * editing — addPoint keeps X-order + box-clamp; movePoint clamps an interior point between its
|
||||
// neighbours (can't cross) and box-clamps the value; endpoints are X-pinned (velocity 0 / 127)
|
||||
// with only the value mobile; deletePoint removes interior points but REFUSES the two endpoints.
|
||||
@@ -333,19 +333,16 @@ static void testUnipolarClampsAtZeroWhereBipolarDoesNot() {
|
||||
CHECK(near(b2.eval(127), 1.0));
|
||||
}
|
||||
|
||||
static void testEvalIsHomogeneousInY() {
|
||||
// The property the pre-v12 filter lift rests on: scaling every knot's y by k scales the
|
||||
// whole evaluated curve by k. Asserted against a CURVED (non-collinear) knot set, where
|
||||
// the Fritsch-Carlson tangents are actually doing work.
|
||||
static void testTheSameKnotsEvaluateIdenticallyInEitherDomain() {
|
||||
// What the codec's v12 domain re-tag rests on: a curve whose y values all lie in [0,1] is
|
||||
// read the same way in either domain — the domain governs the CLAMP, not the evaluation.
|
||||
// Asserted against a CURVED (non-collinear) knot set, where the tangents are doing work,
|
||||
// and with ==: the re-tag is bit-identical, not merely close.
|
||||
const std::vector<VelocityPoint> knots = {
|
||||
{0.0, 0.1}, {30.0, 0.15}, {64.0, 0.9}, {100.0, 0.4}, {127.0, 1.0}};
|
||||
const VelocityCurve base = VelocityCurve::fromPoints(knots, CurveDomain::Unipolar);
|
||||
for (const double k : {0.75, -0.4, 1.0}) {
|
||||
std::vector<VelocityPoint> scaled = knots;
|
||||
for (VelocityPoint& p : scaled) p.value *= k;
|
||||
const VelocityCurve s = VelocityCurve::fromPoints(scaled, CurveDomain::Bipolar);
|
||||
for (int v = 0; v <= 127; ++v) CHECK(near(s.eval(v), k * base.eval(v), 1e-12));
|
||||
}
|
||||
const VelocityCurve u = VelocityCurve::fromPoints(knots, CurveDomain::Unipolar);
|
||||
const VelocityCurve b = VelocityCurve::fromPoints(knots, CurveDomain::Bipolar);
|
||||
for (int v = 0; v <= 127; ++v) CHECK(b.eval(v) == u.eval(v));
|
||||
}
|
||||
|
||||
static void testBipolarPixelMapPutsZeroOnTheCentreLine() {
|
||||
@@ -471,7 +468,7 @@ int main() {
|
||||
testZeroIsExactlyZeroAtEveryVelocity();
|
||||
testBipolarEvalSpansTheNegativeHalf();
|
||||
testUnipolarClampsAtZeroWhereBipolarDoesNot();
|
||||
testEvalIsHomogeneousInY();
|
||||
testTheSameKnotsEvaluateIdenticallyInEitherDomain();
|
||||
testBipolarPixelMapPutsZeroOnTheCentreLine();
|
||||
testBipolarDragCoversTwiceTheValueRange();
|
||||
testPixelFromPointMapsCornersAndMidpoint();
|
||||
|
||||
Reference in New Issue
Block a user