11/*
2- * FFT_Overrlapped_F32
3- *
2+ * FFT_Overrlapped_OA_F32
3+ *
44 * Purpose: Encapsulate the ARM floating point FFT/IFFT functions
55 * in a way that naturally interfaces to my float32
66 * extension of the Teensy Audio Library.
7- *
7+ *
88 * Provides functionality to do overlapped FFT/IFFT where
99 * each audio block is a fraction (1, 1/2, 1/4) of the
1010 * totaly FFT length. This class handles all of the
1111 * data shuffling to composite the previous data blocks
1212 * with the current data block to provide the full FFT.
1313 * Does similar data shuffling (overlapp-add) for IFFT.
14- *
14+ *
1515 * Created: Chip Audette (openaudio.blogspot.com)
16- * Jan-Jul 2017
17- *
16+ * Jan-Jul 2017
17+ *
1818 * Typical Usage as FFT:
19- *
2019 * //setup the audio stuff
2120 * float sample_rate_Hz = 44100.0; //define sample rate
2221 * int audio_block_samples = 32; //define size of audio blocks
2322 * AudioSettings_F32 audio_settings(sample_rate_Hz, audio_block_samples);
2423 * // ... continue creating all of your Audio Processing Blocks ...
25- *
24+ *
2625 * // within a custom audio processing algorithm that you've written
2726 * // you'd create the FFT and IFFT elements
2827 * int NFFT = 128; //define length of FFT that you want (multiple of audio_block_samples)
2928 * FFT_Overrlapped_F32 FFT_obj(audio_settings,NFFT); //Creare FFT object
3029 * FFT_Overrlapped_F32 IFFT_obj(audio_settings,NFFT); //Creare IFFT object
3130 * float complex_2N_buffer[2*NFFT]; //create buffer to hold the FFT output
32- *
31+ *
3332 * // within your own algorithm's "update()" function (which is what
34- * // is called automatically by the Teensy Audio Libarary approach
33+ * // is called automatically by the Teensy Audio Libarary approach
3534 * // to audio processing), you can execute the FFT and IFFT
36- *
35+ *
3736 * // First, get the audio and convert to frequency-domain using an FFT
3837 * audio_block_f32_t *in_audio_block = AudioStream_F32::receiveReadOnly_f32();
3938 * FFT_obj.execute(in_audio_block, complex_2N_buffer); //output is in complex_2N_buffer
4039 * AudioStream_F32::release(in_audio_block); //We just passed ownership to FFT_obj, so release it here.
41- *
40+ *
4241 * // Next do whatever processing you'd like on the frequency domain data
4342 * // that is held in complex_2N_buffer
44- *
43+ *
4544 * // Finally, you can convert back to the time domain via IFFT
46- * audio_block_f32_t *out_audio_block = IFFT_obj.execute(complex_2N_buffer);
45+ * audio_block_f32_t *out_audio_block = IFFT_obj.execute(complex_2N_buffer);
4746 * //note that the "out_audio_block" is mananged by IFFT_obj, so don't worry about releasing it.
48- *
47+ *
48+ *
49+ * https://forum.pjrc.com/threads/53668-fft-ifft?highlight=IFFT willie.from.texas 9-10-2018
50+ * I've been using the CMSIS Version 5.3.0 DSP Library since May 2018 (see github.com/ARM-software/CMSIS_5).
51+ * I might be the only person on this forum using it. The library allows me to use the 32-bit floating point
52+ * capability of the Teensy 3.6. I have been able to use it in real-time with 16-bit sample rates
53+ * out of both ADCs up to around 450 kHz (i-q data). I'm very happy with the performance I am obtaining.
54+ * Here is the FFT/IFFT performance I am getting with the library:
55+ * # Points Forward rfft Inverse rfft Forward cfft Inverse cfft
56+ * 512 201 us 247 us 239 us 294 us
57+ * 1024 362 us 454 us 588 us 714 us
58+ * 2048 846 us 1066 us 1376 us 1620 us
59+ * 4096 1860 us 2304 us 2504 us 2990 us
60+ *
61+ *
4962 * License: MIT License
5063 */
51- #ifndef _FFT_Overlapped_F32_h
52- #define _FFT_Overlapped_F32_h
64+ #ifndef _FFT_Overlapped_OA_F32_h
65+ #define _FFT_Overlapped_OA_F32_h
5366
5467#include " AudioStream_F32.h"
5568#include < arm_math.h>
56- #include " FFT_F32 .h"
69+ #include " FFT_OA_F32 .h"
5770// #include "utility/dspinst.h" //copied from analyze_fft256.cpp. Do we need this?
5871
5972// set the max amount of allowed overlap...some number larger than you'll want to use
6073#define MAX_N_BUFF_BLOCKS 32 // 32 blocks x 16 sample blocks enables NFFT = 512, if the Teensy could keep up.
6174
62- class FFT_Overlapped_Base_F32 { // handles all the data structures for the overlapping stuff. Doesn't care if FFT or IFFT
75+ class FFT_Overlapped_Base_OA_F32 { // handles all the data structures for the overlapping stuff. Doesn't care if FFT or IFFT
6376 public:
64- FFT_Overlapped_Base_F32 (void ) {};
65- ~FFT_Overlapped_Base_F32 (void ) {
77+ FFT_Overlapped_Base_OA_F32 (void ) {};
78+ ~FFT_Overlapped_Base_OA_F32 (void ) {
6679 if (N_BUFF_BLOCKS > 0 ) {
6780 for (int i = 0 ; i < N_BUFF_BLOCKS; i++) {
6881 if (buff_blocks[i] != NULL ) AudioStream_F32::release (buff_blocks[i]);
@@ -73,16 +86,16 @@ class FFT_Overlapped_Base_F32 { //handles all the data structures for the overl
7386
7487 virtual int setup (const AudioSettings_F32 &settings, const int _N_FFT) {
7588 int N_FFT;
76-
89+
7790 // /choose valid _N_FFT
7891 if (!FFT_F32::is_valid_N_FFT (_N_FFT)) {
7992 Serial.println (F (" FFT_Overlapped_Base_F32: *** ERROR ***" ));
80- Serial.print (F (" : N_FFT " )); Serial.print (_N_FFT);
93+ Serial.print (F (" : N_FFT " )); Serial.print (_N_FFT);
8194 Serial.print (F (" is not allowed. Try a power of 2 between 16 and 2048" ));
8295 N_FFT = -1 ;
8396 return N_FFT;
8497 }
85-
98+
8699 // how many buffers will compose each FFT?
87100 audio_block_samples = settings.audio_block_samples ;
88101 N_BUFF_BLOCKS = _N_FFT / audio_block_samples; // truncates!
@@ -93,13 +106,13 @@ class FFT_Overlapped_Base_F32 { //handles all the data structures for the overl
93106
94107 // allocate memory for buffers...this is dynamic allocation. Always dangerous.
95108 complex_buffer = new float32_t [2 *N_FFT]; // should I check to see if it was successfully allcoated?
96-
109+
97110 // initialize the blocks for holding the previous data
98111 for (int i = 0 ; i < N_BUFF_BLOCKS; i++) {
99112 buff_blocks[i] = AudioStream_F32::allocate_f32 ();
100113 clear_audio_block (buff_blocks[i]);
101114 }
102-
115+
103116 return N_FFT;
104117 }
105118 virtual int getNFFT (void ) = 0;
@@ -108,70 +121,65 @@ class FFT_Overlapped_Base_F32 { //handles all the data structures for the overl
108121 protected:
109122 int N_BUFF_BLOCKS = 0 ;
110123 int audio_block_samples;
111-
124+
112125 audio_block_f32_t *buff_blocks[MAX_N_BUFF_BLOCKS];
113126 float32_t *complex_buffer;
114127
115128 void clear_audio_block (audio_block_f32_t *block) {
116129 for (int i = 0 ; i < block->length ; i++) block->data [i] = 0 .f ;
117- }
130+ }
118131};
119132
120- class FFT_Overlapped_F32 : public FFT_Overlapped_Base_F32
133+ class FFT_Overlapped_OA_F32 : public FFT_Overlapped_Base_F32
121134{
122135 public:
123136 // constructors
124- FFT_Overlapped_F32 (void ): FFT_Overlapped_Base_F32() {};
125- FFT_Overlapped_F32 (const AudioSettings_F32 &settings): FFT_Overlapped_Base_F32() { }
126- FFT_Overlapped_F32 (const AudioSettings_F32 &settings, const int _N_FFT): FFT_Overlapped_Base_F32() {
137+ FFT_Overlapped_OA_F32 (void ): FFT_Overlapped_Base_F32() {};
138+ FFT_Overlapped_OA_F32 (const AudioSettings_F32 &settings): FFT_Overlapped_Base_F32() { }
139+ FFT_Overlapped_OA_F32 (const AudioSettings_F32 &settings, const int _N_FFT): FFT_Overlapped_Base_F32() {
127140 setup (settings,_N_FFT);
128141 }
129-
142+
130143 virtual int setup (const AudioSettings_F32 &settings, const int _N_FFT) {
131144 int N_FFT = FFT_Overlapped_Base_F32::setup (settings, _N_FFT);
132-
145+
133146 // setup the FFT routines
134- N_FFT = myFFT.setup (N_FFT);
147+ N_FFT = myFFT.setup (N_FFT);
135148 return N_FFT;
136149 }
137-
150+
138151 virtual void execute (audio_block_f32_t *block, float *complex_2N_buffer);
139152 virtual int getNFFT (void ) { return myFFT.getNFFT (); };
140153 FFT_F32* getFFTObject (void ) { return &myFFT; };
141154 virtual void rebuildNegativeFrequencySpace (float *complex_2N_buffer) { myFFT.rebuildNegativeFrequencySpace (complex_2N_buffer); }
142-
155+
143156 private:
144157 FFT_F32 myFFT;
145158};
146159
147-
148- class IFFT_Overlapped_F32 : public FFT_Overlapped_Base_F32
160+ class IFFT_Overlapped_OA_F32 : public FFT_Overlapped_Base_F32
149161{
150162 public:
151163 // constructors
152- IFFT_Overlapped_F32 (void ): FFT_Overlapped_Base_F32() {};
153- IFFT_Overlapped_F32 (const AudioSettings_F32 &settings): FFT_Overlapped_Base_F32() { }
154- IFFT_Overlapped_F32 (const AudioSettings_F32 &settings, const int _N_FFT): FFT_Overlapped_Base_F32() {
164+ IFFT_Overlapped_OA_F32 (void ): FFT_Overlapped_Base_F32() {};
165+ IFFT_Overlapped_OA_F32 (const AudioSettings_F32 &settings): FFT_Overlapped_Base_F32() { }
166+ IFFT_Overlapped_OA_F32 (const AudioSettings_F32 &settings, const int _N_FFT): FFT_Overlapped_Base_F32() {
155167 setup (settings,_N_FFT);
156168 }
157-
169+
158170 virtual int setup (const AudioSettings_F32 &settings, const int _N_FFT) {
159171 int N_FFT = FFT_Overlapped_Base_F32::setup (settings, _N_FFT);
160-
172+
161173 // setup the FFT routines
162- N_FFT = myIFFT.setup (N_FFT);
174+ N_FFT = myIFFT.setup (N_FFT);
163175 return N_FFT;
164176 }
165-
177+
166178 virtual audio_block_f32_t * execute (float *complex_2N_buffer);
167179 virtual int getNFFT (void ) { return myIFFT.getNFFT (); };
168180 IFFT_F32* getFFTObject (void ) { return &myIFFT; };
169181 IFFT_F32* getIFFTObject (void ) { return &myIFFT; };
170182 private:
171183 IFFT_F32 myIFFT;
172184};
173-
174-
175-
176-
177185#endif
0 commit comments