@@ -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