I am a very satisfied user of KISS FFT by Mark Borgerding. It has an integer transform, and it also has a real-only transform that leverages the Hermitian symmetry inherent in the transform of an exclusively real-valued input to reduce the number of computations required.
However, you will need to keep track of the data locations yourself. The interface is extremely simple and just takes a pointer to an internal data buffer, and input and output buffer addresses.
Assuming your inputs are real-valued, you could do something like:
//Must compile with -DFIXED_POINT=16 directive,
//to tell kiss_fft to do fixed-point transforms with short int data
#include "kiss_fft.h"
#include "kiss_fftr.h"
const size_t K = ...;
const size_t inSize = K/6; //6 based on your diagram above, adjust as needed
kiss_fft_scalar *inBuf = bigInputBuffer;
kiss_fft_cpx outBuf[1+inSize/2]; //Hermitian symmetry, so DC + N/2 complex outputs
//kiss_fft_cpx outBuf[inSize]; //if not using the real transform
size_t ctr = 0;
kiss_fftr_cfg fftCfg = kiss_fftr_alloc(inSize, false, NULL, NULL);
//kiss_fft_cfg fftCfg = kiss_fft_alloc(inSize, false, NULL, NULL); //if not using the real transform
do {
kiss_fftr(fftCfg, inBuf, outBuf); //kiss_fft(...) is not using the real transform
//do something with outBuf
++ctr;
if (ctr == 6) {
inBuf += K;
ctr = 0;
} else {
inBuf += K/6;
}
} while ((inBuf - bigInputBuffer) < bigBufSize);
Caveats:
- You need to recompile to change the data type. Use
FIXED_POINT=16
or FIXED_POINT=32
for short or int data, or don't set FIXED_POINT to do floating-point transforms.
FIXED_POINT
must have the same value in your source, kiss_fft.*
and kiss_fftr.*
. So either set it by hand in all files or (better) use -D
to pass it as a compiler directive e.g., clang -DFIXED_POINT=16 kiss_fft.c kiss_fftr.c main.c
- The real transform expects the input buffer size to be even.
- The transform expects the input buffer to have a size that is a product of 2,3,5. I don't remember if it works with other sizes, but even if it does it will be slow.