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:
FFT();
~FFT();
void process(stereoSample *frame);
void process(stereoSample *frame, double d);
outputSample *getData();
bool prepareInput(stereoSample *buffer, uint32_t sampleSize);
bool prepareInput(stereoSample *buffer, uint32_t sampleSize, double scale);
protected:
double *m_fftwInputLeft{};
double *m_fftwInputRight{};

View file

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

View file

@ -1,23 +1,28 @@
#include <VulcanoLE/Audio/FFT.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);
prepareInput(frame, FFT_SIZE);
m_fftwPlanLeft = fftw_plan_dft_r2c_1d(static_cast<int>(BUFFER_SIZE), m_fftwInputLeft,
m_fftwOutputLeft, FFTW_ESTIMATE);
m_fftwPlanRight = fftw_plan_dft_r2c_1d(static_cast<int>(BUFFER_SIZE), m_fftwInputRight,
m_fftwOutputRight, FFTW_ESTIMATE);
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);
fftw_destroy_plan(m_fftwPlanLeft);
fftw_destroy_plan(m_fftwPlanRight);
for (int i = 0; i < FFT_SIZE; ++i) {
double left = (double(*m_fftwOutputLeft[i]));
double right = (double(*m_fftwOutputRight[i]));
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!
@ -26,28 +31,22 @@ outputSample *FFT::getData() {
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;
for (auto i = 0u; i < sampleSize; ++i) {
m_fftwInputLeft[i] = buffer[i].l;
m_fftwInputRight[i] = buffer[i].r;
if (is_silent && (m_fftwInputLeft[i] > 0 || m_fftwInputRight[i] > 0)) is_silent = false;
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) + 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));
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;