| 192 | } |
| 193 | |
| 194 | void SpectrumTransformer::FillFirstWindow() |
| 195 | { |
| 196 | // Transform samples to frequency domain, windowed as needed |
| 197 | { |
| 198 | auto pFFTBuffer = mFFTBuffer.data(), pInWaveBuffer = mInWaveBuffer.data(); |
| 199 | if (mInWindow.size() > 0) { |
| 200 | auto pInWindow = mInWindow.data(); |
| 201 | for (size_t ii = 0; ii < mWindowSize; ++ii) |
| 202 | *pFFTBuffer++ = *pInWaveBuffer++ * *pInWindow++; |
| 203 | } |
| 204 | else |
| 205 | memmove(pFFTBuffer, pInWaveBuffer, mWindowSize * sizeof(float)); |
| 206 | } |
| 207 | RealFFTf(mFFTBuffer.data(), hFFT.get()); |
| 208 | |
| 209 | auto &record = Nth(0); |
| 210 | |
| 211 | // Store real and imaginary parts for later inverse FFT |
| 212 | { |
| 213 | float *pReal = &record.mRealFFTs[1]; |
| 214 | float *pImag = &record.mImagFFTs[1]; |
| 215 | int *pBitReversed = &hFFT->BitReversed[1]; |
| 216 | const auto last = mSpectrumSize - 1; |
| 217 | for (size_t ii = 1; ii < last; ++ii) { |
| 218 | const int kk = *pBitReversed++; |
| 219 | *pReal++ = mFFTBuffer[kk]; |
| 220 | *pImag++ = mFFTBuffer[kk + 1]; |
| 221 | } |
| 222 | // DC and Fs/2 bins need to be handled specially |
| 223 | const float dc = mFFTBuffer[0]; |
| 224 | record.mRealFFTs[0] = dc; |
| 225 | |
| 226 | const float nyquist = mFFTBuffer[1]; |
| 227 | record.mImagFFTs[0] = nyquist; // For Fs/2, not really imaginary |
| 228 | } |
| 229 | } |
| 230 | |
| 231 | void SpectrumTransformer::RotateWindows() |
| 232 | { |