From 2bef20931e037bada85dbdc4cd078c7f11a4f39b Mon Sep 17 00:00:00 2001 From: Lukas Berbuer Date: Tue, 6 May 2025 17:33:10 +0200 Subject: [PATCH] fix(partial-power): rounding function Use flooring instead of rounding to transform frequencies to bins. --- src/features.cpp | 19 ++++++++++++------- tests/test_features_partial-power.toml | 4 ++-- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/features.cpp b/src/features.cpp index 394feff..b49ca54 100644 --- a/src/features.cpp +++ b/src/features.cpp @@ -89,7 +89,12 @@ constexpr float bin_to_hz(float samplerate, std::integral auto bins, auto bin) n return 0.5F * samplerate * static_cast(bin) / static_cast(bins - 1); } -constexpr size_t hz_to_bin(float samplerate, std::integral auto bins, float frequency) noexcept { +constexpr size_t hz_to_bin( + float samplerate, + std::integral auto bins, + float frequency, + float (*rounding_func)(float) = std::round +) noexcept { if (samplerate == 0.0F || bins <= 1) { return 0; } @@ -97,7 +102,7 @@ constexpr size_t hz_to_bin(float samplerate, std::integral auto bins, float freq assert(frequency >= 0.0F); assert(frequency <= 0.5F * samplerate); const auto bin = static_cast(bins - 1) * frequency / (0.5F * samplerate); - return static_cast(std::round(bin)); + return static_cast(rounding_func(bin)); } namespace views { @@ -226,14 +231,14 @@ static constexpr auto power_spectrum_view(Spectrum spectrum) { float partial_power([[maybe_unused]] Env& env, Input input, float fmin, float fmax) { fmin = std::clamp(fmin, 0.0F, 0.5F * input.samplerate); fmax = std::clamp(fmax, fmin, 0.5F * input.samplerate); - const auto power_spectrum = power_spectrum_view(input.spectrum); - const auto power_spectrum_range = std::ranges::subrange( + const auto ps = power_spectrum_view(input.spectrum); + const auto ps_range = std::ranges::subrange( // NOLINTBEGIN(*narrowing-conversions) - power_spectrum.begin() + hz_to_bin(input.samplerate, power_spectrum.size(), fmin), - power_spectrum.begin() + hz_to_bin(input.samplerate, power_spectrum.size(), fmax) + ps.begin() + hz_to_bin(input.samplerate, ps.size(), fmin, std::floor), + ps.begin() + hz_to_bin(input.samplerate, ps.size(), fmax, std::floor) // NOLINTEND(*narrowing-conversions) ); - return sum(power_spectrum_range) / sum(power_spectrum); + return sum(ps_range) / sum(ps); } float spectral_peak_frequency([[maybe_unused]] Env& env, Input input) { diff --git a/tests/test_features_partial-power.toml b/tests/test_features_partial-power.toml index f703b17..877ac72 100644 --- a/tests/test_features_partial-power.toml +++ b/tests/test_features_partial-power.toml @@ -62,6 +62,6 @@ input.samplerate = 10 input.spectrum = [0, 1, 2, 3, 4, 0] # sum squares: 30 # frequencies: 0, 1, 2, 3, 4, 5 Hz # ^ -params.fmin = 3.4 # round down to bin 3 -params.fmax = 3.6 # round up to bin 4 +params.fmin = 3.4 # floor to bin 3 +params.fmax = 4.6 # floor to bin 4 result = 0.3 # 9/30