@@ -123,6 +123,44 @@ static uint8_t maxVol = 31; // (was 10) Reasonable value for constant v
123123static uint8_t binNum = 8 ; // Used to select the bin for FFT based beat detection (deprecated)
124124
125125#ifdef ARDUINO_ARCH_ESP32
126+ #if !defined(UM_AUDIOREACTIVE_USE_ESPDSP_FFT) && (defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32))
127+ #define UM_AUDIOREACTIVE_USE_ARDUINO_FFT // use ArduinoFFT library for FFT instead of ESP-IDF DSP library by default on ESP32 and S3
128+ #endif
129+
130+ #if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 4, 0)
131+ #define UM_AUDIOREACTIVE_USE_ARDUINO_FFT // DSP FFT library is not available in ESP-IDF < 4.4
132+ #endif
133+
134+ #ifdef UM_AUDIOREACTIVE_USE_ARDUINO_FFT
135+ #include < arduinoFFT.h> // ArduinoFFT library for FFT and window functions
136+ #else
137+ #include " dsps_fft2r.h" // ESP-IDF DSP library for FFT and window functions
138+ #ifdef FFT_PREFER_EXACT_PEAKS
139+ #include " dsps_wind_blackman_harris.h"
140+ #else
141+ #include " dsps_wind_flat_top.h"
142+ #endif
143+ #if defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32C3)
144+ #define UM_AUDIOREACTIVE_USE_INTEGER_FFT // always use integer FFT on ESP32-S2 and ESP32-C3
145+ #endif
146+ #endif
147+
148+ // These are the input and output vectors. Input vectors receive computed results from FFT.
149+ #if !defined(UM_AUDIOREACTIVE_USE_INTEGER_FFT)
150+ static float * valFFT = nullptr ;
151+ #else
152+ static int16_t * valFFT = nullptr ;
153+ #endif
154+ #ifdef UM_AUDIOREACTIVE_USE_ARDUINO_FFT
155+ static float * vImag = nullptr ; // imaginary part of FFT results
156+ #endif
157+
158+ // pre-computed window function
159+ #if !defined(UM_AUDIOREACTIVE_USE_INTEGER_FFT)
160+ __attribute__ ((aligned(16 ))) float* windowFFT;
161+ #else
162+ __attribute__ ((aligned(16 ))) int16_t* windowFFT;
163+ #endif
126164
127165// use audio source class (ESP32 specific)
128166#include " audio_source.h"
@@ -164,51 +202,12 @@ const float agcSampleSmooth[AGC_NUM_PRESETS] = { 1/12.f, 1/6.f, 1/16.f}; //
164202// AGC presets end
165203
166204static AudioSource *audioSource = nullptr ;
167- static bool useBandPassFilter = false ; // if true, enables a bandpass filter 80Hz-16Khz to remove noise . Applies before FFT.
168-
205+ static bool useBandPassFilter = false ; // if true, enables a hard cutoff bandpass filter . Applies after FFT.
206+ static bool useMicFilter = false ; // if true, enables a IIR bandpass filter 80Hz-20Khz to remove noise. Applies before FFT.
169207// //////////////////
170208// Begin FFT Code //
171209// //////////////////
172210
173- #if !defined(UM_AUDIOREACTIVE_USE_ESPDSP_FFT) && (defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32))
174- #define UM_AUDIOREACTIVE_USE_ARDUINO_FFT // use ArduinoFFT library for FFT instead of ESP-IDF DSP library by default on ESP32 and S3
175- #endif
176-
177- #if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 4, 0)
178- #define UM_AUDIOREACTIVE_USE_ARDUINO_FFT // DSP FFT library is not available in ESP-IDF < 4.4
179- #endif
180-
181- #ifdef UM_AUDIOREACTIVE_USE_ARDUINO_FFT
182- #include < arduinoFFT.h> // ArduinoFFT library for FFT and window functions
183- #else
184- #include " dsps_fft2r.h" // ESP-IDF DSP library for FFT and window functions
185- #ifdef FFT_PREFER_EXACT_PEAKS
186- #include " dsps_wind_blackman_harris.h"
187- #else
188- #include " dsps_wind_flat_top.h"
189- #endif
190- #if defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32C3)
191- #define UM_AUDIOREACTIVE_USE_INTEGER_FFT // always use integer FFT on ESP32-S2 and ESP32-C3
192- #endif
193- #endif
194-
195- // These are the input and output vectors. Input vectors receive computed results from FFT.
196- #if !defined(UM_AUDIOREACTIVE_USE_INTEGER_FFT)
197- static float * valFFT = nullptr ;
198- #else
199- static int16_t * valFFT = nullptr ;
200- #endif
201- #ifdef UM_AUDIOREACTIVE_USE_ARDUINO_FFT
202- static float * vImag = nullptr ; // imaginary part of FFT results
203- #endif
204-
205- // pre-computed window function
206- #if !defined(UM_AUDIOREACTIVE_USE_INTEGER_FFT)
207- __attribute__ ((aligned(16 ))) float* windowFFT;
208- #else
209- __attribute__ ((aligned(16 ))) int16_t* windowFFT;
210- #endif
211-
212211// some prototypes, to ensure consistent interfaces
213212static float fftAddAvg (int from, int to); // average of several FFT result bins
214213void FFTcode (void * parameter); // audio processing task: read samples, run FFT, fill GEQ channels from FFT results
@@ -382,8 +381,7 @@ void FFTcode(void * parameter)
382381
383382 // band pass filter - can reduce noise floor by a factor of 50 and avoid aliasing effects to base & high frequency bands
384383 // downside: frequencies below 100Hz will be ignored
385- if (useBandPassFilter) runMicFilter (samplesFFT, valFFT);
386-
384+ if (useMicFilter) runMicFilter (samplesFFT, valFFT);
387385 // find highest sample in the batch
388386 #if !defined(UM_AUDIOREACTIVE_USE_INTEGER_FFT)
389387 float maxSample = 0 .0f ; // max sample from FFT batch
@@ -1400,7 +1398,8 @@ class AudioReactive : public Usermod {
14001398 periph_module_reset (PERIPH_I2S0_MODULE); // not possible on -C3
14011399 #endif
14021400 delay (100 ); // Give that poor microphone some time to setup.
1403- useBandPassFilter = true ; // filter fixes aliasing to base & highest frequency bands and reduces noise floor (use for all mic inputs)
1401+ useBandPassFilter = false ; // filter cuts lowest and highest frequency bands from FFT result (use on very noisy mic inputs)
1402+ useMicFilter = true ; // filter fixes aliasing to base & highest frequency bands and reduces noise floor (recommended for all mic inputs)
14041403
14051404 #if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
14061405 if ((i2sckPin == I2S_PIN_NO_CHANGE) && (i2ssdPin >= 0 ) && (i2swsPin >= 0 ) && ((dmType == 1 ) || (dmType == 4 )) ) dmType = 5 ; // dummy user support: SCK == -1 --means--> PDM microphone
@@ -1435,21 +1434,23 @@ class AudioReactive : public Usermod {
14351434 case 4 :
14361435 DEBUGSR_PRINT (F (" AR: Generic I2S Microphone with Master Clock - " )); DEBUGSR_PRINTLN (F (I2S_MIC_CHANNEL_TEXT));
14371436 audioSource = new I2SSource (SAMPLE_RATE, BLOCK_SIZE, 1 .0f /24 .0f );
1437+ useMicFilter = false ; // I2S with Master Clock is mostly used for line-in, skip sample filtering
14381438 delay (100 );
14391439 if (audioSource) audioSource->initialize (i2swsPin, i2ssdPin, i2sckPin, mclkPin);
14401440 break ;
14411441 #if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
14421442 case 5 :
14431443 DEBUGSR_PRINT (F (" AR: I2S PDM Microphone - " )); DEBUGSR_PRINTLN (F (I2S_PDM_MIC_CHANNEL_TEXT));
14441444 audioSource = new I2SSource (SAMPLE_RATE, BLOCK_SIZE, 1 .0f /4 .0f );
1445+ useBandPassFilter = true ; // this reduces the noise floor on SPM1423 from 5% Vpp (~380) down to 0.05% Vpp (~5)
14451446 delay (100 );
14461447 if (audioSource) audioSource->initialize (i2swsPin, i2ssdPin);
14471448 break ;
14481449 #endif
14491450 case 6 :
14501451 DEBUGSR_PRINTLN (F (" AR: ES8388 Source" ));
14511452 audioSource = new ES8388Source (SAMPLE_RATE, BLOCK_SIZE);
1452- useBandPassFilter = false ;
1453+ useMicFilter = false ;
14531454 delay (100 );
14541455 if (audioSource) audioSource->initialize (i2swsPin, i2ssdPin, i2sckPin, mclkPin);
14551456 break ;
0 commit comments