#include "FFTDisplayProcessor.h" FFTDisplayProcessor::FFTDisplayProcessor (double sr, int numOfAverages, int fftOrder, int numOfChannels) : enable (false), sampleRate (sr), fft (fftOrder), windowBuffer (1, fft.getSize()), inputSampleFifo (numOfChannels, inputSampleFifoSize), fftTimeBuffer (numOfChannels, fft.getSize()), fftFreqBuffer (numOfChannels, fft.getSize() * 2), averageSampleFifo (numOfChannels, 1 + ((fft.getSize() / 2) * numOfAverages)), averageBuffer (numOfChannels, ((fft.getSize() / 2) * numOfAverages)), resultsBufferFifo (numOfChannels, (fft.getSize() / 2) * resultBufferFifoSize), resultBuffer (numOfChannels, fft.getSize() / 2) { WindowingFunction::fillWindowingTables (windowBuffer.getWritePointer (0), fft.getSize(), WindowingFunction::blackman); } void FFTDisplayProcessor::reset (double newSampleRate) { if (newSampleRate == 0.0) { inputSampleFifo.reset(); resultsBufferFifo.reset(); } jassert (newSampleRate > 0.0); sampleRate = newSampleRate; } void FFTDisplayProcessor::process (const AudioBuffer& buffer) { if (! enable) return; if (inputSampleFifo.getFreeSpace() >= buffer.getNumSamples()) inputSampleFifo.writeSamplesToFifo (buffer); while (inputSampleFifo.getNumReady() >= fft.getSize()) { inputSampleFifo.copyWholeBuffer (fftTimeBuffer); inputSampleFifo.readSamplesFromFifo (resultBuffer); // Dummy Read for (int ch = 0; ch < fftTimeBuffer.getNumChannels(); ++ch) { FloatVectorOperations::multiply (fftTimeBuffer.getWritePointer (ch), windowBuffer.getReadPointer (0), fft.getSize()); fftFreqBuffer.clear(); fftFreqBuffer.copyFrom (ch, 0, fftTimeBuffer, ch, 0, fftTimeBuffer.getNumSamples()); fft.performFrequencyOnlyForwardTransform (fftFreqBuffer.getWritePointer (ch)); resultBuffer.copyFrom (ch, 0, fftFreqBuffer, ch, 0, resultBuffer.getNumSamples()); } if (averageSampleFifo.getFreeSpace() >= resultBuffer.getNumSamples()) averageSampleFifo.writeSamplesToFifo (resultBuffer); if (averageSampleFifo.getFreeSpace() == 0) { const float numOfAverages = (float) averageBuffer.getNumSamples() / (float) resultBuffer.getNumSamples(); const float ratio = 1.f / numOfAverages; averageSampleFifo.copyWholeBuffer (averageBuffer); averageSampleFifo.readSamplesFromFifo (resultBuffer); // Dummy Read averageBuffer.applyGain (ratio); resultBuffer.clear(); for (int avg = 0; avg < numOfAverages; ++avg) for (int ch = 0; ch < resultBuffer.getNumChannels(); ++ch) resultBuffer.addFrom (ch, 0, averageBuffer, ch, avg * resultBuffer.getNumSamples(), resultBuffer.getNumSamples()); writeBufferToResult (resultBuffer); } } } int FFTDisplayProcessor::readBufferFromResult (AudioBuffer &buffer) { SpinLock::ScopedLockType scopedLock (spinLock); return resultsBufferFifo.readSamplesFromFifo (buffer); } int FFTDisplayProcessor::writeBufferToResult (const AudioBuffer &buffer) { SpinLock::ScopedLockType scopedLock (spinLock); return resultsBufferFifo.writeSamplesToFifo (buffer); }