Skip to content

Commit cc68e6b

Browse files
committed
Squashed commit of the following:
Remove sync receive Disallow 2D effects on non-2D segments Optimisations Sync clarification AR palettes Return of 2 audio simulations Bugfix in sync wled#3344 - remove excessive segments - ignore inactive segments if not syncing bounds - send UDP/WS on segment change - pop_back() when removing last segment Add pairing support for ESP-NOW sync Reduce string RAM footprint UDP parse optimisation Make WizMote work with sync. ESP-NOW wireless sync POC. - caveat: devices have to be on the same channel - clashes with WizMote handling ATM
1 parent 60c47cf commit cc68e6b

35 files changed

+6185
-5863
lines changed

.vscode/tasks.json

+3-3
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,16 @@
99
],
1010
"dependsOrder": "sequence",
1111
"problemMatcher": [
12-
"$platformio",
13-
],
12+
"$platformio"
13+
]
1414
},
1515
{
1616
"type": "PlatformIO",
1717
"label": "Build: binary only",
1818
"task": "Build",
1919
"group": {
2020
"kind": "build",
21-
"isDefault": true,
21+
"isDefault": true
2222
},
2323
"problemMatcher": [
2424
"$platformio"

platformio.ini

+3
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,9 @@ lib_deps =
181181
IRremoteESP8266 @ 2.8.2
182182
makuna/NeoPixelBus @ 2.7.5
183183
https://github.com/Aircoookie/ESPAsyncWebServer.git @ ~2.0.7
184+
# ESP-NOW library (includes mandatory QuickDebug library)
185+
; gmag11/QuickESPNow @ 0.6.2
186+
https://github.com/blazoncek/QuickESPNow.git#optional-debug
184187
#For use of the TTGO T-Display ESP32 Module with integrated TFT display uncomment the following line
185188
#TFT_eSPI
186189
#For compatible OLED display uncomment following

usermods/audioreactive/audio_reactive.h

+104
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@
5151
#define PLOT_PRINTF(x...)
5252
#endif
5353

54+
#define MAX_PALETTES 3
55+
5456
// use audio source class (ESP32 specific)
5557
#include "audio_source.h"
5658
constexpr i2s_port_t I2S_PORT = I2S_NUM_0; // I2S port to use (do not change !)
@@ -614,6 +616,8 @@ class AudioReactive : public Usermod {
614616
// set your config variables to their boot default value (this can also be done in readFromConfig() or a constructor if you prefer)
615617
bool enabled = false;
616618
bool initDone = false;
619+
bool addPalettes = false;
620+
CRGBPalette16 *palette[MAX_PALETTES];
617621

618622
// variables for UDP sound sync
619623
WiFiUDP fftUdp; // UDP object for sound sync (from WiFi UDP, not Async UDP!)
@@ -652,10 +656,15 @@ class AudioReactive : public Usermod {
652656
static const char _inputLvl[];
653657
static const char _analogmic[];
654658
static const char _digitalmic[];
659+
static const char _addPalettes[];
655660
static const char UDP_SYNC_HEADER[];
656661
static const char UDP_SYNC_HEADER_v1[];
657662

658663
// private methods
664+
void removeAudioPalettes(void);
665+
void createAudioPalettes(void);
666+
CRGB getCRGBForBand(int x, int pal);
667+
void fillAudioPalette(int pal);
659668

660669
////////////////////
661670
// Debug support //
@@ -1196,6 +1205,7 @@ class AudioReactive : public Usermod {
11961205
}
11971206

11981207
if (enabled) connectUDPSoundSync();
1208+
if (enabled && addPalettes) createAudioPalettes();
11991209
initDone = true;
12001210
}
12011211

@@ -1358,6 +1368,7 @@ class AudioReactive : public Usermod {
13581368
lastTime = millis();
13591369
}
13601370

1371+
for (int i=0; i<MAX_PALETTES; i++) fillAudioPalette(i);
13611372
}
13621373

13631374

@@ -1610,6 +1621,11 @@ class AudioReactive : public Usermod {
16101621
if (usermod[FPSTR(_enabled)].is<bool>()) {
16111622
enabled = usermod[FPSTR(_enabled)].as<bool>();
16121623
if (prevEnabled != enabled) onUpdateBegin(!enabled);
1624+
if (addPalettes) {
1625+
// add/remove custom/audioreactive palettes
1626+
if (prevEnabled && !enabled) removeAudioPalettes();
1627+
if (!prevEnabled && enabled) createAudioPalettes();
1628+
}
16131629
}
16141630
if (usermod[FPSTR(_inputLvl)].is<int>()) {
16151631
inputLevel = min(255,max(0,usermod[FPSTR(_inputLvl)].as<int>()));
@@ -1657,6 +1673,7 @@ class AudioReactive : public Usermod {
16571673
{
16581674
JsonObject top = root.createNestedObject(FPSTR(_name));
16591675
top[FPSTR(_enabled)] = enabled;
1676+
top[FPSTR(_addPalettes)] = addPalettes;
16601677

16611678
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3)
16621679
JsonObject amic = top.createNestedObject(FPSTR(_analogmic));
@@ -1709,8 +1726,11 @@ class AudioReactive : public Usermod {
17091726
{
17101727
JsonObject top = root[FPSTR(_name)];
17111728
bool configComplete = !top.isNull();
1729+
bool oldEnabled = enabled;
1730+
bool oldAddPalettes = addPalettes;
17121731

17131732
configComplete &= getJsonValue(top[FPSTR(_enabled)], enabled);
1733+
configComplete &= getJsonValue(top[FPSTR(_addPalettes)], addPalettes);
17141734

17151735
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3)
17161736
configComplete &= getJsonValue(top[FPSTR(_analogmic)]["pin"], audioPin);
@@ -1744,6 +1764,11 @@ class AudioReactive : public Usermod {
17441764
configComplete &= getJsonValue(top["sync"][F("port")], audioSyncPort);
17451765
configComplete &= getJsonValue(top["sync"][F("mode")], audioSyncEnabled);
17461766

1767+
if (initDone) {
1768+
// add/remove custom/audioreactive palettes
1769+
if ((oldAddPalettes && !addPalettes) || (oldAddPalettes && !enabled)) removeAudioPalettes();
1770+
if ((addPalettes && !oldAddPalettes && enabled) || (addPalettes && !oldEnabled && enabled)) createAudioPalettes();
1771+
} // else setup() will create palettes
17471772
return configComplete;
17481773
}
17491774

@@ -1819,6 +1844,84 @@ class AudioReactive : public Usermod {
18191844
}
18201845
};
18211846

1847+
void AudioReactive::removeAudioPalettes(void) {
1848+
for (int i=MAX_PALETTES-1; i>=0; i--) {
1849+
if (palette[i]) strip.customPalettes.pop_back();
1850+
palette[i] = nullptr;
1851+
}
1852+
}
1853+
1854+
void AudioReactive::createAudioPalettes(void) {
1855+
for (int i=0; i<MAX_PALETTES; i++)
1856+
if (strip.customPalettes.size() < 10) {
1857+
strip.customPalettes.push_back(CRGBPalette16(CRGB(BLACK)));
1858+
palette[i] = &strip.customPalettes.back();
1859+
} else {
1860+
palette[i] = nullptr;
1861+
}
1862+
}
1863+
1864+
// credit @netmindz ar palette, adapted for usermod @blazoncek
1865+
CRGB AudioReactive::getCRGBForBand(int x, int pal) {
1866+
CRGB value;
1867+
CHSV hsv;
1868+
int b;
1869+
switch (pal) {
1870+
case 2:
1871+
b = map(x, 0, 255, 0, NUM_GEQ_CHANNELS/2); // convert palette position to lower half of freq band
1872+
hsv = CHSV(fftResult[b], 255, x);
1873+
hsv2rgb_rainbow(hsv, value); // convert to R,G,B
1874+
break;
1875+
case 1:
1876+
b = map(x, 1, 255, 0, 10); // convert palette position to lower half of freq band
1877+
hsv = CHSV(fftResult[b], 255, map(fftResult[b], 0, 255, 30, 255)); // pick hue
1878+
hsv2rgb_rainbow(hsv, value); // convert to R,G,B
1879+
break;
1880+
default:
1881+
if (x == 1) {
1882+
value = CRGB(fftResult[10]/2, fftResult[4]/2, fftResult[0]/2);
1883+
} else if(x == 255) {
1884+
value = CRGB(fftResult[10]/2, fftResult[0]/2, fftResult[4]/2);
1885+
} else {
1886+
value = CRGB(fftResult[0]/2, fftResult[4]/2, fftResult[10]/2);
1887+
}
1888+
break;
1889+
}
1890+
return value;
1891+
}
1892+
1893+
void AudioReactive::fillAudioPalette(int pal) {
1894+
if (pal>=MAX_PALETTES || !palette[pal]) return; // palette does not exist
1895+
1896+
uint8_t tcp[16]; // Needs to be 4 times however many colors are being used.
1897+
// 3 colors = 12, 4 colors = 16, etc.
1898+
1899+
tcp[0] = 0; // anchor of first color - must be zero
1900+
tcp[1] = 0;
1901+
tcp[2] = 0;
1902+
tcp[3] = 0;
1903+
1904+
CRGB rgb = getCRGBForBand(1, pal);
1905+
tcp[4] = 1; // anchor of first color
1906+
tcp[5] = rgb.r;
1907+
tcp[6] = rgb.g;
1908+
tcp[7] = rgb.b;
1909+
1910+
rgb = getCRGBForBand(128, pal);
1911+
tcp[8] = 128;
1912+
tcp[9] = rgb.r;
1913+
tcp[10] = rgb.g;
1914+
tcp[11] = rgb.b;
1915+
1916+
rgb = getCRGBForBand(255, pal);
1917+
tcp[12] = 255; // anchor of last color - must be 255
1918+
tcp[13] = rgb.r;
1919+
tcp[14] = rgb.g;
1920+
tcp[15] = rgb.b;
1921+
1922+
palette[pal]->loadDynamicGradientPalette(tcp);
1923+
}
1924+
18221925
// strings to reduce flash memory usage (used more than twice)
18231926
const char AudioReactive::_name[] PROGMEM = "AudioReactive";
18241927
const char AudioReactive::_enabled[] PROGMEM = "enabled";
@@ -1827,5 +1930,6 @@ const char AudioReactive::_inputLvl[] PROGMEM = "inputLevel";
18271930
const char AudioReactive::_analogmic[] PROGMEM = "analogmic";
18281931
#endif
18291932
const char AudioReactive::_digitalmic[] PROGMEM = "digitalmic";
1933+
const char AudioReactive::_addPalettes[] PROGMEM = "add-palettes";
18301934
const char AudioReactive::UDP_SYNC_HEADER[] PROGMEM = "00002"; // new sync header version, as format no longer compatible with previous structure
18311935
const char AudioReactive::UDP_SYNC_HEADER_v1[] PROGMEM = "00001"; // old sync header version - need to add backwards-compatibility feature

0 commit comments

Comments
 (0)