From d2510d0caa64d4deebdc1823189ce4dbf92b0c40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?kleines=20Filmr=C3=B6llchen?= Date: Fri, 4 Mar 2022 00:25:15 +0100 Subject: SoundPlayer: Implement logarithmic spectrum display Now that we have y-axis (gain) logarithmic display, we should also have x-axis (frequency) logarithmic display; that's how our ears work. This can be turned off with an option, but it generally looks much nicer. --- .../SoundPlayer/BarsVisualizationWidget.cpp | 37 ++++++++++++++++++---- .../SoundPlayer/BarsVisualizationWidget.h | 4 ++- 2 files changed, 33 insertions(+), 8 deletions(-) (limited to 'Userland') diff --git a/Userland/Applications/SoundPlayer/BarsVisualizationWidget.cpp b/Userland/Applications/SoundPlayer/BarsVisualizationWidget.cpp index 4553060de0..c8ffa9608e 100644 --- a/Userland/Applications/SoundPlayer/BarsVisualizationWidget.cpp +++ b/Userland/Applications/SoundPlayer/BarsVisualizationWidget.cpp @@ -36,14 +36,31 @@ void BarsVisualizationWidget::render(GUI::PaintEvent& event, FixedArray Array groups {}; - for (size_t i = 0; i < fft_size / 2; i += values_per_bar) { - double const magnitude = m_fft_samples[i].magnitude(); - groups[i / values_per_bar] = magnitude; - for (size_t j = 0; j < values_per_bar; j++) { - double const magnitude = m_fft_samples[i + j].magnitude(); - groups[i / values_per_bar] += magnitude; + if (m_logarithmic_spectrum) { + auto const log_bar_size = static_cast(bar_count) / AK::log2(fft_size); + + for (size_t i = 0; i < bar_count; ++i) { + auto const bar_start = i == 0 ? 0 : static_cast(floor(AK::pow(2., static_cast(i) / log_bar_size))); + auto const bar_end = clamp(static_cast(floor(AK::pow(2., static_cast(i + 1) / log_bar_size))), bar_start + 1, cutoff); + auto const values_in_bar = bar_end - bar_start; + + for (size_t sample_index = bar_start; sample_index < bar_start + values_in_bar; sample_index++) { + double const magnitude = m_fft_samples[sample_index].magnitude(); + groups[i] += magnitude; + } + groups[i] /= static_cast(values_in_bar); + } + } else { + static constexpr size_t values_per_bar = (fft_size / 2) / bar_count; + for (size_t i = 0; i < fft_size / 2; i += values_per_bar) { + double const magnitude = m_fft_samples[i].magnitude(); + groups[i / values_per_bar] = magnitude; + for (size_t j = 0; j < values_per_bar; j++) { + double const magnitude = m_fft_samples[i + j].magnitude(); + groups[i / values_per_bar] += magnitude; + } + groups[i / values_per_bar] /= values_per_bar; } - groups[i / values_per_bar] /= values_per_bar; } double const max_peak_value = AK::sqrt(static_cast(fft_size * 2)); @@ -71,6 +88,7 @@ void BarsVisualizationWidget::render(GUI::PaintEvent& event, FixedArray BarsVisualizationWidget::BarsVisualizationWidget() : m_is_using_last(false) , m_adjust_frequencies(true) + , m_logarithmic_spectrum(true) { m_context_menu = GUI::Menu::construct(); auto frequency_energy_action = GUI::Action::create_checkable("Adjust frequency energy (for aesthetics)", [&](GUI::Action& action) { @@ -78,6 +96,11 @@ BarsVisualizationWidget::BarsVisualizationWidget() }); frequency_energy_action->set_checked(true); m_context_menu->add_action(frequency_energy_action); + auto logarithmic_spectrum_action = GUI::Action::create_checkable("Scale spectrum logarithmically", [&](GUI::Action& action) { + m_logarithmic_spectrum = action.is_checked(); + }); + logarithmic_spectrum_action->set_checked(true); + m_context_menu->add_action(logarithmic_spectrum_action); m_fft_window = LibDSP::Window::hann(); diff --git a/Userland/Applications/SoundPlayer/BarsVisualizationWidget.h b/Userland/Applications/SoundPlayer/BarsVisualizationWidget.h index d2bd539422..b8739d1dca 100644 --- a/Userland/Applications/SoundPlayer/BarsVisualizationWidget.h +++ b/Userland/Applications/SoundPlayer/BarsVisualizationWidget.h @@ -28,7 +28,8 @@ private: static constexpr size_t fft_size = 512; static constexpr size_t bar_count = 64; - static constexpr size_t values_per_bar = (fft_size / 2) / bar_count; + // Things become weird near the Nyquist limit. Just don't use that FFT data. + static constexpr size_t cutoff = fft_size - 32; Array, fft_size> m_fft_samples {}; Array m_fft_window {}; @@ -36,5 +37,6 @@ private: Array m_gfx_falling_bars {}; bool m_is_using_last; bool m_adjust_frequencies; + bool m_logarithmic_spectrum; RefPtr m_context_menu; }; -- cgit v1.2.3