diff --git a/src/sfizz/ModifierHelpers.h b/src/sfizz/ModifierHelpers.h index e233009d..810a16dd 100644 --- a/src/sfizz/ModifierHelpers.h +++ b/src/sfizz/ModifierHelpers.h @@ -18,15 +18,17 @@ namespace sfz { template float crossfadeIn(const sfz::Range& crossfadeRange, U value, CrossfadeCurve curve) { + constexpr float gapOffset { static_cast(normalize7Bits(1)) }; if (value < crossfadeRange.getStart()) return 0.0f; - const auto length = static_cast(crossfadeRange.length()); + const auto length = static_cast(crossfadeRange.length()) - gapOffset; if (length <= 0.0f) return 1.0f; else if (value < crossfadeRange.getEnd()) { - const auto crossfadePosition = static_cast(value - crossfadeRange.getStart()) / length; + const auto distanceFromStart = static_cast(value - crossfadeRange.getStart()); + const auto crossfadePosition = distanceFromStart / length; if (curve == CrossfadeCurve::power) return sqrt(crossfadePosition); if (curve == CrossfadeCurve::gain) @@ -42,15 +44,16 @@ float crossfadeIn(const sfz::Range& crossfadeRange, U value, CrossfadeCurv template float crossfadeOut(const sfz::Range& crossfadeRange, U value, CrossfadeCurve curve) { - if (value > crossfadeRange.getEnd()) - return 0.0f; - - const auto length = static_cast(crossfadeRange.length()); + constexpr float gapOffset { static_cast(normalize7Bits(1)) }; + const auto length = static_cast(crossfadeRange.length()) - gapOffset; if (length <= 0.0f) return 1.0f; else if (value > crossfadeRange.getStart()) { - const auto crossfadePosition = static_cast(value - crossfadeRange.getStart()) / length; + const auto distanceFromStart = static_cast(value - crossfadeRange.getStart()); + const auto crossfadePosition = distanceFromStart / length; + if (crossfadePosition > 1.0f) + return 0.0f; if (curve == CrossfadeCurve::power) return std::sqrt(1 - crossfadePosition); if (curve == CrossfadeCurve::gain) diff --git a/tests/FilesT.cpp b/tests/FilesT.cpp index 0c94934b..196f5bcf 100644 --- a/tests/FilesT.cpp +++ b/tests/FilesT.cpp @@ -149,10 +149,10 @@ TEST_CASE("[Files] Group from AVL") REQUIRE(synth.getRegionView(i)->keyRange == Range(36, 36)); } - almostEqualRanges(synth.getRegionView(0)->velocityRange, { 1_norm, 26_norm }); - almostEqualRanges(synth.getRegionView(1)->velocityRange, { 27_norm, 52_norm }); - almostEqualRanges(synth.getRegionView(2)->velocityRange, { 53_norm, 77_norm }); - almostEqualRanges(synth.getRegionView(3)->velocityRange, { 78_norm, 102_norm }); + almostEqualRanges(synth.getRegionView(0)->velocityRange, { 1_norm, std::nextafter(27_norm, 0.0f) }); + almostEqualRanges(synth.getRegionView(1)->velocityRange, { 27_norm, std::nextafter(53_norm, 0.0f) }); + almostEqualRanges(synth.getRegionView(2)->velocityRange, { 53_norm, std::nextafter(78_norm, 0.0f) }); + almostEqualRanges(synth.getRegionView(3)->velocityRange, { 78_norm, std::nextafter(103_norm, 0.0f) }); almostEqualRanges(synth.getRegionView(4)->velocityRange, { 103_norm, 127_norm }); }