| 28 | } |
| 29 | |
| 30 | Utils::SpecBuffer* Fft::process(const juce::AudioBuffer<float>* audioBuffer) { |
| 31 | mInputBuffer = audioBuffer; |
| 32 | clear(true); |
| 33 | // Runs with first channel |
| 34 | const int numInputSamples = mInputBuffer->getNumSamples(); |
| 35 | const float* pBuffer = mInputBuffer->getReadPointer(0); |
| 36 | mFftFrame.resize(mWindowSize * 2, 0.0f); |
| 37 | int curSample = 0; |
| 38 | bool hasData = numInputSamples > mFftFrame.size(); |
| 39 | float curMax = std::numeric_limits<float>::min(); |
| 40 | |
| 41 | while (hasData) { |
| 42 | // updateProgress(mStartProgress + (mDiffProgress * (static_cast<double>(curSample) / static_cast<double>(numInputSamples)))); |
| 43 | const float* startSample = &pBuffer[curSample]; |
| 44 | int numSamples = mFftFrame.size(); |
| 45 | if (curSample + mFftFrame.size() > numInputSamples) { |
| 46 | numSamples = (numInputSamples - curSample); |
| 47 | } |
| 48 | mFftFrame.clear(); |
| 49 | mFftFrame.resize(mWindowSize * 2, 0.0f); |
| 50 | memcpy(mFftFrame.data(), startSample, numSamples); |
| 51 | mWindowEnvelope.multiplyWithWindowingTable(mFftFrame.data(), mFftFrame.size()); |
| 52 | |
| 53 | // then render our FFT data.. |
| 54 | mForwardFFT.performFrequencyOnlyForwardTransform(mFftFrame.data()); |
| 55 | |
| 56 | // Add fft data to our master array |
| 57 | std::vector<float> newFrame = std::vector<float>(mFftFrame.begin(), mFftFrame.begin() + (mWindowSize / 2)); |
| 58 | float frameMax = juce::FloatVectorOperations::findMaximum(mFftFrame.data(), mFftFrame.size()); |
| 59 | if (frameMax > curMax) curMax = frameMax; |
| 60 | mFftData.push_back(newFrame); |
| 61 | // Normalize fft values according to max frame value |
| 62 | for (size_t i = 0; i < mFftData.back().size(); ++i) { |
| 63 | mFftData.back()[i] /= curMax; |
| 64 | } |
| 65 | |
| 66 | curSample += mHopSize; |
| 67 | if (curSample > numInputSamples) { |
| 68 | hasData = false; |
| 69 | } |
| 70 | } |
| 71 | |
| 72 | return &mFftData; |
| 73 | } |
no test coverage detected