1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 11:37:44 +00:00

SoundPlayer: Rework FFT visualization

The input to the FFT was distorted by the usage of fabs on the samples.
It led to a big DC offset and a distorted spectrum. Simply removing fabs
improves the quality of the spectrum a lot.

The FFT input should be windowed to reduce spectral leakage. This also
improves the visual quality of the spectrum.

Also, no need to do a FFT of the whole buffer if we only mean to render
64 bars. A 8192 point FFT may smooth out fast local changes but at 44100
hz samplerate that's 200 ms worth of sound which significantly reduces
FPS.

A better approach for a fluent visualization is to do small FFTs at the
current playing position inside the current buffer.
There may be a better way to get the current playing position, but for
now it's implemented as an estimation depending on how many frames where
already rendered with the current buffer.
Also I picked y-axis log scale as a default because there's usually a
big difference in energy between low and high frequency bands. log scale
looks nicer.
This commit is contained in:
Arne Elster 2022-01-09 23:21:55 +01:00 committed by Andreas Kling
parent 9edaa033e5
commit a5d95aa6e8
2 changed files with 35 additions and 31 deletions

View file

@ -8,6 +8,7 @@
#pragma once
#include "VisualizationWidget.h"
#include <AK/Array.h>
#include <AK/Complex.h>
#include <AK/FixedArray.h>
#include <LibAudio/Buffer.h>
@ -25,8 +26,13 @@ private:
void render(GUI::PaintEvent&, FixedArray<double> const&) override;
void context_menu_event(GUI::ContextMenuEvent& event) override;
FixedArray<Complex<double>> m_fft_samples;
Vector<int> m_gfx_falling_bars;
static constexpr size_t fft_size = 256;
static constexpr size_t bar_count = 64;
static constexpr size_t values_per_bar = (fft_size / 2) / bar_count;
Array<Complex<double>, fft_size> m_fft_samples {};
Array<double, fft_size> m_fft_window {};
Array<int, bar_count> m_gfx_falling_bars {};
bool m_is_using_last;
bool m_adjust_frequencies;
RefPtr<GUI::Menu> m_context_menu;