diff --git a/src/sfizz/ADSREnvelope.cpp b/src/sfizz/ADSREnvelope.cpp index 9581ab7a..d2f3daff 100644 --- a/src/sfizz/ADSREnvelope.cpp +++ b/src/sfizz/ADSREnvelope.cpp @@ -188,6 +188,8 @@ void ADSREnvelope::getBlock(absl::Span output) noexcept this->currentValue = currentValue; this->shouldRelease = shouldRelease; this->releaseDelay = releaseDelay; + + ASSERT(!hasNanInf(output)); } template diff --git a/src/sfizz/MathHelpers.h b/src/sfizz/MathHelpers.h index 960ccb73..7d7aae6e 100644 --- a/src/sfizz/MathHelpers.h +++ b/src/sfizz/MathHelpers.h @@ -11,6 +11,7 @@ #pragma once #include "Config.h" #include "Macros.h" +#include "absl/types/span.h" #include #include #include @@ -292,3 +293,36 @@ inline F fp_from_parts(bool sgn, int ex, uint64_t mant) (static_cast(sgn) << (T::e_bits + T::m_bits)); return u.real; } + + +template +inline bool fp_naninf(F x) +{ + typedef FP_traits T; + typedef typename T::same_size_int I; + union { F real; I integer; } u; + u.real = x; + const auto all_ones = ((1u << T::e_bits) - 1); + const auto ex = (u.integer >> T::m_bits) & all_ones; + return ex == all_ones; +} + +template +bool hasNanInf(absl::Span span) +{ + for (const auto& x: span) + if (fp_naninf(x)) + return true; + + return false; +} + +template +bool isValidAudio(absl::Span span) +{ + for (const auto& x: span) + if (x < -1.0f || x > 1.0f) + return false; + + return true; +} diff --git a/tests/FloatHelpersT.cpp b/tests/FloatHelpersT.cpp index 58b92acc..ecfc0cf0 100644 --- a/tests/FloatHelpersT.cpp +++ b/tests/FloatHelpersT.cpp @@ -7,6 +7,7 @@ #include "catch2/catch.hpp" #include "sfizz/MathHelpers.h" #include +#include TEST_CASE("[FloatMath] Fast ilog2 (float)") { @@ -51,3 +52,19 @@ TEST_CASE("[FloatMath] Break apart and reconstruct (double)") REQUIRE(fp_from_parts(sgn, ex, mant.num) == f); } } + +TEST_CASE("[FloatMath] Nan/Inf checker") +{ + REQUIRE(fp_naninf(std::numeric_limits::quiet_NaN())); + REQUIRE(fp_naninf(std::numeric_limits::quiet_NaN())); + REQUIRE(fp_naninf(std::numeric_limits::infinity())); + REQUIRE(fp_naninf(std::numeric_limits::infinity())); + REQUIRE(fp_naninf(-std::numeric_limits::infinity())); + REQUIRE(fp_naninf(-std::numeric_limits::infinity())); + REQUIRE(!fp_naninf(0.0f)); + REQUIRE(!fp_naninf(0.0)); + REQUIRE(!fp_naninf(1.0f)); + REQUIRE(!fp_naninf(1.0)); + REQUIRE(!fp_naninf(-1.0f)); + REQUIRE(!fp_naninf(-1.0)); +}