diff --git a/headers/VulcanoLE/Audio/FFT.h b/headers/VulcanoLE/Audio/FFT.h index 5217444..e034c42 100644 --- a/headers/VulcanoLE/Audio/FFT.h +++ b/headers/VulcanoLE/Audio/FFT.h @@ -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{}; diff --git a/src/VulcanoLE/Audio/AudioGrabber.cpp b/src/VulcanoLE/Audio/AudioGrabber.cpp index 2c4d8e4..7c19305 100644 --- a/src/VulcanoLE/Audio/AudioGrabber.cpp +++ b/src/VulcanoLE/Audio/AudioGrabber.cpp @@ -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 { diff --git a/src/VulcanoLE/Audio/FFT.cpp b/src/VulcanoLE/Audio/FFT.cpp index 54e1d9b..0602df9 100644 --- a/src/VulcanoLE/Audio/FFT.cpp +++ b/src/VulcanoLE/Audio/FFT.cpp @@ -1,23 +1,28 @@ #include #include +#include -void FFT::process(stereoSample *frame) { +void FFT::process(stereoSample *frame, double scale) { std::unique_lock lck(m_mtx); - prepareInput(frame, FFT_SIZE); - m_fftwPlanLeft = fftw_plan_dft_r2c_1d(static_cast(BUFFER_SIZE), m_fftwInputLeft, - m_fftwOutputLeft, FFTW_ESTIMATE); - m_fftwPlanRight = fftw_plan_dft_r2c_1d(static_cast(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(BUFFER_SIZE) / 2) + 1; - - m_fftwInputLeft = static_cast( - fftw_malloc(sizeof(double) * BUFFER_SIZE)); - m_fftwInputRight = static_cast( - fftw_malloc(sizeof(double) * BUFFER_SIZE)); - - m_fftwOutputLeft = static_cast( - fftw_malloc(sizeof(fftw_complex) * m_fftwResults)); - m_fftwOutputRight = static_cast( - fftw_malloc(sizeof(fftw_complex) * m_fftwResults)); + m_fftwResults = (static_cast(BUFFER_SIZE) / 2.0) + 1; + m_fftwInputLeft = static_cast(fftw_malloc(sizeof(double) * BUFFER_SIZE)); + m_fftwInputRight = static_cast(fftw_malloc(sizeof(double) * BUFFER_SIZE)); + m_fftwOutputLeft = static_cast(fftw_malloc(sizeof(fftw_complex) * m_fftwResults)); + m_fftwOutputRight = static_cast(fftw_malloc(sizeof(fftw_complex) * m_fftwResults)); } FFT::~FFT() { delete m_sample;