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:
|
||||
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{};
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue