diff --git a/fft.cpp b/fft.cpp new file mode 100644 index 0000000..12c9958 --- /dev/null +++ b/fft.cpp @@ -0,0 +1,25 @@ +#include "fft.h" +#include "string.h" + +FFT::FFT(int size) +{ + fftSize = size; + + fftwIn = (fftwf_complex*)fftwf_malloc(sizeof(fftwf_complex) * fftSize); + fftwOut = (fftwf_complex*)fftwf_malloc(sizeof(fftwf_complex) * fftSize); + fftwPlan = fftwf_plan_dft_1d(fftSize, fftwIn, fftwOut, FFTW_FORWARD, FFTW_MEASURE); +} + +FFT::~FFT() +{ + if (fftwPlan) fftwf_destroy_plan(fftwPlan); + if (fftwIn) fftwf_free(fftwIn); + if (fftwOut) fftwf_free(fftwOut); +} + +void FFT::process(void *dest, void *source) +{ + memcpy(fftwIn, source, fftSize * sizeof(fftwf_complex)); + fftwf_execute(fftwPlan); + memcpy(dest, fftwOut, fftSize * sizeof(fftwf_complex)); +} diff --git a/fft.h b/fft.h new file mode 100644 index 0000000..97f1907 --- /dev/null +++ b/fft.h @@ -0,0 +1,17 @@ +#pragma once + +#include + +class FFT { +public: + FFT(int size); + ~FFT(); + void process(void *dest, void *source); + int getSize() { return fftSize; } + +private: + int fftSize; + fftwf_complex *fftwIn = nullptr; + fftwf_complex *fftwOut = nullptr; + fftwf_plan fftwPlan = nullptr; +}; diff --git a/inputsource.cpp b/inputsource.cpp index 899a474..ff497c1 100644 --- a/inputsource.cpp +++ b/inputsource.cpp @@ -27,17 +27,11 @@ InputSource::InputSource(const char *filename, int fft_size) { } InputSource::~InputSource() { - cleanupFFTW(); + delete fft; munmap(m_data, m_file_size); fclose(m_file); } -void InputSource::cleanupFFTW() { - if (m_fftw_plan != nullptr) fftwf_destroy_plan(m_fftw_plan); - if (m_fftw_in != nullptr) fftwf_free(m_fftw_in); - if (m_fftw_out != nullptr) fftwf_free(m_fftw_out); -} - bool InputSource::getSamples(fftwf_complex *dest, int start, int length) { if (start + length >= sampleCount) @@ -48,7 +42,7 @@ bool InputSource::getSamples(fftwf_complex *dest, int start, int length) } void InputSource::getViewport(float *dest, int x, int y, int width, int height, int zoom) { - + fftwf_complex buffer[m_fft_size]; fftwf_complex *sample_ptr = &m_data[y * getFFTStride()]; for (int i = 0; i < height; i++) { @@ -56,20 +50,20 @@ void InputSource::getViewport(float *dest, int x, int y, int width, int height, if (sample_ptr > m_data + (m_file_size/sizeof(fftwf_complex))) break; - memcpy(m_fftw_in, sample_ptr, m_fft_size * sizeof(fftwf_complex)); + memcpy(buffer, sample_ptr, m_fft_size * sizeof(fftwf_complex)); // Apply window for (int j = 0; j < m_fft_size; j++) { - m_fftw_in[j][0] *= m_window[j]; - m_fftw_in[j][1] *= m_window[j]; + buffer[j][0] *= m_window[j]; + buffer[j][1] *= m_window[j]; } - fftwf_execute(m_fftw_plan); + fft->process(buffer, buffer); for (int j = x; j < width; j++) { int k = (j + m_fft_size / 2) % m_fft_size; - float re = m_fftw_out[k][0]; - float im = m_fftw_out[k][1]; + float re = buffer[k][0]; + float im = buffer[k][1]; float mag = sqrt(re * re + im * im) / m_fft_size; float magdb = 10 * log2(mag) / log2(10); *dest = magdb; @@ -88,13 +82,10 @@ int InputSource::getWidth() { } void InputSource::setFFTSize(int size) { - cleanupFFTW(); + delete fft; + fft = new FFT(size); m_fft_size = size; - m_fftw_in = (fftwf_complex*)fftwf_malloc(sizeof(fftwf_complex) * m_fft_size); - m_fftw_out = (fftwf_complex*)fftwf_malloc(sizeof(fftwf_complex) * m_fft_size); - m_fftw_plan = fftwf_plan_dft_1d(m_fft_size, m_fftw_in, m_fftw_out, FFTW_FORWARD, FFTW_MEASURE); - m_window.reset(new float[m_fft_size]); for (int i = 0; i < m_fft_size; i++) { m_window[i] = 0.5f * (1.0f - cos(Tau * i / (m_fft_size - 1))); diff --git a/inputsource.h b/inputsource.h index 45bd189..0d127ac 100644 --- a/inputsource.h +++ b/inputsource.h @@ -1,4 +1,6 @@ #pragma once + +#include "fft.h" #include #include @@ -11,9 +13,7 @@ private: fftwf_complex *m_data; int m_fft_size; - fftwf_complex *m_fftw_in = nullptr; - fftwf_complex *m_fftw_out = nullptr; - fftwf_plan m_fftw_plan = nullptr; + FFT *fft = nullptr; std::unique_ptr m_window; @@ -21,7 +21,6 @@ private: int m_max_zoom; int getFFTStride(); - void cleanupFFTW(); public: diff --git a/inspectrum.pro b/inspectrum.pro index 01fb30a..c67d27b 100644 --- a/inspectrum.pro +++ b/inspectrum.pro @@ -4,5 +4,5 @@ TARGET = inspectrum TEMPLATE = app LIBS += -lfftw3f -HEADERS += mainwindow.h inputsource.h spectrogram.h spectrogramcontrols.h -SOURCES += main.cpp mainwindow.cpp inputsource.cpp spectrogram.cpp spectrogramcontrols.cpp +HEADERS += mainwindow.h fft.h inputsource.h spectrogram.h spectrogramcontrols.h +SOURCES += main.cpp fft.cpp mainwindow.cpp inputsource.cpp spectrogram.cpp spectrogramcontrols.cpp