Files
QMKhost/src/signal_processing/fft.hpp
T
2022-06-26 12:47:43 -07:00

121 lines
2.4 KiB
C++

#pragma once
#include <stdio.h>
#include <cstdint>
#include <vector>
#include <math.h>
#include <cstring> // memset
#include <fftw3.h>
#include "utility/buffer.hpp"
class FFT_Visualizer {
public:
FFT_Visualizer(
size_t width,
size_t height,
// Advanced options you probably shouldn't touch
double HZ_MIN = 20,
double HZ_MAX = 20000,
uint32_t DFT_TOTAL_SIZE = 1 << 15,
// #define conf_spectrum_dft_size 2 (between 1 and 5, inclusive)
uint32_t DFT_NONZERO_SIZE = (2048 * (2*2 + 4)),
double GAIN = 10
);
~FFT_Visualizer();
void update(
const Buffer& buf
);
size_t compute_buffer_output_size() const;
const std::vector<size_t>& get_output() {
return output;
};
private:
///
// Visualizer parameters
///
// Horizontal resolution
const size_t width;
// Vertical resolution
const size_t height;
// Leftmost frequency in spectrum
const double HZ_MIN;
// Rightmost frequency in spectrum
const double HZ_MAX;
// Not sure what this does
const uint32_t DFT_TOTAL_SIZE;
// Not sure what this does, either
const uint32_t DFT_NONZERO_SIZE;
// Visualization spectrum gain
// tune if bars are too small
const double GAIN;
// Not sure what this does
const double DYNAMIC_RANGE;
///
// FFTW resources
///
fftw_plan plan;
// How many output values fftw will give us
size_t fftw_results;
// Input array. This is filled with buffer data
// that has been filtered through a window.
double* fftw_input;
// FFT output array.
fftw_complex *fftw_output;
///
// Intermediate values
///
// The magnitudes of the complex values fftw returns.
std::vector<double> freq_magnitudes;
// An array of frequency bins, scaled logarithmically.
std::vector<double> logspace;
// Nearly-complete output.
// This is necessary because some frequency bins
// may be empty, and need to be interpolated
std::vector<
std::pair<
size_t,
double
>
> partial_output;
// Output vector, with empty bins interpolated.
// The maximum possible value of an element in this
// vector is `height`.
std::vector<size_t> output;
///
// Helper methods
// See definition for docs.
///
void GenLogspace();
double Bin2Hz(size_t bin) const;
void ApplyWindow(
double *output,
const int16_t *input,
ssize_t samples
) const;
double Interpolate(
size_t x,
size_t h_idx
);
};