diff --git a/benchmarks/BM_filterModulation.cpp b/benchmarks/BM_filterModulation.cpp new file mode 100644 index 00000000..32640c41 --- /dev/null +++ b/benchmarks/BM_filterModulation.cpp @@ -0,0 +1,135 @@ +// 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 "SIMDHelpers.h" +#include "OnePoleFilter.h" +#include "SfzFilter.h" +#include +#include +#include +#include +#include +#include + +constexpr int blockSize { 1024 }; +constexpr float sampleRate { 48000.0f }; + +class FilterFixture : public benchmark::Fixture { +public: + void SetUp(const ::benchmark::State& state) { + input = std::vector(blockSize); + output = std::vector(blockSize); + cutoff = std::vector(blockSize); + q = std::vector(blockSize); + pksh = std::vector(blockSize); + sfz::linearRamp(absl::MakeSpan(cutoff), 500, 1.0f); + sfz::linearRamp(absl::MakeSpan(q), 0.0f, 0.001f); + sfz::linearRamp(absl::MakeSpan(pksh), 0.0f, 0.001f); + std::generate(input.begin(), input.end(), [&]() { return dist(gen); }); + } + + void TearDown(const ::benchmark::State& state [[maybe_unused]]) { + + } + std::random_device rd { }; + std::mt19937 gen { rd() }; + std::normal_distribution dist { 0, 0.5 }; + std::vector cutoff; + std::vector q; + std::vector pksh; + std::vector input; + std::vector output; +}; + +BENCHMARK_DEFINE_F(FilterFixture, OnePole_VA)(benchmark::State& state) { + sfz::OnePoleFilter filter; + for (auto _ : state) + { + const auto step = static_cast(state.range(0)); + auto cutoffIterator = cutoff.begin(); + auto inputIterator = input.begin(); + auto outputIterator = output.begin(); + while (cutoffIterator < cutoff.end()) + { + const auto gain = sfz::OnePoleFilter::normalizedGain(*cutoffIterator, sampleRate); + filter.setGain(gain); + filter.processLowpass({ inputIterator.base(), step }, { outputIterator.base(), step } ); + cutoffIterator += step; + inputIterator += step; + outputIterator += step; + } + } +} + +BENCHMARK_DEFINE_F(FilterFixture, OnePole_Faust)(benchmark::State& state) { + sfz::Filter<1> filter; + filter.setType(sfz::FilterType::kFilterLpf1p); + for (auto _ : state) + { + const auto step = static_cast(state.range(0)); + auto cutoffIterator = cutoff.begin(); + auto inputIterator = input.begin(); + auto outputIterator = output.begin(); + while (cutoffIterator < cutoff.end()) + { + filter.process(&inputIterator.base(), &outputIterator.base(), *cutoffIterator, 0.0, 0.0, step); + cutoffIterator += step; + inputIterator += step; + outputIterator += step; + } + } +} + +BENCHMARK_DEFINE_F(FilterFixture, TwoPole_Faust)(benchmark::State& state) { + sfz::Filter<1> filter; + filter.setType(sfz::FilterType::kFilterLpf2p); + for (auto _ : state) + { + const auto step = static_cast(state.range(0)); + auto cutoffIterator = cutoff.begin(); + auto qIterator = q.begin(); + auto inputIterator = input.begin(); + auto outputIterator = output.begin(); + while (cutoffIterator < cutoff.end()) + { + filter.process(&inputIterator.base(), &outputIterator.base(), *cutoffIterator, *qIterator, 0.0, step); + qIterator += step; + cutoffIterator += step; + inputIterator += step; + outputIterator += step; + } + } +} + +BENCHMARK_DEFINE_F(FilterFixture, TwoPoleShelf_Faust)(benchmark::State& state) { + sfz::Filter<1> filter; + filter.setType(sfz::FilterType::kFilterLsh); + for (auto _ : state) + { + const auto step = static_cast(state.range(0)); + auto cutoffIterator = cutoff.begin(); + auto qIterator = q.begin(); + auto pkshIterator = pksh.begin(); + auto inputIterator = input.begin(); + auto outputIterator = output.begin(); + while (cutoffIterator < cutoff.end()) + { + filter.process(&inputIterator.base(), &outputIterator.base(), *cutoffIterator, *qIterator, *pkshIterator, step); + qIterator += step; + cutoffIterator += step; + pkshIterator += step; + inputIterator += step; + outputIterator += step; + } + } +} + +BENCHMARK_REGISTER_F(FilterFixture, OnePole_VA)->RangeMultiplier(2)->Range(1, 1 << 8); +BENCHMARK_REGISTER_F(FilterFixture, OnePole_Faust)->RangeMultiplier(2)->Range(1, 1 << 8); +BENCHMARK_REGISTER_F(FilterFixture, TwoPole_Faust)->RangeMultiplier(2)->Range(1, 1 << 8); +BENCHMARK_REGISTER_F(FilterFixture, TwoPoleShelf_Faust)->RangeMultiplier(2)->Range(1, 1 << 8); +BENCHMARK_MAIN(); + diff --git a/benchmarks/BM_filterStereoMono.cpp b/benchmarks/BM_filterStereoMono.cpp new file mode 100644 index 00000000..d7168ed1 --- /dev/null +++ b/benchmarks/BM_filterStereoMono.cpp @@ -0,0 +1,293 @@ +// 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 "SIMDHelpers.h" +#include "OnePoleFilter.h" +#include "SfzFilter.h" +#include +#include +#include +#include +#include +#include + +constexpr int blockSize { 1024 }; +constexpr float sampleRate { 48000.0f }; + +class FilterFixture : public benchmark::Fixture { +public: + void SetUp(const ::benchmark::State& state) { + inputLeft = std::vector(blockSize); + inputRight = std::vector(blockSize); + outputLeft = std::vector(blockSize); + outputRight = std::vector(blockSize); + cutoff = std::vector(blockSize); + q = std::vector(blockSize); + pksh = std::vector(blockSize); + sfz::linearRamp(absl::MakeSpan(cutoff), 500, 1.0f); + sfz::linearRamp(absl::MakeSpan(q), 0.0f, 0.001f); + sfz::linearRamp(absl::MakeSpan(pksh), 0.0f, 0.001f); + std::generate(inputLeft.begin(), inputLeft.end(), [&]() { return dist(gen); }); + std::generate(inputRight.begin(), inputRight.end(), [&]() { return dist(gen); }); + } + + void TearDown(const ::benchmark::State& state [[maybe_unused]]) { + + } + std::random_device rd { }; + std::mt19937 gen { rd() }; + std::normal_distribution dist { 0, 0.5 }; + std::vector cutoff; + std::vector q; + std::vector pksh; + std::vector inputLeft; + std::vector inputRight; + std::vector outputLeft; + std::vector outputRight; +}; + +BENCHMARK_DEFINE_F(FilterFixture, OnePole_MonoOnce)(benchmark::State& state) { + sfz::Filter<1> filterLeft; + sfz::Filter<1> filterRight; + filterLeft.setType(sfz::FilterType::kFilterLpf1p); + for (auto _ : state) + { + const auto step = static_cast(state.range(0)); + auto cutoffIterator = cutoff.begin(); + auto inLIterator = inputLeft.begin(); + auto outLIterator = outputRight.begin(); + while (cutoffIterator < cutoff.end()) + { + filterLeft.process( &inLIterator.base(), &outLIterator.base(), *cutoffIterator, 0.0, 0.0, step); + cutoffIterator += step; + inLIterator += step; + outLIterator += step; + } + } +} + +BENCHMARK_DEFINE_F(FilterFixture, OnePole_MonoTwice)(benchmark::State& state) { + sfz::Filter<1> filterLeft; + sfz::Filter<1> filterRight; + filterLeft.setType(sfz::FilterType::kFilterLpf1p); + filterRight.setType(sfz::FilterType::kFilterLpf1p); + for (auto _ : state) + { + const auto step = static_cast(state.range(0)); + auto cutoffIterator = cutoff.begin(); + auto inLIterator = inputLeft.begin(); + auto inRIterator = inputRight.begin(); + auto outRIterator = outputLeft.begin(); + auto outLIterator = outputRight.begin(); + while (cutoffIterator < cutoff.end()) + { + filterLeft.process( &inLIterator.base(), &outLIterator.base(), *cutoffIterator, 0.0, 0.0, step); + filterRight.process(&inRIterator.base(), &outRIterator.base(), *cutoffIterator, 0.0, 0.0, step); + cutoffIterator += step; + inLIterator += step; + inRIterator += step; + outLIterator += step; + outRIterator += step; + } + } +} + +BENCHMARK_DEFINE_F(FilterFixture, OnePole_Stereo)(benchmark::State& state) { + sfz::Filter<2> filter; + filter.setType(sfz::FilterType::kFilterLpf1p); + for (auto _ : state) + { + const auto step = static_cast(state.range(0)); + auto cutoffIterator = cutoff.begin(); + auto inLIterator = inputLeft.begin(); + auto inRIterator = inputRight.begin(); + auto outRIterator = outputLeft.begin(); + auto outLIterator = outputRight.begin(); + while (cutoffIterator < cutoff.end()) + { + float * inputs[2] = { inLIterator.base(), inRIterator.base() }; + float * outputs[2] = { outLIterator.base(), outRIterator.base() }; + filter.process(inputs, outputs, *cutoffIterator, 0.0, 0.0, step); + cutoffIterator += step; + inLIterator += step; + inRIterator += step; + outLIterator += step; + outRIterator += step; + } + } +} + +BENCHMARK_DEFINE_F(FilterFixture, TwoPole_MonoOnce)(benchmark::State& state) { + sfz::Filter<1> filterLeft; + sfz::Filter<1> filterRight; + filterLeft.setType(sfz::FilterType::kFilterLpf2p); + for (auto _ : state) + { + const auto step = static_cast(state.range(0)); + auto cutoffIterator = cutoff.begin(); + auto qIterator = q.begin(); + auto inLIterator = inputLeft.begin(); + auto outLIterator = outputRight.begin(); + while (cutoffIterator < cutoff.end()) + { + filterLeft.process(&inLIterator.base(), &outLIterator.base(), *cutoffIterator, *qIterator, 0.0, step); + cutoffIterator += step; + qIterator += step; + inLIterator += step; + outLIterator += step; + } + } +} + +BENCHMARK_DEFINE_F(FilterFixture, TwoPole_MonoTwice)(benchmark::State& state) { + sfz::Filter<1> filterLeft; + sfz::Filter<1> filterRight; + filterLeft.setType(sfz::FilterType::kFilterLpf2p); + filterRight.setType(sfz::FilterType::kFilterLpf2p); + for (auto _ : state) + { + const auto step = static_cast(state.range(0)); + auto cutoffIterator = cutoff.begin(); + auto qIterator = q.begin(); + auto inLIterator = inputLeft.begin(); + auto inRIterator = inputRight.begin(); + auto outRIterator = outputLeft.begin(); + auto outLIterator = outputRight.begin(); + while (cutoffIterator < cutoff.end()) + { + filterLeft.process( &inLIterator.base(), &outLIterator.base(), *cutoffIterator, *qIterator, 0.0, step); + filterRight.process(&inRIterator.base(), &outRIterator.base(), *cutoffIterator, *qIterator, 0.0, step); + cutoffIterator += step; + qIterator += step; + inLIterator += step; + inRIterator += step; + outLIterator += step; + outRIterator += step; + } + } +} + +BENCHMARK_DEFINE_F(FilterFixture, TwoPole_Stereo)(benchmark::State& state) { + sfz::Filter<2> filter; + filter.setType(sfz::FilterType::kFilterLpf2p); + for (auto _ : state) + { + const auto step = static_cast(state.range(0)); + auto cutoffIterator = cutoff.begin(); + auto qIterator = q.begin(); + auto inLIterator = inputLeft.begin(); + auto inRIterator = inputRight.begin(); + auto outRIterator = outputLeft.begin(); + auto outLIterator = outputRight.begin(); + while (cutoffIterator < cutoff.end()) + { + float * inputs[2] = { inLIterator.base(), inRIterator.base() }; + float * outputs[2] = { outLIterator.base(), outRIterator.base() }; + filter.process(inputs, outputs, *cutoffIterator, *qIterator, 0.0, step); + cutoffIterator += step; + qIterator += step; + inLIterator += step; + inRIterator += step; + outLIterator += step; + outRIterator += step; + } + } +} + +BENCHMARK_DEFINE_F(FilterFixture, Shelf_MonoOnce)(benchmark::State& state) { + sfz::Filter<1> filterLeft; + sfz::Filter<1> filterRight; + filterLeft.setType(sfz::FilterType::kFilterLpf2p); + for (auto _ : state) + { + const auto step = static_cast(state.range(0)); + auto cutoffIterator = cutoff.begin(); + auto qIterator = q.begin(); + auto pkshIterator = pksh.begin(); + auto inLIterator = inputLeft.begin(); + auto outLIterator = outputRight.begin(); + while (cutoffIterator < cutoff.end()) + { + filterLeft.process(&inLIterator.base(), &outLIterator.base(), *cutoffIterator, *qIterator, *pkshIterator, step); + cutoffIterator += step; + qIterator += step; + pkshIterator += step; + inLIterator += step; + outLIterator += step; + } + } +} + +BENCHMARK_DEFINE_F(FilterFixture, Shelf_MonoTwice)(benchmark::State& state) { + sfz::Filter<1> filterLeft; + sfz::Filter<1> filterRight; + filterLeft.setType(sfz::FilterType::kFilterLpf2p); + filterRight.setType(sfz::FilterType::kFilterLpf2p); + for (auto _ : state) + { + const auto step = static_cast(state.range(0)); + auto cutoffIterator = cutoff.begin(); + auto qIterator = q.begin(); + auto pkshIterator = pksh.begin(); + auto inLIterator = inputLeft.begin(); + auto inRIterator = inputRight.begin(); + auto outRIterator = outputLeft.begin(); + auto outLIterator = outputRight.begin(); + while (cutoffIterator < cutoff.end()) + { + filterLeft.process( &inLIterator.base(), &outLIterator.base(), *cutoffIterator, *qIterator, *pkshIterator, step); + filterRight.process(&inRIterator.base(), &outRIterator.base(), *cutoffIterator, *qIterator, *pkshIterator, step); + cutoffIterator += step; + qIterator += step; + pkshIterator += step; + inLIterator += step; + inRIterator += step; + outLIterator += step; + outRIterator += step; + } + } +} + +BENCHMARK_DEFINE_F(FilterFixture, Shelf_Stereo)(benchmark::State& state) { + sfz::Filter<2> filter; + filter.setType(sfz::FilterType::kFilterLpf2p); + for (auto _ : state) + { + const auto step = static_cast(state.range(0)); + auto cutoffIterator = cutoff.begin(); + auto qIterator = q.begin(); + auto pkshIterator = pksh.begin(); + auto inLIterator = inputLeft.begin(); + auto inRIterator = inputRight.begin(); + auto outRIterator = outputLeft.begin(); + auto outLIterator = outputRight.begin(); + while (cutoffIterator < cutoff.end()) + { + float * inputs[2] = { inLIterator.base(), inRIterator.base() }; + float * outputs[2] = { outLIterator.base(), outRIterator.base() }; + filter.process(inputs, outputs, *cutoffIterator, *qIterator, *pkshIterator, step); + cutoffIterator += step; + qIterator += step; + pkshIterator += step; + inLIterator += step; + inRIterator += step; + outLIterator += step; + outRIterator += step; + } + } +} + +BENCHMARK_REGISTER_F(FilterFixture, OnePole_MonoOnce)->RangeMultiplier(2)->Range(1, 1 << 8); +BENCHMARK_REGISTER_F(FilterFixture, OnePole_MonoTwice)->RangeMultiplier(2)->Range(1, 1 << 8); +BENCHMARK_REGISTER_F(FilterFixture, OnePole_Stereo)->RangeMultiplier(2)->Range(1, 1 << 8); +BENCHMARK_REGISTER_F(FilterFixture, TwoPole_MonoOnce)->RangeMultiplier(2)->Range(1, 1 << 8); +BENCHMARK_REGISTER_F(FilterFixture, TwoPole_MonoTwice)->RangeMultiplier(2)->Range(1, 1 << 8); +BENCHMARK_REGISTER_F(FilterFixture, TwoPole_Stereo)->RangeMultiplier(2)->Range(1, 1 << 8); +BENCHMARK_REGISTER_F(FilterFixture, Shelf_MonoOnce)->RangeMultiplier(2)->Range(1, 1 << 8); +BENCHMARK_REGISTER_F(FilterFixture, Shelf_MonoTwice)->RangeMultiplier(2)->Range(1, 1 << 8); +BENCHMARK_REGISTER_F(FilterFixture, Shelf_Stereo)->RangeMultiplier(2)->Range(1, 1 << 8); +BENCHMARK_MAIN(); + diff --git a/benchmarks/CMakeLists.txt b/benchmarks/CMakeLists.txt index cd888984..e47f10f1 100644 --- a/benchmarks/CMakeLists.txt +++ b/benchmarks/CMakeLists.txt @@ -120,6 +120,14 @@ add_executable(bm_resampleChunk BM_resampleChunk.cpp ${BENCHMARK_SIMD_SOURCES}) target_link_libraries(bm_resampleChunk PRIVATE absl::span absl::algorithm benchmark::benchmark benchmark::benchmark_main sfizz-sndfile) target_include_directories(bm_resampleChunk PRIVATE ../src/sfizz ../src/external) +add_executable(bm_filterModulation BM_filterModulation.cpp ${BENCHMARK_SIMD_SOURCES} ../src/sfizz/SfzFilter.cpp) +target_link_libraries(bm_filterModulation PRIVATE absl::span absl::algorithm benchmark::benchmark benchmark::benchmark_main sfizz-sndfile) +target_include_directories(bm_filterModulation PRIVATE ../src/sfizz ../src/external) + +add_executable(bm_filterStereoMono BM_filterStereoMono.cpp ${BENCHMARK_SIMD_SOURCES} ../src/sfizz/SfzFilter.cpp) +target_link_libraries(bm_filterStereoMono PRIVATE absl::span absl::algorithm benchmark::benchmark benchmark::benchmark_main sfizz-sndfile) +target_include_directories(bm_filterStereoMono PRIVATE ../src/sfizz ../src/external) + add_custom_target(sfizz_benchmarks) add_dependencies(sfizz_benchmarks bm_opf_high_vs_low @@ -148,6 +156,8 @@ add_dependencies(sfizz_benchmarks bm_envelopes bm_wavfile bm_flacfile + bm_filterModulation + bm_filterStereoMono ) if (NOT WIN32)