| 110 | } |
| 111 | |
| 112 | void RealtimeAnalyser::doFFTAnalysis() |
| 113 | { |
| 114 | // Unroll the input buffer into a temporary buffer, where we'll apply an analysis window followed by an FFT. |
| 115 | uint32_t fftSize = this->fftSize(); |
| 116 | |
| 117 | AudioFloatArray temporaryBuffer(fftSize); |
| 118 | float * inputBuffer = m_inputBuffer.data(); |
| 119 | float * tempP = temporaryBuffer.data(); |
| 120 | |
| 121 | // Take the previous fftSize values from the input buffer and copy into the temporary buffer. |
| 122 | size_t writeIndex = m_writeIndex; |
| 123 | if (writeIndex < fftSize) |
| 124 | { |
| 125 | memcpy(tempP, inputBuffer + writeIndex - fftSize + InputBufferSize, sizeof(*tempP) * (fftSize - writeIndex)); |
| 126 | memcpy(tempP + fftSize - writeIndex, inputBuffer, sizeof(*tempP) * writeIndex); |
| 127 | } |
| 128 | else |
| 129 | { |
| 130 | memcpy(tempP, inputBuffer + writeIndex - fftSize, sizeof(*tempP) * fftSize); |
| 131 | } |
| 132 | |
| 133 | // Window the input samples. |
| 134 | ApplyWindowFunctionInplace(WindowFunction::blackman, tempP, fftSize); |
| 135 | |
| 136 | // Do the analysis. |
| 137 | m_analysisFrame->computeForwardFFT(tempP); |
| 138 | |
| 139 | float * realP = m_analysisFrame->realData(); |
| 140 | float * imagP = m_analysisFrame->imagData(); |
| 141 | |
| 142 | // Erase the packed nyquist component. |
| 143 | imagP[0] = 0; |
| 144 | |
| 145 | // Normalize so than an input sine wave at 0dBfs registers as 0dBfs (undo FFT scaling factor). |
| 146 | const double magnitudeScale = 1.0 / DefaultFFTSize; |
| 147 | |
| 148 | // A value of 0 does no averaging with the previous result. Larger values produce slower, but smoother changes. |
| 149 | double k = m_smoothingTimeConstant; |
| 150 | k = max(0.0, k); |
| 151 | k = min(1.0, k); |
| 152 | |
| 153 | // Convert the analysis data from complex to magnitude and average with the previous result. |
| 154 | float * destination = magnitudeBuffer().data(); |
| 155 | size_t n = magnitudeBuffer().size(); |
| 156 | for (size_t i = 0; i < n; ++i) |
| 157 | { |
| 158 | std::complex<double> c(realP[i], imagP[i]); |
| 159 | double scalarMagnitude = abs(c) * magnitudeScale; |
| 160 | destination[i] = float(k * destination[i] + (1 - k) * scalarMagnitude); |
| 161 | } |
| 162 | } |
| 163 | |
| 164 | void RealtimeAnalyser::getFloatFrequencyData(std::vector<float> & destinationArray) |
| 165 | { |
nothing calls this directly
no test coverage detected