sfizz/tests/CurveT.cpp
2020-03-15 02:09:40 +01:00

196 lines
8 KiB
C++

// SPDX-License-Identifier: BSD-2-Clause
// This code is part of the sfizz library and is licensed under a BSD 2-clause
// license. You should have receive a LICENSE.md file along with the code.
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
#include "sfizz/Curve.h"
#include "sfizz/Opcode.h"
#include "catch2/catch.hpp"
#include <algorithm>
using namespace Catch::literals;
TEST_CASE("[Curve] Bipolar 0 to 1")
{
auto curve = sfz::Curve::buildPredefinedCurve(0);
REQUIRE( curve.evalCC7(0) == 0.0f );
REQUIRE( curve.evalCC7(127) == 1.0f );
REQUIRE( curve.evalCC7(2) == Approx(0.0157).margin(1e-3) );
REQUIRE( curve.evalCC7(63) == Approx(0.496).margin(1e-3) );
REQUIRE( curve.evalCC7(85) == Approx(0.669).margin(1e-3) );
REQUIRE( curve.evalNormalized(0.0f) == 0.0f );
REQUIRE( curve.evalNormalized(1.0f) == 1.0f );
REQUIRE( curve.evalNormalized(0.3f) == Approx(0.299).margin(1e-3) );
}
TEST_CASE("[Curve] Bipolar -1 to 1")
{
auto curve = sfz::Curve::buildPredefinedCurve(1);
REQUIRE( curve.evalCC7(0) == -1.0f );
REQUIRE( curve.evalCC7(127) == 1.0f );
REQUIRE( curve.evalCC7(2) == Approx(-0.9685).margin(1e-3) );
REQUIRE( curve.evalCC7(63) == Approx(-0.00787).margin(1e-5) );
REQUIRE( curve.evalCC7(85) == Approx(0.3386).margin(1e-3) );
REQUIRE( curve.evalNormalized(0.0f) == -1.0f );
REQUIRE( curve.evalNormalized(1.0f) == 1.0f );
REQUIRE( curve.evalNormalized(0.3f) == Approx(-0.402).margin(1e-3) );
}
TEST_CASE("[Curve] Bipolar 1 to 0")
{
auto curve = sfz::Curve::buildPredefinedCurve(2);
REQUIRE( curve.evalCC7(0) == 1.0f );
REQUIRE( curve.evalCC7(127) == 0.0f );
REQUIRE( curve.evalCC7(2) == Approx(0.984).margin(1e-3) );
REQUIRE( curve.evalCC7(63) == Approx(0.504).margin(1e-3) );
REQUIRE( curve.evalCC7(85) == Approx(0.331).margin(1e-3) );
REQUIRE( curve.evalNormalized(0.0f) == 1.0f );
REQUIRE( curve.evalNormalized(1.0f) == 0.0f );
REQUIRE( curve.evalNormalized(0.3f) == Approx(0.701).margin(1e-3) );
}
TEST_CASE("[Curve] Bipolar 1 to -1")
{
auto curve = sfz::Curve::buildPredefinedCurve(3);
REQUIRE( curve.evalCC7(0) == 1.0f );
REQUIRE( curve.evalCC7(127) == -1.0f );
REQUIRE( curve.evalCC7(2) == Approx(0.9685).margin(1e-3) );
REQUIRE( curve.evalCC7(63) == Approx(0.00787).margin(1e-5) );
REQUIRE( curve.evalCC7(85) == Approx(-0.3386).margin(1e-3) );
REQUIRE( curve.evalNormalized(0.0f) == 1.0f );
REQUIRE( curve.evalNormalized(1.0f) == -1.0f );
REQUIRE( curve.evalNormalized(0.3f) == Approx(0.402).margin(1e-3) );
}
TEST_CASE("[Curve] x**2")
{
auto curve = sfz::Curve::buildPredefinedCurve(4);
REQUIRE( curve.evalCC7(0) == 0.0f );
REQUIRE( curve.evalCC7(127) == 1.0f );
REQUIRE( curve.evalCC7(2) == Approx(0.000248).margin(1e-5) );
REQUIRE( curve.evalCC7(63) == Approx(0.246).margin(1e-3) );
REQUIRE( curve.evalCC7(85) == Approx(0.448).margin(1e-3) );
REQUIRE( curve.evalNormalized(0.0f) == 0.0f );
REQUIRE( curve.evalNormalized(1.0f) == 1.0f );
REQUIRE( curve.evalNormalized(0.3f) == Approx(0.09).margin(1e-3) );
}
TEST_CASE("[Curve] sqrt(x)")
{
auto curve = sfz::Curve::buildPredefinedCurve(5);
REQUIRE( curve.evalCC7(0) == 0.0f );
REQUIRE( curve.evalCC7(127) == 1.0f );
REQUIRE( curve.evalCC7(2) == Approx(0.125).margin(1e-3) );
REQUIRE( curve.evalCC7(63) == Approx(0.704).margin(1e-3) );
REQUIRE( curve.evalCC7(85) == Approx(0.818).margin(1e-3) );
REQUIRE( curve.evalNormalized(0.0f) == 0.0f );
REQUIRE( curve.evalNormalized(1.0f) == 1.0f );
REQUIRE( curve.evalNormalized(0.3f) == Approx(0.5477).margin(1e-3) );
}
TEST_CASE("[Curve] sqrt(1-x)")
{
auto curve = sfz::Curve::buildPredefinedCurve(6);
REQUIRE( curve.evalCC7(0) == 1.0f );
REQUIRE( curve.evalCC7(127) == 0.0f );
REQUIRE( curve.evalCC7(2) == Approx(0.992).margin(1e-3) );
REQUIRE( curve.evalCC7(63) == Approx(0.710).margin(1e-3) );
REQUIRE( curve.evalCC7(85) == Approx(0.575).margin(1e-3) );
REQUIRE( curve.evalNormalized(0.0f) == 1.0f );
REQUIRE( curve.evalNormalized(1.0f) == 0.0f );
REQUIRE( curve.evalNormalized(0.3f) == Approx(0.837).margin(1e-3) );
}
TEST_CASE("[Curve] Custom")
{
auto curve = sfz::Curve::buildCurveFromHeader({
{ "v000", "0" },
{ "v063", "1" },
{ "v127", "0" }
}, sfz::Curve::Interpolator::Linear);
REQUIRE( curve.evalCC7(0) == 0.0f );
REQUIRE( curve.evalCC7(127) == 0.0f );
REQUIRE( curve.evalCC7(63) == 1.0f );
REQUIRE( curve.evalCC7(2) == Approx(0.032).margin(1e-3) );
REQUIRE( curve.evalCC7(70) == Approx(0.891).margin(1e-3) );
}
TEST_CASE("[Curve] Custom 2")
{
auto curve = sfz::Curve::buildCurveFromHeader({
{ "v063", "1" }
}, sfz::Curve::Interpolator::Linear);
REQUIRE( curve.evalCC7(0) == 0.0f );
REQUIRE( curve.evalCC7(127) == 1.0f );
REQUIRE( curve.evalCC7(63) == 1.0f );
REQUIRE( curve.evalCC7(2) == Approx(0.032).margin(1e-3) );
REQUIRE( curve.evalCC7(70) == 1.0f );
}
TEST_CASE("[Curve] Custom 3")
{
auto curve = sfz::Curve::buildCurveFromHeader({
{ "v063", "1" },
{ "v064", "0.5" }
}, sfz::Curve::Interpolator::Linear);
REQUIRE( curve.evalCC7(0) == 0.0f );
REQUIRE( curve.evalCC7(127) == 1.0f );
REQUIRE( curve.evalCC7(63) == 1.0f );
REQUIRE( curve.evalCC7(2) == Approx(0.032).margin(1e-3) );
REQUIRE( curve.evalCC7(70) == Approx(0.548).margin(1e-3) );
}
TEST_CASE("[Curve] Add curves to CurveSet")
{
sfz::CurveSet curveSet;
curveSet.addCurve(sfz::Curve::buildPredefinedCurve(0));
curveSet.addCurve(sfz::Curve::buildPredefinedCurve(2));
REQUIRE( curveSet.getNumCurves() == 2 );
REQUIRE( curveSet.getCurve(0).evalCC7(0) == 0.0f );
REQUIRE( curveSet.getCurve(1).evalCC7(0) == 1.0f );
curveSet.addCurve(sfz::Curve::buildPredefinedCurve(0), 1);
REQUIRE(curveSet.getNumCurves() == 2);
REQUIRE( curveSet.getCurve(1).evalCC7(0) == 0.0f );
// Can't add an implicit curve after the explicit one
curveSet.addCurve(sfz::Curve::buildPredefinedCurve(0));
REQUIRE(curveSet.getNumCurves() == 2);
curveSet.addCurve(sfz::Curve::buildPredefinedCurve(2), 4);
REQUIRE(curveSet.getNumCurves() == 5);
REQUIRE( curveSet.getCurve(2).evalCC7(0) == 0.0f ); // Default "empty" curve
REQUIRE( curveSet.getCurve(3).evalCC7(0) == 0.0f ); // Default "empty" curve
REQUIRE( curveSet.getCurve(4).evalCC7(0) == 1.0f );
}
TEST_CASE("[Curve] Default CurveSet")
{
auto curveSet = sfz::CurveSet::createPredefined();
REQUIRE(curveSet.getNumCurves() == 7);
REQUIRE( curveSet.getCurve(0).evalNormalized(0.0f) == 0.0f );
REQUIRE( curveSet.getCurve(0).evalNormalized(1.0f) == 1.0f );
REQUIRE( curveSet.getCurve(0).evalNormalized(0.3f) == Approx(0.299).margin(1e-3) );
REQUIRE( curveSet.getCurve(1).evalNormalized(0.0f) == -1.0f );
REQUIRE( curveSet.getCurve(1).evalNormalized(1.0f) == 1.0f );
REQUIRE( curveSet.getCurve(1).evalNormalized(0.3f) == Approx(-0.402).margin(1e-3) );
REQUIRE( curveSet.getCurve(2).evalNormalized(0.0f) == 1.0f );
REQUIRE( curveSet.getCurve(2).evalNormalized(1.0f) == 0.0f );
REQUIRE( curveSet.getCurve(2).evalNormalized(0.3f) == Approx(0.701).margin(1e-3) );
REQUIRE( curveSet.getCurve(3).evalNormalized(0.0f) == 1.0f );
REQUIRE( curveSet.getCurve(3).evalNormalized(1.0f) == -1.0f );
REQUIRE( curveSet.getCurve(3).evalNormalized(0.3f) == Approx(0.402).margin(1e-3) );
REQUIRE( curveSet.getCurve(4).evalNormalized(0.0f) == 0.0f );
REQUIRE( curveSet.getCurve(4).evalNormalized(1.0f) == 1.0f );
REQUIRE( curveSet.getCurve(4).evalNormalized(0.3f) == Approx(0.09).margin(1e-3) );
REQUIRE( curveSet.getCurve(5).evalNormalized(0.0f) == 0.0f );
REQUIRE( curveSet.getCurve(5).evalNormalized(1.0f) == 1.0f );
REQUIRE( curveSet.getCurve(5).evalNormalized(0.3f) == Approx(0.5477).margin(1e-3) );
REQUIRE( curveSet.getCurve(6).evalNormalized(0.0f) == 1.0f );
REQUIRE( curveSet.getCurve(6).evalNormalized(1.0f) == 0.0f );
REQUIRE( curveSet.getCurve(6).evalNormalized(0.3f) == Approx(0.837).margin(1e-3) );
}