Fixed FFT
This commit is contained in:
parent
2e266fe038
commit
d0e8eb0d5e
3 changed files with 36 additions and 41 deletions
|
@ -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{};
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue