diff --git a/tests/AudioFilesT.cpp b/tests/AudioFilesT.cpp index 8046ca71..f888c650 100644 --- a/tests/AudioFilesT.cpp +++ b/tests/AudioFilesT.cpp @@ -5,12 +5,33 @@ // If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz #include "AudioSpan.h" +#include "absl/types/span.h" #include "sfizz/Synth.h" #include "TestHelpers.h" #include "catch2/catch.hpp" #include +#include using namespace Catch::literals; +TEST_CASE("[AudioFiles] No leakage on right") +{ + sfz::Synth synth; + sfz::AudioBuffer buffer { 2, static_cast(synth.getSamplesPerBlock()) }; + std::vector zeros(synth.getSamplesPerBlock(), 0); + sfz::AudioSpan span { buffer }; + synth.loadSfzString(fs::current_path() / "tests/TestFiles/wavpack.sfz", R"( + sample=kick.wav key=60 pan=-100 + )"); + synth.noteOn(0, 60, 127); + synth.renderBlock(buffer); + REQUIRE( numPlayingVoices(synth) == 1 ); + REQUIRE( approxEqual(span.getConstSpan(1), absl::MakeConstSpan(zeros), 1e-2f) ); + while (numPlayingVoices(synth) > 0) { + synth.renderBlock(buffer); + REQUIRE( approxEqual(span.getConstSpan(1), absl::MakeConstSpan(zeros), 1e-2f) ); + } +} + TEST_CASE("[AudioFiles] WavPack file") { sfz::Synth synth; @@ -29,3 +50,22 @@ TEST_CASE("[AudioFiles] WavPack file") REQUIRE( approxEqual(span.getConstSpan(0), span.getConstSpan(1)) ); } } + +TEST_CASE("[AudioFiles] Flac file") +{ + sfz::Synth synth; + sfz::AudioBuffer buffer { 2, static_cast(synth.getSamplesPerBlock()) }; + sfz::AudioSpan span { buffer }; + synth.loadSfzString(fs::current_path() / "tests/TestFiles/wavpack.sfz", R"( + sample=kick.wav key=60 pan=-100 + sample=kick.flac key=60 pan=100 + )"); + synth.noteOn(0, 60, 127); + synth.renderBlock(buffer); + REQUIRE( numPlayingVoices(synth) == 2 ); + REQUIRE( approxEqual(span.getConstSpan(0), span.getConstSpan(1)) ); + while (numPlayingVoices(synth) > 0) { + synth.renderBlock(buffer); + REQUIRE( approxEqual(span.getConstSpan(0), span.getConstSpan(1)) ); + } +} diff --git a/tests/EventEnvelopesT.cpp b/tests/EventEnvelopesT.cpp index 01287d3e..60bd9830 100644 --- a/tests/EventEnvelopesT.cpp +++ b/tests/EventEnvelopesT.cpp @@ -7,6 +7,7 @@ #include "sfizz/ModifierHelpers.h" #include "sfizz/Buffer.h" #include "catch2/catch.hpp" +#include "TestHelpers.h" #include #include #include @@ -14,20 +15,6 @@ #include using namespace Catch::literals; -template -inline bool approxEqual(absl::Span lhs, absl::Span rhs, Type eps = 1e-3) -{ - if (lhs.size() != rhs.size()) - return false; - - for (size_t i = 0; i < rhs.size(); ++i) - if (rhs[i] != Approx(lhs[i]).epsilon(eps)) { - std::cerr << lhs[i] << " != " << rhs[i] << " at index " << i << '\n'; - return false; - } - - return true; -} const auto idModifier = [](float x) { return x; }; const auto twiceModifier = [](float x) { return 2 * x; }; diff --git a/tests/SIMDHelpersT.cpp b/tests/SIMDHelpersT.cpp index 6bdf8cf6..4bac07b1 100644 --- a/tests/SIMDHelpersT.cpp +++ b/tests/SIMDHelpersT.cpp @@ -7,6 +7,7 @@ #include "sfizz/simd/Common.h" #include "sfizz/SIMDHelpers.h" #include "sfizz/Panning.h" +#include "TestHelpers.h" #include "catch2/catch.hpp" #include #include @@ -20,39 +21,9 @@ template using aligned_vector = std::vector>; constexpr int bigBufferSize { 4095 }; -constexpr int medBufferSize { 127 }; +constexpr int medBufferSize { 1023 }; constexpr float fillValue { 1.3f }; -template -inline bool approxEqualMargin(absl::Span lhs, absl::Span rhs, Type eps = 1e-3) -{ - if (lhs.size() != rhs.size()) - return false; - - for (size_t i = 0; i < rhs.size(); ++i) - if (rhs[i] != Approx(lhs[i]).margin(eps)) { - std::cerr << lhs[i] << " != " << rhs[i] << " at index " << i << '\n'; - return false; - } - - return true; -} - -template -inline bool approxEqual(absl::Span lhs, absl::Span rhs, Type eps = 1e-3) -{ - if (lhs.size() != rhs.size()) - return false; - - for (size_t i = 0; i < rhs.size(); ++i) - if (rhs[i] != Approx(lhs[i]).epsilon(eps)) { - std::cerr << lhs[i] << " != " << rhs[i] << " at index " << i << '\n'; - return false; - } - - return true; -} - TEST_CASE("[Helpers] willAlign, prevAligned and unaligned tests") { aligned_vector array(16); @@ -430,8 +401,8 @@ TEST_CASE("[Helpers] Linear Ramp (SIMD)") TEST_CASE("[Helpers] Linear Ramp (SIMD vs scalar)") { const float start { 0.0f }; - std::vector outputScalar(bigBufferSize); - std::vector outputSIMD(bigBufferSize); + std::vector outputScalar(medBufferSize); + std::vector outputSIMD(medBufferSize); sfz::setSIMDOpStatus(sfz::SIMDOps::linearRamp, false); sfz::linearRamp(absl::MakeSpan(outputScalar), start, fillValue); sfz::setSIMDOpStatus(sfz::SIMDOps::linearRamp, true); @@ -442,8 +413,8 @@ TEST_CASE("[Helpers] Linear Ramp (SIMD vs scalar)") TEST_CASE("[Helpers] Linear Ramp unaligned (SIMD vs scalar)") { const float start { 0.0f }; - std::vector outputScalar(bigBufferSize); - std::vector outputSIMD(bigBufferSize); + std::vector outputScalar(medBufferSize); + std::vector outputSIMD(medBufferSize); sfz::setSIMDOpStatus(sfz::SIMDOps::linearRamp, false); sfz::linearRamp(absl::MakeSpan(outputScalar).subspan(1), start, fillValue); sfz::setSIMDOpStatus(sfz::SIMDOps::linearRamp, true); diff --git a/tests/SmoothersT.cpp b/tests/SmoothersT.cpp index 63c05141..342da8e3 100644 --- a/tests/SmoothersT.cpp +++ b/tests/SmoothersT.cpp @@ -7,6 +7,7 @@ #include "sfizz/OnePoleFilter.h" #include "sfizz/Smoothers.h" #include "catch2/catch.hpp" +#include "TestHelpers.h" // #include "cnpy.h" // #include "ghc/fs_std.hpp" #include @@ -16,21 +17,6 @@ #include using namespace Catch::literals; -template -inline bool approxEqual(const std::array& lhs, const std::array& rhs, Type epsilon = 1e-3) -{ - if (lhs.size() != rhs.size()) - return false; - - for (size_t i = 0; i < rhs.size(); ++i) - if (lhs[i] != Approx(rhs[i]).epsilon(epsilon)) { - std::cerr << lhs[i] << " != " << rhs[i] << " at index " << i << '\n'; - return false; - } - - return true; -} - template void testFilter(const std::array& input, const std::array& expectedLow, const std::array& expectedHigh, Type gain) { @@ -43,19 +29,19 @@ void testFilter(const std::array& input, const std::array& exp sfz::OnePoleFilter filter; filter.setGain(gain); filter.processLowpass(input, outputSpan); - REQUIRE(approxEqual(output, expectedLow)); + REQUIRE(approxEqual(absl::MakeConstSpan(output), absl::MakeConstSpan(expectedLow))); filter.reset(); filter.processLowpass(input, outputSpan, gains); - REQUIRE(approxEqual(output, expectedLow)); + REQUIRE(approxEqual(absl::MakeConstSpan(output), absl::MakeConstSpan(expectedLow))); filter.reset(); filter.processHighpass(input, outputSpan); - REQUIRE(approxEqual(output, expectedHigh)); + REQUIRE(approxEqual(absl::MakeConstSpan(output), absl::MakeConstSpan(expectedHigh))); filter.reset(); filter.processHighpass(input, outputSpan, gains); - REQUIRE(approxEqual(output, expectedHigh)); + REQUIRE(approxEqual(absl::MakeConstSpan(output), absl::MakeConstSpan(expectedHigh))); } constexpr std::array floatInput01 = { diff --git a/tests/TestFiles/kick.flac b/tests/TestFiles/kick.flac new file mode 100755 index 00000000..79a2f4e6 Binary files /dev/null and b/tests/TestFiles/kick.flac differ diff --git a/tests/TestHelpers.h b/tests/TestHelpers.h index 8faa28b5..37d10de1 100644 --- a/tests/TestHelpers.h +++ b/tests/TestHelpers.h @@ -12,6 +12,8 @@ #include "sfizz/Messaging.h" #include "catch2/catch.hpp" #include "sfizz/modulations/ModKey.h" +#include +#include class RegionCCView { public: @@ -148,18 +150,52 @@ std::string createDefaultGraph(std::vector lines, int numRegions = std::string createModulationDotGraph(std::vector lines); template -inline bool approxEqual(absl::Span lhs, absl::Span rhs, Type eps = 1e-3) +bool approxEqual(absl::Span lhs, absl::Span rhs, Type eps = 1e-3) { if (lhs.size() != rhs.size()) return false; + bool different = false; for (size_t i = 0; i < rhs.size(); ++i) - if (rhs[i] != Approx(lhs[i]).epsilon(eps)) { - std::cerr << lhs[i] << " != " << rhs[i] << " at index " << i << '\n'; - return false; + if (rhs[i] != Approx(lhs[i]).margin(eps)) { + std::cerr << lhs[i] << " != " << rhs[i] << " (delta " << std::abs(rhs[i] - lhs[i]) << ") at index " << i << '\n'; + different = true; + break; } - return true; + auto print_span = [](absl::Span span) { + if (span.empty()) { + std::cerr << "{ }" << '\n'; + return; + } + + std::cerr << "{ "; + if (span.size() < 16) { + for (unsigned i = 0; i < span.size() - 1; ++i) { + std::cerr << span[i] << ", "; + } + } else { + for (unsigned i = 0; i < 8; ++i) { + std::cerr << span[i] << ", "; + } + std::cerr << "..., "; + for (unsigned i = span.size() - 8; i < span.size() - 1; ++i) { + std::cerr << span[i] << ", "; + } + } + std::cerr << span.back() << " }" << '\n'; + }; + + if (different) { + std::cerr << std::setprecision(3) << std::fixed; + std::cerr << "Differences between spans" << '\n'; + std::cerr << "lhs: "; + print_span(lhs); + std::cerr << "rhs: "; + print_span(rhs); + } + + return !different; } /**