VulcanoLE/src/VulcanoLE/Audio/FFT.cpp

55 lines
2.0 KiB
C++

#include <VulcanoLE/Audio/FFT.h>
#include <VUtils/Logging.h>
#include <VUtils/Math.h>
void FFT::process(stereoSample *frame, double scale) {
std::unique_lock<std::mutex> lck(m_mtx);
if (prepareInput(frame, FFT_SIZE, scale)) {
for (int i = 0; i < FFT_SIZE; ++i) {
m_sample->leftChannel[i] = 0;
m_sample->rightChannel[i] = 0;
}
return;
}
m_fftwPlanRight = fftw_plan_dft_r2c_1d(FFT_SIZE, m_fftwInputRight, m_fftwOutputRight, FFTW_ESTIMATE);
m_fftwPlanLeft = fftw_plan_dft_r2c_1d(FFT_SIZE, m_fftwInputLeft, m_fftwOutputLeft, FFTW_ESTIMATE);
fftw_execute(m_fftwPlanLeft);
fftw_execute(m_fftwPlanRight);
for (int i = 0; i < m_fftwResults; ++i) {
double left = m_fftwOutputLeft[i][0];
double right = m_fftwOutputRight[i][0];
m_sample->leftChannel[i] = left;
m_sample->rightChannel[i] = right;
}
fftw_destroy_plan(m_fftwPlanRight);
fftw_destroy_plan(m_fftwPlanLeft);
}
// return vector of floats!
outputSample *FFT::getData() {
std::unique_lock<std::mutex> lck(m_mtx);
return m_sample;
}
bool FFT::prepareInput(stereoSample *buffer, uint32_t sampleSize, double scale) {
bool is_silent = true;
for (size_t i = 0; i < sampleSize; ++i) {
m_fftwInputLeft[i] = VUtils::Math::clamp(buffer[i].r * scale, -1, 1);
m_fftwInputRight[i] = VUtils::Math::clamp(buffer[i].r * scale, -1, 1);
if (is_silent && (m_fftwInputLeft[i] != 0 || m_fftwInputRight[i] != 0)) is_silent = false;
}
return is_silent;
}
FFT::FFT() {
m_fftwResults = (static_cast<size_t>(BUFFER_SIZE) / 2.0) + 1;
m_fftwInputLeft = static_cast<double *>(fftw_malloc(sizeof(double) * BUFFER_SIZE));
m_fftwInputRight = static_cast<double *>(fftw_malloc(sizeof(double) * BUFFER_SIZE));
m_fftwOutputLeft = static_cast<fftw_complex *>(fftw_malloc(sizeof(fftw_complex) * m_fftwResults));
m_fftwOutputRight = static_cast<fftw_complex *>(fftw_malloc(sizeof(fftw_complex) * m_fftwResults));
}
FFT::~FFT() {
delete m_sample;
}