| # Notes on PFFFT |
| We strongly recommend to **read this file** before using PFFFT and to **always wrap** the original C library within a C++ wrapper. |
| |
| [Example of PFFFT wrapper](https://cs.chromium.org/chromium/src/third_party/webrtc/modules/audio_processing/utility/pffft_wrapper.h). |
| |
| ## Scratch buffer |
| The caller can optionally provide a scratch buffer. When not provided, VLA is used to provide a thread-safe option. |
| However, it is recommended to write a C++ wrapper which allocates its own scratch buffer. |
| Note that the scratch buffer has the same memory alignment requirements of the input and output vectors. |
| |
| ## Output layout |
| PFFFT computes the forward transform with two possible output layouts: |
| 1. ordered |
| 2. unordered |
| |
| ### Ordered layout |
| Calling `pffft_transform_ordered` produces an array of **interleaved real and imaginary parts**. |
| The last Fourier coefficient is purely real and stored in the imaginary part of the DC component (which is also purely real). |
| |
| ### Unordered layout |
| Calling `pffft_transform` produces an array with a more complex structure, but in a more efficient way than `pffft_transform_ordered`. |
| Below, the output produced by Matlab and that produced by PFFFT are compared. |
| The comparison is made for a 32 point transform of a 16 sample buffer. |
| A 32 point transform has been chosen as this is the minimum supported by PFFFT. |
| |
| Important notes: |
| - In Matlab the DC (Matlab index 1 [R1, I1]]) and Nyquist (Matlab index 17 [R17, I17]) values are not repeated as complex conjugates. |
| - In PFFFT the Nyquist real and imaginary parts ([R17, I17]) are omitted entirely. |
| - In PFFFT the final 8 values (4 real and 4 imaginary) are not in the same order as all of the others. |
| - In PFFFT all imaginary parts are stored as negatives (like second half in Matlab). |
| |
| ``` |
| +-------+-----------+-------+-------+ |
| | Index | Matlab | Index | PFFFT | |
| +-------+-----------+-------+-------+ |
| | 1 | R1 + I1 | 0 | R1 | |
| | 2 | R2+ I2 | 1 | R2 | |
| | 3 | R3 + I3 | 2 | R3 | |
| | 4 | R4 + I4 | 3 | R4 | |
| | 5 | R5 + I5 | 4 | -I1 | |
| | 6 | R6 + I6 | 5 | -I2 | |
| | 7 | R7 + I7 | 6 | -I3 | |
| | 8 | R8 + I8 | 7 | -I4 | |
| | 9 | R9 + I9 | 8 | R5 | |
| | 10 | R10 + I10 | 9 | R6 | |
| | 11 | R11 + I11 | 10 | R7 | |
| | 12 | R12 + I12 | 11 | R8 | |
| | 13 | R13 + I13 | 12 | -I5 | |
| | 14 | R14 + I14 | 13 | -I6 | |
| | 15 | R15 + I15 | 14 | -I7 | |
| | 16 | R16 + I16 | 15 | -I8 | |
| | 17 | R17 + I17 | 16 | R9 | |
| | 18 | R16 - I16 | 17 | R10 | |
| | 19 | R15 - I15 | 18 | R11 | |
| | 20 | R14 - I14 | 19 | R12 | |
| | 21 | R13 - I13 | 20 | -I9 | |
| | 22 | R12 - I12 | 21 | -I10 | |
| | 23 | R11 - I11 | 22 | -I11 | |
| | 24 | R10 - I10 | 23 | -I12 | |
| | 25 | R9 - I9 | 24 | R13 | |
| | 26 | R8 - I8 | 25 | R16 | |
| | 27 | R7 - I7 | 26 | R15 | |
| | 28 | R6 - I6 | 27 | R14 | |
| | 29 | R5 - I5 | 28 | -I13 | |
| | 30 | R4 - I4 | 29 | -I16 | |
| | 31 | R3 - I3 | 30 | -I15 | |
| | 32 | R2 - I2 | 31 | -I14 | |
| +-------+-----------+-------+-------+ |
| ``` |