| 14 | #include "FFT.h" |
| 15 | |
| 16 | SpectrumTransformer::SpectrumTransformer( bool needsOutput, |
| 17 | eWindowFunctions inWindowType, |
| 18 | eWindowFunctions outWindowType, |
| 19 | size_t windowSize, unsigned stepsPerWindow, |
| 20 | bool leadingPadding, bool trailingPadding ) |
| 21 | : mWindowSize{ windowSize } |
| 22 | , mSpectrumSize{ 1 + mWindowSize / 2 } |
| 23 | , mStepsPerWindow{ stepsPerWindow } |
| 24 | , mStepSize{ mWindowSize / mStepsPerWindow } |
| 25 | , mLeadingPadding{ leadingPadding } |
| 26 | , mTrailingPadding{ trailingPadding } |
| 27 | , hFFT{ GetFFT(mWindowSize) } |
| 28 | , mFFTBuffer( mWindowSize ) |
| 29 | , mInWaveBuffer( mWindowSize ) |
| 30 | , mOutOverlapBuffer( mWindowSize ) |
| 31 | , mNeedsOutput{ needsOutput } |
| 32 | { |
| 33 | // Check preconditions |
| 34 | |
| 35 | // Powers of 2 only! |
| 36 | wxASSERT(mWindowSize > 0 && |
| 37 | 0 == (mWindowSize & (mWindowSize - 1))); |
| 38 | |
| 39 | wxASSERT(mWindowSize % mStepsPerWindow == 0); |
| 40 | |
| 41 | wxASSERT(!(inWindowType == eWinFuncRectangular && outWindowType == eWinFuncRectangular)); |
| 42 | |
| 43 | // To do: check that inWindowType, outWindowType, and mStepsPerWindow |
| 44 | // are compatible for correct overlap-add reconstruction. |
| 45 | |
| 46 | // Create windows as needed |
| 47 | if (inWindowType != eWinFuncRectangular) { |
| 48 | mInWindow.resize(mWindowSize); |
| 49 | std::fill(mInWindow.begin(), mInWindow.end(), 1.0f); |
| 50 | NewWindowFunc(inWindowType, mWindowSize, false, mInWindow.data()); |
| 51 | } |
| 52 | if (outWindowType != eWinFuncRectangular) { |
| 53 | mOutWindow.resize(mWindowSize); |
| 54 | std::fill(mOutWindow.begin(), mOutWindow.end(), 1.0f); |
| 55 | NewWindowFunc(outWindowType, mWindowSize, false, mOutWindow.data()); |
| 56 | } |
| 57 | |
| 58 | // Must scale one or the other window so overlap-add |
| 59 | // comes out right |
| 60 | double denom = 0; |
| 61 | for (size_t ii = 0; ii < mWindowSize; ii += mStepSize) { |
| 62 | denom += |
| 63 | (mInWindow.empty() ? 1.0 : mInWindow[ii]) |
| 64 | * |
| 65 | (mOutWindow.empty() ? 1.0 : mOutWindow[ii]); |
| 66 | } |
| 67 | // It is ASSUMED that you have chosen window types and |
| 68 | // steps per window, so that this sum denom would be the |
| 69 | // same, starting the march anywhere from 0 to mStepSize - 1. |
| 70 | // Else, your overlap-add won't be right, and the transformer |
| 71 | // might not be an identity even when you do nothing to the |
| 72 | // spectra. |
| 73 | |