Fixed FFT

This commit is contained in:
Maurice Grönwoldt 2021-03-22 20:46:29 +01:00
parent 2e266fe038
commit d0e8eb0d5e
3 changed files with 36 additions and 41 deletions

View file

@ -8,9 +8,9 @@ class FFT {
public: public:
FFT(); FFT();
~FFT(); ~FFT();
void process(stereoSample *frame); void process(stereoSample *frame, double d);
outputSample *getData(); outputSample *getData();
bool prepareInput(stereoSample *buffer, uint32_t sampleSize); bool prepareInput(stereoSample *buffer, uint32_t sampleSize, double scale);
protected: protected:
double *m_fftwInputLeft{}; double *m_fftwInputLeft{};
double *m_fftwInputRight{}; double *m_fftwInputRight{};

View file

@ -141,8 +141,8 @@ void AudioGrabber::calculateRMS(stereoSample *pFrame) {
float squareL = 0, meanL; float squareL = 0, meanL;
float squareR = 0, meanR; float squareR = 0, meanR;
for (int i = 0; i < BUFFER_SIZE; i++) { for (int i = 0; i < BUFFER_SIZE; i++) {
squareL += std::pow(pFrame[0].l, 2); squareL += std::pow(pFrame[0].l * m_scale, 2);
squareR += std::pow(pFrame[0].r, 2); squareR += std::pow(pFrame[0].r * m_scale, 2);
} }
meanL = (squareL / (float) (BUFFER_SIZE)); meanL = (squareL / (float) (BUFFER_SIZE));
meanR = (squareR / (float) (BUFFER_SIZE)); meanR = (squareR / (float) (BUFFER_SIZE));
@ -152,8 +152,8 @@ void AudioGrabber::calculateRMS(stereoSample *pFrame) {
void AudioGrabber::calculatePEAK(stereoSample *pFrame) { void AudioGrabber::calculatePEAK(stereoSample *pFrame) {
stereoSampleFrame max = { 0, 0 }; stereoSampleFrame max = { 0, 0 };
for (int i = 0; i < BUFFER_SIZE; i++) { for (int i = 0; i < BUFFER_SIZE; i++) {
float left = std::abs(pFrame[0].l); float left = std::abs(pFrame[0].l * m_scale);
float right = std::abs(pFrame[0].r); float right = std::abs(pFrame[0].r * m_scale);
if (left > max.l) if (left > max.l)
max.l = left; max.l = left;
if (right > max.r) if (right > max.r)
@ -172,12 +172,7 @@ bool AudioGrabber::work() {
if (this->read(m_buffer, BUFFER_SIZE)) { if (this->read(m_buffer, BUFFER_SIZE)) {
switch (requestMode) { switch (requestMode) {
case ReqMode::FFT: case ReqMode::FFT:
// FFT get's better results with maybe a bit scaling.. for RMS and PEAK this gets "worse" fft.process(m_buffer, m_scale);
for (int i = 0; i < BUFFER_SIZE; ++i) {
m_buffer[i].l *= m_scale;
m_buffer[i].r *= m_scale;
}
fft.process(m_buffer);
break; break;
case ReqMode::RMS: case ReqMode::RMS:
calculateRMS(m_buffer); calculateRMS(m_buffer);
@ -185,10 +180,11 @@ bool AudioGrabber::work() {
case ReqMode::PEAK: case ReqMode::PEAK:
calculatePEAK(m_buffer); calculatePEAK(m_buffer);
break; break;
default: default: {
fft.process(m_buffer);
calculateRMS(m_buffer); calculateRMS(m_buffer);
calculatePEAK(m_buffer); calculatePEAK(m_buffer);
fft.process(m_buffer, m_scale);
}
} }
return true; return true;
} else { } else {

View file

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