Carsten
Although I have been using a different FFT library for product developments requiring more capabilities I have integrated the complex FFT in the uTasker project so that it can be used simply on (in-place) circular buffers (which is what tends to be needed in real-time applications).
There is a document at:
https://www.utasker.com/docs/uTasker/uTasker_DSP.pdf
And a video showing it in operation at:
https://www.youtube.com/watch?v=n-GABeILGV8&feature=youtu.be
This is the actual code for the calculation (after each part of the USB audio buffer has been filled by the received waveform) of the video reference on a K22F:
static void fnPerformFFT(int iBufferReference)
{
int iInputSample;
int iOutputSample = 0;
int iInputOffset = 0;
int iCopyLength = FFT_INPUT_SAMPLES;
float fft_magnitude_buffer[(FFT_INPUT_SAMPLES/2)]; // temporary fft frequency amplitude output
signed short sRawInput[FFT_INPUT_SAMPLES]; // temporary linear input buffer with original waveform
switch (iBufferReference) {
case EVENT_FFT_HALF_PONG:
iInputOffset = (FFT_INPUT_SAMPLES/2);
iInputSample = (FFT_INPUT_SAMPLES/4);
break;
case EVENT_FFT_PONG:
iInputOffset = (FFT_INPUT_SAMPLES);
iInputSample = (FFT_INPUT_SAMPLES/2);
break;
case EVENT_FFT_HALF_PING:
iInputOffset = (2 *(3 * FFT_INPUT_SAMPLES/4));
uMemcpy(&sRawInput[0], &fft_buffer[(3 * FFT_INPUT_SAMPLES / 4)], ((FFT_INPUT_SAMPLES / 2) * sizeof(signed short))); // handle the circular buffer wrap around in this case
iOutputSample = (FFT_INPUT_SAMPLES / 2);
iCopyLength = (FFT_INPUT_SAMPLES / 2);
// Fall-through intentionally
//
case EVENT_FFT_PING:
default:
iInputSample = 0;
break;
}
uMemcpy(&sRawInput[iOutputSample], &fft_buffer[iInputSample], (iCopyLength * sizeof(signed short)));
fnFFT((void *)fft_buffer, (void *)fft_magnitude_buffer, FFT_INPUT_SAMPLES, iInputOffset, (FFT_INPUT_SAMPLES * sizeof(signed short)), windowing_buffer, window_conversionFactor, (FFT_INPUT_HALF_WORDS_SIGNED | FFT_OUTPUT_FLOATS | FFT_MAGNITUDE_RESULT)); // perform complex fast-fourier transform (the result is in the input buffer)
#if defined BLAZE_K22
fnDisplayFFT(fft_magnitude_buffer, sRawInput); // display FFT output on display
#endif
}
The magnitude compensation is included in the Windowing step, whereby a Blackmann Harris window is (typically) used.
window_conversionFactor = fnGenerateWindowFloat(windowing_buffer, FFT_INPUT_SAMPLES, BLACKMANN_HARRIS_WINDOW);
This means that all of the dirty work is handled in fnFFT() so that it can be used simply.
The CMSIS coefficients code has been optimised in the uTasker project to make the sure that no unnecessary tables are in the code, otherwise these can unnecessarily use up code space. The range of samples is from 16, 32, 64,... 4k although recently the CMSIS developers showed (after being asked repeated during two years) how to extend to 8k, although they won't include it in the public version:
https://github.com/ARM-software/CMSIS_5/issues/393#issuecomment-546250633
I may add it at at some point.
As well as a few FFT references in the project (and the ability to simulate all operation and inject simulated sine waves) I also have included the CMSIS FFT test reference in order to check that the reference waveform detects the correct frequency and amplitude.
I have attached the DSP.c file and command line menu interface containing the FFT test code "fft" (debug.c) - search for fnTestFFT() so that you should be able to see all details.
uTasker project users select the CMSIS FFT support and configure which sample lengths are needed by the defines:
//#define CMSIS_DSP_CFFT // enable FFT support - details at http://www.utasker.com/docs/uTasker/uTasker_DSP.pdf
#define CMSIS_DSP_CFFT_FLOAT
//#define CMSIS_DSP_CFFT_Q15
//#define CMSIS_DSP_FFT_16 // enable 16 point FFT
//#define CMSIS_DSP_FFT_32 // enable 32 point FFT
//#define CMSIS_DSP_FFT_64 // enable 64 point FFT
//#define CMSIS_DSP_FFT_128 // enable 128 point FFT
//#define CMSIS_DSP_FFT_256 // enable 256 point FFT
//#define CMSIS_DSP_FFT_512 // enable 512 point FFT
//#define CMSIS_DSP_FFT_1024 // enable 1024 point FFT
#define CMSIS_DSP_FFT_2048 // enable 2048 point FFT
#define CMSIS_DSP_FFT_4096 // enable 4096 point FFT
#define CMSIS_DSP_FFT_8192 // enable 8192 point FFT
Regards
Mark
[uTasker project developer for Kinetis and i.MX RT]