summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Userland/Applications/SoundPlayer/BarsVisualizationWidget.cpp2
-rw-r--r--Userland/Libraries/LibDSP/CMakeLists.txt1
-rw-r--r--Userland/Libraries/LibDSP/FFT.cpp62
-rw-r--r--Userland/Libraries/LibDSP/FFT.h37
4 files changed, 36 insertions, 66 deletions
diff --git a/Userland/Applications/SoundPlayer/BarsVisualizationWidget.cpp b/Userland/Applications/SoundPlayer/BarsVisualizationWidget.cpp
index 0c87ced853..3e6ca3d75b 100644
--- a/Userland/Applications/SoundPlayer/BarsVisualizationWidget.cpp
+++ b/Userland/Applications/SoundPlayer/BarsVisualizationWidget.cpp
@@ -26,7 +26,7 @@ void BarsVisualizationWidget::paint_event(GUI::PaintEvent& event)
if (m_sample_buffer.is_empty())
return;
- LibDSP::fft(m_sample_buffer, false);
+ LibDSP::fft(m_sample_buffer.span(), false);
double max = AK::sqrt(m_sample_count * 2.);
double freq_bin = m_samplerate / (double)m_sample_count;
diff --git a/Userland/Libraries/LibDSP/CMakeLists.txt b/Userland/Libraries/LibDSP/CMakeLists.txt
index f7dc72fcd1..a5de6f120e 100644
--- a/Userland/Libraries/LibDSP/CMakeLists.txt
+++ b/Userland/Libraries/LibDSP/CMakeLists.txt
@@ -3,7 +3,6 @@ set(SOURCES
Track.cpp
Effects.cpp
Synthesizers.cpp
- FFT.cpp
)
serenity_lib(LibDSP dsp)
diff --git a/Userland/Libraries/LibDSP/FFT.cpp b/Userland/Libraries/LibDSP/FFT.cpp
deleted file mode 100644
index 8083333f96..0000000000
--- a/Userland/Libraries/LibDSP/FFT.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2021, Cesar Torres <shortanemoia@protonmail.com>
- *
- * SPDX-License-Identifier: BSD-2-Clause
- */
-
-#include "FFT.h"
-#include <AK/Complex.h>
-#include <AK/Math.h>
-
-namespace LibDSP {
-
-// This function uses the input vector as output too. therefore, if you wish to
-// leave it intact, pass a copy to this function
-//
-// The sampling frequency must be more than twice the frequency to resolve.
-// The sample window must be at least large enough to reflect the periodicity
-// of the smallest frequency to be resolved.
-//
-// For example, to resolve a 10 KHz and a 2 Hz sine waves we need at least
-// a samplerate of 20 KHz and a window of 0.5 seconds
-//
-// If invert is true, this function computes the inverse discrete fourier transform.
-//
-// The data vector must be a power of 2
-// Adapted from https://cp-algorithms.com/algebra/fft.html
-void fft(Vector<Complex<double>>& sample_data, bool invert)
-{
- int n = sample_data.size();
- auto data = sample_data.data();
-
- for (int i = 1, j = 0; i < n; i++) {
- int bit = n >> 1;
- for (; j & bit; bit >>= 1)
- j ^= bit;
- j ^= bit;
-
- if (i < j)
- swap(data[i], data[j]);
- }
-
- for (int len = 2; len <= n; len <<= 1) {
- double ang = 2 * AK::Pi<double> / len * (invert ? -1 : 1);
- Complex<double> wlen(AK::cos(ang), AK::sin(ang));
- for (int i = 0; i < n; i += len) {
- Complex<double> w = { 1., 0. };
- for (int j = 0; j < len / 2; j++) {
- Complex<double> u = data[i + j], v = data[i + j + len / 2] * w;
- data[i + j] = u + v;
- data[i + j + len / 2] = u - v;
- w *= wlen;
- }
- }
- }
-
- if (invert) {
- for (int i = 0; i < n; i++)
- data[i] /= n;
- }
-}
-
-}
diff --git a/Userland/Libraries/LibDSP/FFT.h b/Userland/Libraries/LibDSP/FFT.h
index d13d358af2..c9db991b1d 100644
--- a/Userland/Libraries/LibDSP/FFT.h
+++ b/Userland/Libraries/LibDSP/FFT.h
@@ -7,10 +7,43 @@
#pragma once
#include <AK/Complex.h>
-#include <AK/Vector.h>
+#include <AK/Math.h>
+#include <AK/Span.h>
namespace LibDSP {
-void fft(Vector<Complex<double>>& sample_data, bool invert = false);
+constexpr void fft(Span<Complex<double>> sample_data, bool invert = false)
+{
+ int n = sample_data.size();
+
+ for (int i = 1, j = 0; i < n; i++) {
+ int bit = n >> 1;
+ for (; j & bit; bit >>= 1)
+ j ^= bit;
+ j ^= bit;
+
+ if (i < j)
+ swap(sample_data[i], sample_data[j]);
+ }
+
+ for (int len = 2; len <= n; len <<= 1) {
+ double ang = 2 * AK::Pi<double> / len * (invert ? -1 : 1);
+ Complex<double> wlen(AK::cos(ang), AK::sin(ang));
+ for (int i = 0; i < n; i += len) {
+ Complex<double> w = { 1., 0. };
+ for (int j = 0; j < len / 2; j++) {
+ Complex<double> u = sample_data[i + j], v = sample_data[i + j + len / 2] * w;
+ sample_data[i + j] = u + v;
+ sample_data[i + j + len / 2] = u - v;
+ w *= wlen;
+ }
+ }
+ }
+
+ if (invert) {
+ for (int i = 0; i < n; i++)
+ sample_data[i] /= n;
+ }
+}
}