Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ ldscript_2m512k = eagle.flash.2m512.ld
ldscript_2m1m = eagle.flash.2m1m.ld
ldscript_4m1m = eagle.flash.4m1m.ld

default_usermods = audioreactive ;; audioreactive compiles, but crashes on classic esp32 (driver conflict related to legacy ADC)
default_usermods = audioreactive
;; default_usermods = wizlights animartrix ;; for testing
default_usermodsV4 = audioreactive ;; audioreactive is compatible with V4 builds

Expand Down Expand Up @@ -420,7 +420,7 @@ monitor_filters = esp32_exception_decoder
;; NOTE: ESP32-C5 requires pioarduino platform (Tasmota framework doesn't include C5 Arduino libs yet)
platform = https://github.com/pioarduino/platform-espressif32/releases/download/55.03.37/platform-espressif32.zip
platform_packages =
custom_usermods = ;; ${common.default_usermods} ;; ToDO: audiorective compiles, but not tested on C5 yet
custom_usermods = ${common.default_usermods} ;; ToDO: audiorective compiles, but not tested on C5 yet
build_unflags = ${esp32_idf_V5.build_unflags}
-D WLED_ENABLE_DMX_INPUT ;; esp_dmx library doesn't support C5 UART registers yet
build_flags = -g
Expand All @@ -447,7 +447,7 @@ platform_packages = ${esp32_idf_V5.platform_packages}
;;platform_packages =
;; framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#3.0.1
;; framework-arduinoespressif32-libs @ https://github.com/espressif/arduino-esp32/releases/download/3.0.1/esp32-arduino-libs-3.0.1.zip
custom_usermods = ;; ${common.default_usermods} ;; ToDO: audiorective compiles, but not tested on C6 yet
custom_usermods = ${common.default_usermods}

build_unflags = ${esp32_idf_V5.build_unflags}
-D WLED_ENABLE_DMX_INPUT ;; esp_dmx library doesn't support C6 UART registers yet
Expand Down Expand Up @@ -475,7 +475,7 @@ lib_ignore = ${esp32_idf_V5.lib_ignore}
;; Using latest tasmota framework - older frameworks only have minimal support for P4
platform = https://github.com/pioarduino/platform-espressif32/releases/download/55.03.37/platform-espressif32.zip
platform_packages =
custom_usermods = ;; ${common.default_usermods} ;; ToDO: audiorective compiles, but not tested on P4 yet
custom_usermods = ${common.default_usermods} ;; ToDO: audiorective compiles, but not tested on P4 yet
build_unflags = ${esp32_idf_V5.build_unflags}
-D WLED_ENABLE_DMX_INPUT ;; library not compatible with -P4
-D WLED_ENABLE_DMX ;; DMX serial out needs adaptations for P4 compatibility
Expand Down Expand Up @@ -764,7 +764,7 @@ board = esp32dev
platform = ${esp32_idf_V5.platform}
platform_packages = ${esp32_idf_V5.platform_packages}
build_unflags = ${esp32_idf_V5.build_unflags}
custom_usermods = ${common.default_usermods} ;; warning: audioreactive analog mic support had to be removed in V5 builds
custom_usermods = ${common.default_usermods}
build_flags = ${common.build_flags} ${esp32_idf_V5.build_flags} -D WLED_RELEASE_NAME=\"ESP32\" #-D WLED_DISABLE_BROWNOUT_DET
-DARDUINO_USB_CDC_ON_BOOT=0 ;; this flag is mandatory for "classic ESP32" when building with arduino-esp32 >=2.0.3
lib_deps = ${esp32_idf_V5.lib_deps}
Expand All @@ -778,7 +778,7 @@ extends = env:esp32dev
;;build_type = debug ;; disabled - leads to stack smashing in ArduinoJSON "Unhandled debug exception: Stack canary watchpoint triggered (loopTask)"
monitor_filters = esp32_exception_decoder
upload_speed = 921600
custom_usermods = ${common.default_usermods} ;; warning: audioreactive analog mic support had to be removed in V5 builds
custom_usermods = ${common.default_usermods}
build_unflags = ${esp32_idf_V5.build_unflags}
-D WLED_RELEASE_NAME=\"ESP32\"
;; -DCORE_DEBUG_LEVEL=0
Expand All @@ -797,7 +797,7 @@ lib_ignore = ${esp32_idf_V5.lib_ignore}
board = esp32dev
platform = ${esp32_idf_V5.platform}
platform_packages = ${esp32_idf_V5.platform_packages}
custom_usermods = ${common.default_usermods} ;; warning: audioreactive analog mic support had to be removed in V5 builds
custom_usermods = ${common.default_usermods}
build_unflags = ${esp32_idf_V5.build_unflags}
build_flags = ${common.build_flags} ${esp32_idf_V5.build_flags} -D WLED_RELEASE_NAME=\"ESP32_8M\" #-D WLED_DISABLE_BROWNOUT_DET
-DARDUINO_USB_CDC_ON_BOOT=0 ;; this flag is mandatory for "classic ESP32" when building with arduino-esp32 >=2.0.3
Expand All @@ -813,7 +813,7 @@ board_upload.maximum_size = 8388608
board = esp32dev
platform = ${esp32_idf_V5.platform}
platform_packages = ${esp32_idf_V5.platform_packages}
custom_usermods = ${common.default_usermods} ;; warning: audioreactive analog mic support had to be removed in V5 builds
custom_usermods = ${common.default_usermods}
build_unflags = ${esp32_idf_V5.build_unflags}
build_flags = ${common.build_flags} ${esp32_idf_V5.build_flags} -D WLED_RELEASE_NAME=\"ESP32_16M\" #-D WLED_DISABLE_BROWNOUT_DET
-DARDUINO_USB_CDC_ON_BOOT=0 ;; this flag is mandatory for "classic ESP32" when building with arduino-esp32 >=2.0.3
Expand Down Expand Up @@ -848,7 +848,7 @@ board = esp32-poe
platform = ${esp32_idf_V5.platform}
platform_packages = ${esp32_idf_V5.platform_packages}
upload_speed = 921600
custom_usermods = ${common.default_usermods} ;; warning: audioreactive analog mic support had to be removed in V5 builds
custom_usermods = ${common.default_usermods}
build_unflags = ${esp32_idf_V5.build_unflags}
build_flags = ${common.build_flags} ${esp32_idf_V5.build_flags} -D WLED_RELEASE_NAME=\"ESP32_Ethernet\" -D RLYPIN=-1 -D WLED_USE_ETHERNET -D BTNPIN=-1
-D SR_DMTYPE=-1 -D AUDIOPIN=-1 -D I2S_SDPIN=-1 -D I2S_WSPIN=-1 -D I2S_CKPIN=-1 -D MCLK_PIN=-1 ;; force AR to not allocate any PINs at startup
Expand All @@ -867,7 +867,7 @@ board = ttgo-t7-v14-mini32
board_build.f_flash = 80000000L
board_build.flash_mode = qio
board_build.partitions = ${esp32.extended_partitions}
custom_usermods = ${common.default_usermods} ;; warning: audioreactive analog mic support had to be removed in V5 builds
custom_usermods = ${common.default_usermods}
build_unflags = ${esp32_idf_V5.build_unflags}
build_flags = ${common.build_flags} ${esp32_idf_V5.build_flags} -D WLED_RELEASE_NAME=\"ESP32_WROVER\"
-DARDUINO_USB_CDC_ON_BOOT=0 ;; this flag is mandatory for "classic ESP32" when building with arduino-esp32 >=2.0.3
Expand Down
82 changes: 27 additions & 55 deletions usermods/audioreactive/audio_reactive.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,49 +3,16 @@

#ifdef ARDUINO_ARCH_ESP32

#include <driver/i2s.h>
#include <driver/adc.h>
#if ESP_IDF_VERSION_MAJOR >= 5
#include <driver/i2s_std.h> // new I2S driver - IDF v5.x and v6.x (legacy driver removed in IDF v6.0)
#else
#include <driver/i2s.h> // legacy I2S driver - IDF v4.x only
#if defined(CONFIG_IDF_TARGET_ESP32)
#include <driver/adc.h> // legacy ADC driver causes bootloops in V5
#endif
#endif

// AI: below section was generated by an AI
#if defined(CONFIG_IDF_TARGET_ESP32) && (ESP_IDF_VERSION_MAJOR >= 5)
/*
* Bootloop workaround for classic ESP32 on esp-idf 5.x (WLED V5):
* AR still uses the legacy I2S driver (driver/i2s.h) which pulls in the legacy ADC driver.
* This causes a "abort" on boot as IDF V5 does not allow the legacy ADC driver to be used
* if any other function (i.e. Arduino's analogRead()) pulls in the new driver.
*
* The no-op stubs below satisfy exactly the symbols i2s_legacy.c.obj needs, so the real
* adc_i2s_deprecated.c.obj / adc_legacy.c.obj are never linked. This is safe because on IDF >= 5
* the analog built-in-ADC mic class (I2SAdcSource) is compiled out anyway (see audio_source.h),
* so these paths are never executed; digital I2S/PDM mics don't use them.
* Delete this block once the usermod is ported to the new I2S driver (driver/i2s_std.h).
*/
#include <esp_err.h>

// Stub: would configure the (removed) I2S built-in ADC mode. Never called for digital mics.
extern "C" esp_err_t adc_i2s_mode_init(int adcUnit, int channel) {
(void)adcUnit; (void)channel;
return ESP_ERR_NOT_SUPPORTED;
}

// Stub: would select the ADC data source for I2S DMA. Never called for digital mics.
extern "C" esp_err_t adc_set_i2s_data_source(int source) {
(void)source;
return ESP_ERR_NOT_SUPPORTED;
}

// Stub: would acquire ADC1 for DMA (built-in ADC mode only). Report failure if ever called.
extern "C" esp_err_t adc1_dma_mode_acquire(void) {
return ESP_ERR_NOT_SUPPORTED;
}

// Stub: would release the legacy ADC1 lock. No lock is ever taken, so nothing to do.
extern "C" esp_err_t adc1_lock_release(void) {
return ESP_OK;
}
#endif
// AI: end

#if defined(ARDUINO_ARCH_ESP32) && (defined(WLED_DEBUG) || defined(SR_DEBUG))
#include <esp_timer.h>
Expand Down Expand Up @@ -76,7 +43,7 @@ extern "C" esp_err_t adc1_lock_release(void) {
*/

//#define UM_AUDIOREACTIVE_USE_ESPDSP_FFT // default on S2 and C3
//#define UM_AUDIOREACTIVE_USE_INTEGER_FFT // use integer FFT if using ESP-IDF DSP library, always used on S2 and C3 (UM_AUDIOREACTIVE_USE_ARDUINO_FFT takes priority)
//#define UM_AUDIOREACTIVE_USE_INTEGER_FFT // use integer FFT if using ESP-IDF DSP library, always used on chips with no FPU (UM_AUDIOREACTIVE_USE_ARDUINO_FFT takes priority)
//#define UM_AUDIOREACTIVE_USE_ARDUINO_FFT // default on ESP32 and S3

#if !defined(FFTTASK_PRIORITY)
Expand Down Expand Up @@ -176,8 +143,8 @@ static uint8_t binNum = 8; // Used to select the bin for FFT based bea
#else
#include "dsps_wind_flat_top.h"
#endif
#if defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32C3)
#define UM_AUDIOREACTIVE_USE_INTEGER_FFT // always use integer FFT on ESP32-S2 and ESP32-C3
#if !SOC_CPU_HAS_FPU
#define UM_AUDIOREACTIVE_USE_INTEGER_FFT // always use integer FFT on MCU's with no hardware float unit
#endif
#endif // UM_AUDIOREACTIVE_USE_ARDUINO_FFT

Expand All @@ -201,7 +168,6 @@ static FFTsampleType* windowFFT = nullptr;

// use audio source class (ESP32 specific)
#include "audio_source.h"
constexpr i2s_port_t I2S_PORT = I2S_NUM_0; // I2S port to use (do not change !)
constexpr int BLOCK_SIZE = 128; // I2S buffer size (samples)

// globals
Expand Down Expand Up @@ -915,7 +881,7 @@ class AudioReactive : public Usermod {
static const char _dynamics[];
static const char _frequency[];
static const char _inputLvl[];
#if defined(CONFIG_IDF_TARGET_ESP32) && (ESP_IDF_VERSION_MAJOR < 5) // legacy ADC driver is not available any more in esp-idf V5.x.y
#if defined(AR_ANALOG_MIC_SUPPORTED) // analog mic: legacy ADC-over-I2S on IDF v4, ADC continuous driver on IDF v5/v6
static const char _analogmic[];
#endif
static const char _digitalmic[];
Expand Down Expand Up @@ -1414,12 +1380,14 @@ class AudioReactive : public Usermod {

#ifdef ARDUINO_ARCH_ESP32

// Reset I2S peripheral for good measure
#if ESP_IDF_VERSION_MAJOR < 5
// Reset I2S peripheral for good measure (legacy driver only - the new driver cleans up after itself)
i2s_driver_uninstall(I2S_NUM_0); // E (696) I2S: i2s_driver_uninstall(2006): I2S port 0 has not installed
#if !defined(CONFIG_IDF_TARGET_ESP32C3) && (ESP_IDF_VERSION_MAJOR < 5)
#if !defined(CONFIG_IDF_TARGET_ESP32C3)
delay(100);
periph_module_reset(PERIPH_I2S0_MODULE); // not possible on -C3, neither on esp-idf V5
#endif
#endif
delay(100); // Give that poor microphone some time to setup.
useBandPassFilter = false; // filter cuts lowest and highest frequency bands from FFT result (use on very noisy mic inputs)
useMicFilter = true; // filter fixes aliasing to base & highest frequency bands and reduces noise floor (recommended for all mic inputs)
Expand All @@ -1430,7 +1398,7 @@ class AudioReactive : public Usermod {

switch (dmType) {
// stub cases for not-yet-supported I2S modes on other ESP32 chips
#if !defined(CONFIG_IDF_TARGET_ESP32) || (ESP_IDF_VERSION_MAJOR > 4) // legacy ADC driver is not available any more in esp-idf V5.x.y
#if !defined(AR_ANALOG_MIC_SUPPORTED) // no analog mic support on this MCU / IDF version
case 0: //ADC analog
#endif
#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S3) // PDM is only supported on S3 and classic esp32
Expand Down Expand Up @@ -1478,11 +1446,15 @@ class AudioReactive : public Usermod {
if (audioSource) audioSource->initialize(i2swsPin, i2ssdPin, i2sckPin, mclkPin);
break;

#if defined(CONFIG_IDF_TARGET_ESP32) && (ESP_IDF_VERSION_MAJOR < 5) // legacy ADC driver is not available any more in esp-idf V5.x.y
// ADC over I2S is only possible on "classic" ESP32
#if defined(AR_ANALOG_MIC_SUPPORTED)
// analog microphone input - ADC over I2S on IDF v4 (classic ESP32), ADC continuous driver on IDF v5/v6
case 0:
DEBUGSR_PRINTLN(F("AR: Analog Microphone (left channel only)."));
#if defined(AR_ANALOG_MIC_I2S_ADC)
audioSource = new I2SAdcSource(SAMPLE_RATE, BLOCK_SIZE);
#else
audioSource = new AdcContinuousSource(SAMPLE_RATE, BLOCK_SIZE);
#endif
delay(100);
useBandPassFilter = true; // PDM bandpass filter seems to help for bad quality analog
if (audioSource) audioSource->initialize(audioPin);
Expand Down Expand Up @@ -2057,7 +2029,7 @@ class AudioReactive : public Usermod {
top[FPSTR(_addPalettes)] = addPalettes;

#ifdef ARDUINO_ARCH_ESP32
#if defined(CONFIG_IDF_TARGET_ESP32) && (ESP_IDF_VERSION_MAJOR < 5) // legacy ADC driver is not available any more in esp-idf V5.x.y
#if defined(AR_ANALOG_MIC_SUPPORTED) // analog mic: legacy ADC-over-I2S on IDF v4, ADC continuous driver on IDF v5/v6
JsonObject amic = top.createNestedObject(FPSTR(_analogmic));
amic["pin"] = audioPin;
#endif
Expand Down Expand Up @@ -2123,14 +2095,14 @@ class AudioReactive : public Usermod {
configComplete &= getJsonValue(top[FPSTR(_addPalettes)], addPalettes);

#ifdef ARDUINO_ARCH_ESP32
#if defined(CONFIG_IDF_TARGET_ESP32) && (ESP_IDF_VERSION_MAJOR < 5) // legacy ADC driver is not available any more in esp-idf V5.x.y
#if defined(AR_ANALOG_MIC_SUPPORTED) // analog mic: legacy ADC-over-I2S on IDF v4, ADC continuous driver on IDF v5/v6
configComplete &= getJsonValue(top[FPSTR(_analogmic)]["pin"], audioPin);
#else
audioPin = -1; // MCU does not support analog mic
#endif

configComplete &= getJsonValue(top[FPSTR(_digitalmic)]["type"], dmType);
#if !defined(CONFIG_IDF_TARGET_ESP32) || (ESP_IDF_VERSION_MAJOR > 4) // legacy ADC driver is not available any more in esp-idf V5.x.y
#if !defined(AR_ANALOG_MIC_SUPPORTED) // no analog mic support on this MCU / IDF version
if (dmType == 0) dmType = SR_DMTYPE; // MCU does not support analog
#endif
#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S3) // PDM is only supported on S3 and classic esp32
Expand Down Expand Up @@ -2179,7 +2151,7 @@ class AudioReactive : public Usermod {
#ifdef ARDUINO_ARCH_ESP32
uiScript.print(F("uxp=ux+':digitalmic:pin[]';")); // uxp = shortcut for AudioReactive:digitalmic:pin[]
uiScript.print(F("dd=addDropdown(ux,'digitalmic:type');"));
#if defined(CONFIG_IDF_TARGET_ESP32) && (ESP_IDF_VERSION_MAJOR < 5) // legacy ADC driver is not available any more in esp-idf V5.x.y
#if defined(AR_ANALOG_MIC_SUPPORTED) // analog mic: legacy ADC-over-I2S on IDF v4, ADC continuous driver on IDF v5/v6
uiScript.print(F("addOption(dd,'Generic Analog',0);"));
#endif
uiScript.print(F("addOption(dd,'Generic I2S',1);"));
Expand Down Expand Up @@ -2346,7 +2318,7 @@ const char AudioReactive::_config[] PROGMEM = "config";
const char AudioReactive::_dynamics[] PROGMEM = "dynamics";
const char AudioReactive::_frequency[] PROGMEM = "frequency";
const char AudioReactive::_inputLvl[] PROGMEM = "inputLevel";
#if defined(CONFIG_IDF_TARGET_ESP32) && (ESP_IDF_VERSION_MAJOR < 5) // legacy ADC driver is not available any more in esp-idf V5.x.y
#if defined(AR_ANALOG_MIC_SUPPORTED) // analog mic: legacy ADC-over-I2S on IDF v4, ADC continuous driver on IDF v5/v6
const char AudioReactive::_analogmic[] PROGMEM = "analogmic";
#endif
const char AudioReactive::_digitalmic[] PROGMEM = "digitalmic";
Expand Down
Loading
Loading