mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 07:37:46 +00:00
LibDSP: Generalize & improve FFT
Several related improvements to our Fast Fourier Transform implementation: - FFT now operates on spans, allowing it to use many more container types other than Vector. It's intended anyways that FFT transmutes the input data. - FFT is now constexpr, moving the implementation to the header and removing the cpp file. This means that if we have static collections of samples, we can transform them at compile time. - sample_data.data() weirdness is now gone.
This commit is contained in:
parent
428d4ae337
commit
00dd8f8fbe
4 changed files with 36 additions and 66 deletions
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue