diff --git a/tests/OnePoleFilterT.cpp b/tests/OnePoleFilterT.cpp index 1d29efdb..512c6a9b 100644 --- a/tests/OnePoleFilterT.cpp +++ b/tests/OnePoleFilterT.cpp @@ -4,10 +4,27 @@ #include "gsl/gsl-lite.hpp" #include #include +#include using namespace Catch::literals; template -void testInputOutput(const std::filesystem::path& inputNumpyFile, const std::filesystem::path& outputNumpyFile, Type gain) +inline bool approxEqual(const std::vector& lhs, const std::vector& rhs) +{ + if (lhs.size() != rhs.size()) + return false; + + for (size_t i = 0; i < rhs.size(); ++i) + if (lhs[i] != Approx(rhs[i]).epsilon(1e-3)) + { + std::cerr << lhs[i] << " != " << rhs[i] << " at index " << i << '\n'; + return false; + } + + return true; +} + +template +void testLowpass(const std::filesystem::path& inputNumpyFile, const std::filesystem::path& outputNumpyFile, Type gain) { const auto input = cnpy::npy_load(inputNumpyFile.string()); REQUIRE( input.word_size == 8 ); @@ -31,72 +48,163 @@ void testInputOutput(const std::filesystem::path& inputNumpyFile, const std::fil OnePoleFilter filter { gain }; std::vector outputData (size); filter.processLowpass(inputData, outputData); - for (size_t i = 0; i < size; ++i) - REQUIRE( outputData[i] == Approx(expectedData[i]) ); + REQUIRE( approxEqual(outputData, expectedData) ); filter.reset(); std::fill(outputData.begin(), outputData.end(), 0.0); std::vector gains(size); std::fill(gains.begin(), gains.end(), gain); filter.processLowpassVariableGain(inputData, outputData, gains); - for (size_t i = 0; i < size; ++i) - REQUIRE( outputData[i] == Approx(expectedData[i]) ); + REQUIRE( approxEqual(outputData, expectedData) ); } -TEST_CASE("[OnePoleFilter] Float") +template +void testHighpass(const std::filesystem::path& inputNumpyFile, const std::filesystem::path& outputNumpyFile, Type gain) { - testInputOutput( + const auto input = cnpy::npy_load(inputNumpyFile.string()); + REQUIRE( input.word_size == 8 ); + const auto inputSpan = gsl::make_span(input.data(), input.shape[0]); + + const auto output = cnpy::npy_load(outputNumpyFile.string()); + REQUIRE( output.word_size == 8 ); + const auto outputSpan = gsl::make_span(output.data(), output.shape[0]); + auto size = std::min(outputSpan.size(), inputSpan.size()); + REQUIRE( size > 0 ); + + std::vector inputData; + std::vector expectedData; + inputData.reserve(size); + expectedData.reserve(size); + for (auto& data: inputSpan) + inputData.push_back(static_cast(data)); + for (auto& data: outputSpan) + expectedData.push_back(static_cast(data)); + + OnePoleFilter filter { gain }; + std::vector outputData (size); + filter.processHighpass(inputData, outputData); + REQUIRE( approxEqual(outputData, expectedData) ); + + filter.reset(); + std::fill(outputData.begin(), outputData.end(), 0.0); + std::vector gains(size); + std::fill(gains.begin(), gains.end(), gain); + filter.processHighpassVariableGain(inputData, outputData, gains); + REQUIRE( approxEqual(outputData, expectedData) ); +} + +TEST_CASE("[OnePoleFilter] Lowpass Float") +{ + testLowpass( std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.1.npy", - std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_output_gain_0.1.npy", + std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.1.npy", 0.1f ); - testInputOutput( + testLowpass( std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.3.npy", - std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_output_gain_0.3.npy", + std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.3.npy", 0.3f ); - testInputOutput( + testLowpass( std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.5.npy", - std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_output_gain_0.5.npy", + std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.5.npy", 0.5f ); - testInputOutput( + testLowpass( std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.7.npy", - std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_output_gain_0.7.npy", + std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.7.npy", 0.7f ); - testInputOutput( + testLowpass( std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.9.npy", - std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_output_gain_0.9.npy", + std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.9.npy", 0.9f ); } -TEST_CASE("[OnePoleFilter] Double") +TEST_CASE("[OnePoleFilter] Lowpass Double") { - testInputOutput( + testLowpass( std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.1.npy", - std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_output_gain_0.1.npy", + std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.1.npy", 0.1f ); - testInputOutput( + testLowpass( std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.3.npy", - std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_output_gain_0.3.npy", + std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.3.npy", 0.3f ); - testInputOutput( + testLowpass( std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.5.npy", - std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_output_gain_0.5.npy", + std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.5.npy", 0.5f ); - testInputOutput( + testLowpass( std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.7.npy", - std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_output_gain_0.7.npy", + std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.7.npy", 0.7f ); - testInputOutput( + testLowpass( std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.9.npy", - std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_output_gain_0.9.npy", + std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.9.npy", + 0.9f + ); +} + +TEST_CASE("[OnePoleFilter] Highpass Float") +{ + testHighpass( + std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.1.npy", + std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.1.npy", + 0.1f + ); + testHighpass( + std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.3.npy", + std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.3.npy", + 0.3f + ); + testHighpass( + std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.5.npy", + std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.5.npy", + 0.5f + ); + testHighpass( + std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.7.npy", + std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.7.npy", + 0.7f + ); + testHighpass( + std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.9.npy", + std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.9.npy", + 0.9f + ); +} + +TEST_CASE("[OnePoleFilter] Highpass Double") +{ + testHighpass( + std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.1.npy", + std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.1.npy", + 0.1f + ); + testHighpass( + std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.3.npy", + std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.3.npy", + 0.3f + ); + testHighpass( + std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.5.npy", + std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.5.npy", + 0.5f + ); + testHighpass( + std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.7.npy", + std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.7.npy", + 0.7f + ); + testHighpass( + std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.9.npy", + std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.9.npy", 0.9f ); } diff --git a/tests/TestFiles/OnePoleFilter/OPF_high_gain_0.1.npy b/tests/TestFiles/OnePoleFilter/OPF_high_gain_0.1.npy new file mode 100644 index 00000000..0f15488c Binary files /dev/null and b/tests/TestFiles/OnePoleFilter/OPF_high_gain_0.1.npy differ diff --git a/tests/TestFiles/OnePoleFilter/OPF_high_gain_0.3.npy b/tests/TestFiles/OnePoleFilter/OPF_high_gain_0.3.npy new file mode 100644 index 00000000..bd4f9e2d Binary files /dev/null and b/tests/TestFiles/OnePoleFilter/OPF_high_gain_0.3.npy differ diff --git a/tests/TestFiles/OnePoleFilter/OPF_high_gain_0.5.npy b/tests/TestFiles/OnePoleFilter/OPF_high_gain_0.5.npy new file mode 100644 index 00000000..882f7529 Binary files /dev/null and b/tests/TestFiles/OnePoleFilter/OPF_high_gain_0.5.npy differ diff --git a/tests/TestFiles/OnePoleFilter/OPF_high_gain_0.7.npy b/tests/TestFiles/OnePoleFilter/OPF_high_gain_0.7.npy new file mode 100644 index 00000000..df049fd7 Binary files /dev/null and b/tests/TestFiles/OnePoleFilter/OPF_high_gain_0.7.npy differ diff --git a/tests/TestFiles/OnePoleFilter/OPF_high_gain_0.9.npy b/tests/TestFiles/OnePoleFilter/OPF_high_gain_0.9.npy new file mode 100644 index 00000000..eaff9057 Binary files /dev/null and b/tests/TestFiles/OnePoleFilter/OPF_high_gain_0.9.npy differ diff --git a/tests/TestFiles/OnePoleFilter/OPF_input_gain_0.1.npy b/tests/TestFiles/OnePoleFilter/OPF_input_gain_0.1.npy index 7c87bb65..3dc90c54 100644 Binary files a/tests/TestFiles/OnePoleFilter/OPF_input_gain_0.1.npy and b/tests/TestFiles/OnePoleFilter/OPF_input_gain_0.1.npy differ diff --git a/tests/TestFiles/OnePoleFilter/OPF_input_gain_0.3.npy b/tests/TestFiles/OnePoleFilter/OPF_input_gain_0.3.npy index c5bee388..3cbf3db1 100644 Binary files a/tests/TestFiles/OnePoleFilter/OPF_input_gain_0.3.npy and b/tests/TestFiles/OnePoleFilter/OPF_input_gain_0.3.npy differ diff --git a/tests/TestFiles/OnePoleFilter/OPF_input_gain_0.5.npy b/tests/TestFiles/OnePoleFilter/OPF_input_gain_0.5.npy index a7a3e773..bd6cfe10 100644 Binary files a/tests/TestFiles/OnePoleFilter/OPF_input_gain_0.5.npy and b/tests/TestFiles/OnePoleFilter/OPF_input_gain_0.5.npy differ diff --git a/tests/TestFiles/OnePoleFilter/OPF_input_gain_0.7.npy b/tests/TestFiles/OnePoleFilter/OPF_input_gain_0.7.npy index eb17324d..a33ec54f 100644 Binary files a/tests/TestFiles/OnePoleFilter/OPF_input_gain_0.7.npy and b/tests/TestFiles/OnePoleFilter/OPF_input_gain_0.7.npy differ diff --git a/tests/TestFiles/OnePoleFilter/OPF_input_gain_0.9.npy b/tests/TestFiles/OnePoleFilter/OPF_input_gain_0.9.npy index 5b88b321..c9599017 100644 Binary files a/tests/TestFiles/OnePoleFilter/OPF_input_gain_0.9.npy and b/tests/TestFiles/OnePoleFilter/OPF_input_gain_0.9.npy differ diff --git a/tests/TestFiles/OnePoleFilter/OPF_low_gain_0.1.npy b/tests/TestFiles/OnePoleFilter/OPF_low_gain_0.1.npy new file mode 100644 index 00000000..f63964d4 Binary files /dev/null and b/tests/TestFiles/OnePoleFilter/OPF_low_gain_0.1.npy differ diff --git a/tests/TestFiles/OnePoleFilter/OPF_low_gain_0.3.npy b/tests/TestFiles/OnePoleFilter/OPF_low_gain_0.3.npy new file mode 100644 index 00000000..e2400538 Binary files /dev/null and b/tests/TestFiles/OnePoleFilter/OPF_low_gain_0.3.npy differ diff --git a/tests/TestFiles/OnePoleFilter/OPF_low_gain_0.5.npy b/tests/TestFiles/OnePoleFilter/OPF_low_gain_0.5.npy new file mode 100644 index 00000000..7d373bfc Binary files /dev/null and b/tests/TestFiles/OnePoleFilter/OPF_low_gain_0.5.npy differ diff --git a/tests/TestFiles/OnePoleFilter/OPF_low_gain_0.7.npy b/tests/TestFiles/OnePoleFilter/OPF_low_gain_0.7.npy new file mode 100644 index 00000000..372bbde1 Binary files /dev/null and b/tests/TestFiles/OnePoleFilter/OPF_low_gain_0.7.npy differ diff --git a/tests/TestFiles/OnePoleFilter/OPF_low_gain_0.9.npy b/tests/TestFiles/OnePoleFilter/OPF_low_gain_0.9.npy new file mode 100644 index 00000000..93297867 Binary files /dev/null and b/tests/TestFiles/OnePoleFilter/OPF_low_gain_0.9.npy differ diff --git a/tests/TestFiles/OnePoleFilter/OPF_output_gain_0.1.npy b/tests/TestFiles/OnePoleFilter/OPF_output_gain_0.1.npy deleted file mode 100644 index 2a0b42dd..00000000 Binary files a/tests/TestFiles/OnePoleFilter/OPF_output_gain_0.1.npy and /dev/null differ diff --git a/tests/TestFiles/OnePoleFilter/OPF_output_gain_0.3.npy b/tests/TestFiles/OnePoleFilter/OPF_output_gain_0.3.npy deleted file mode 100644 index b17e6d95..00000000 Binary files a/tests/TestFiles/OnePoleFilter/OPF_output_gain_0.3.npy and /dev/null differ diff --git a/tests/TestFiles/OnePoleFilter/OPF_output_gain_0.5.npy b/tests/TestFiles/OnePoleFilter/OPF_output_gain_0.5.npy deleted file mode 100644 index 6001b75b..00000000 Binary files a/tests/TestFiles/OnePoleFilter/OPF_output_gain_0.5.npy and /dev/null differ diff --git a/tests/TestFiles/OnePoleFilter/OPF_output_gain_0.7.npy b/tests/TestFiles/OnePoleFilter/OPF_output_gain_0.7.npy deleted file mode 100644 index dcbda93b..00000000 Binary files a/tests/TestFiles/OnePoleFilter/OPF_output_gain_0.7.npy and /dev/null differ diff --git a/tests/TestFiles/OnePoleFilter/OPF_output_gain_0.9.npy b/tests/TestFiles/OnePoleFilter/OPF_output_gain_0.9.npy deleted file mode 100644 index acec0e5f..00000000 Binary files a/tests/TestFiles/OnePoleFilter/OPF_output_gain_0.9.npy and /dev/null differ