Skip to content

Commit

Permalink
Squashed commit of the following:
Browse files Browse the repository at this point in the history
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
  • Loading branch information
blazoncek committed Sep 10, 2023
1 parent 60c47cf commit cc68e6b
Show file tree
Hide file tree
Showing 35 changed files with 6,185 additions and 5,863 deletions.
6 changes: 3 additions & 3 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,16 @@
],
"dependsOrder": "sequence",
"problemMatcher": [
"$platformio",
],
"$platformio"
]
},
{
"type": "PlatformIO",
"label": "Build: binary only",
"task": "Build",
"group": {
"kind": "build",
"isDefault": true,
"isDefault": true
},
"problemMatcher": [
"$platformio"
Expand Down
3 changes: 3 additions & 0 deletions platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,9 @@ lib_deps =
IRremoteESP8266 @ 2.8.2
makuna/NeoPixelBus @ 2.7.5
https://github.com/Aircoookie/ESPAsyncWebServer.git @ ~2.0.7
# ESP-NOW library (includes mandatory QuickDebug library)
; gmag11/QuickESPNow @ 0.6.2
https://github.com/blazoncek/QuickESPNow.git#optional-debug
#For use of the TTGO T-Display ESP32 Module with integrated TFT display uncomment the following line
#TFT_eSPI
#For compatible OLED display uncomment following
Expand Down
104 changes: 104 additions & 0 deletions usermods/audioreactive/audio_reactive.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@
#define PLOT_PRINTF(x...)
#endif

#define MAX_PALETTES 3

// 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 !)
Expand Down Expand Up @@ -614,6 +616,8 @@ class AudioReactive : public Usermod {
// set your config variables to their boot default value (this can also be done in readFromConfig() or a constructor if you prefer)
bool enabled = false;
bool initDone = false;
bool addPalettes = false;
CRGBPalette16 *palette[MAX_PALETTES];

// variables for UDP sound sync
WiFiUDP fftUdp; // UDP object for sound sync (from WiFi UDP, not Async UDP!)
Expand Down Expand Up @@ -652,10 +656,15 @@ class AudioReactive : public Usermod {
static const char _inputLvl[];
static const char _analogmic[];
static const char _digitalmic[];
static const char _addPalettes[];
static const char UDP_SYNC_HEADER[];
static const char UDP_SYNC_HEADER_v1[];

// private methods
void removeAudioPalettes(void);
void createAudioPalettes(void);
CRGB getCRGBForBand(int x, int pal);
void fillAudioPalette(int pal);

////////////////////
// Debug support //
Expand Down Expand Up @@ -1196,6 +1205,7 @@ class AudioReactive : public Usermod {
}

if (enabled) connectUDPSoundSync();
if (enabled && addPalettes) createAudioPalettes();
initDone = true;
}

Expand Down Expand Up @@ -1358,6 +1368,7 @@ class AudioReactive : public Usermod {
lastTime = millis();
}

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


Expand Down Expand Up @@ -1610,6 +1621,11 @@ class AudioReactive : public Usermod {
if (usermod[FPSTR(_enabled)].is<bool>()) {
enabled = usermod[FPSTR(_enabled)].as<bool>();
if (prevEnabled != enabled) onUpdateBegin(!enabled);
if (addPalettes) {
// add/remove custom/audioreactive palettes
if (prevEnabled && !enabled) removeAudioPalettes();
if (!prevEnabled && enabled) createAudioPalettes();
}
}
if (usermod[FPSTR(_inputLvl)].is<int>()) {
inputLevel = min(255,max(0,usermod[FPSTR(_inputLvl)].as<int>()));
Expand Down Expand Up @@ -1657,6 +1673,7 @@ class AudioReactive : public Usermod {
{
JsonObject top = root.createNestedObject(FPSTR(_name));
top[FPSTR(_enabled)] = enabled;
top[FPSTR(_addPalettes)] = addPalettes;

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

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

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

if (initDone) {
// add/remove custom/audioreactive palettes
if ((oldAddPalettes && !addPalettes) || (oldAddPalettes && !enabled)) removeAudioPalettes();
if ((addPalettes && !oldAddPalettes && enabled) || (addPalettes && !oldEnabled && enabled)) createAudioPalettes();
} // else setup() will create palettes
return configComplete;
}

Expand Down Expand Up @@ -1819,6 +1844,84 @@ class AudioReactive : public Usermod {
}
};

void AudioReactive::removeAudioPalettes(void) {
for (int i=MAX_PALETTES-1; i>=0; i--) {
if (palette[i]) strip.customPalettes.pop_back();
palette[i] = nullptr;
}
}

void AudioReactive::createAudioPalettes(void) {
for (int i=0; i<MAX_PALETTES; i++)
if (strip.customPalettes.size() < 10) {
strip.customPalettes.push_back(CRGBPalette16(CRGB(BLACK)));
palette[i] = &strip.customPalettes.back();
} else {
palette[i] = nullptr;
}
}

// credit @netmindz ar palette, adapted for usermod @blazoncek
CRGB AudioReactive::getCRGBForBand(int x, int pal) {
CRGB value;
CHSV hsv;
int b;
switch (pal) {
case 2:
b = map(x, 0, 255, 0, NUM_GEQ_CHANNELS/2); // convert palette position to lower half of freq band
hsv = CHSV(fftResult[b], 255, x);
hsv2rgb_rainbow(hsv, value); // convert to R,G,B
break;
case 1:
b = map(x, 1, 255, 0, 10); // convert palette position to lower half of freq band
hsv = CHSV(fftResult[b], 255, map(fftResult[b], 0, 255, 30, 255)); // pick hue
hsv2rgb_rainbow(hsv, value); // convert to R,G,B
break;
default:
if (x == 1) {
value = CRGB(fftResult[10]/2, fftResult[4]/2, fftResult[0]/2);
} else if(x == 255) {
value = CRGB(fftResult[10]/2, fftResult[0]/2, fftResult[4]/2);
} else {
value = CRGB(fftResult[0]/2, fftResult[4]/2, fftResult[10]/2);
}
break;
}
return value;
}

void AudioReactive::fillAudioPalette(int pal) {
if (pal>=MAX_PALETTES || !palette[pal]) return; // palette does not exist

uint8_t tcp[16]; // Needs to be 4 times however many colors are being used.
// 3 colors = 12, 4 colors = 16, etc.

tcp[0] = 0; // anchor of first color - must be zero
tcp[1] = 0;
tcp[2] = 0;
tcp[3] = 0;

CRGB rgb = getCRGBForBand(1, pal);
tcp[4] = 1; // anchor of first color
tcp[5] = rgb.r;
tcp[6] = rgb.g;
tcp[7] = rgb.b;

rgb = getCRGBForBand(128, pal);
tcp[8] = 128;
tcp[9] = rgb.r;
tcp[10] = rgb.g;
tcp[11] = rgb.b;

rgb = getCRGBForBand(255, pal);
tcp[12] = 255; // anchor of last color - must be 255
tcp[13] = rgb.r;
tcp[14] = rgb.g;
tcp[15] = rgb.b;

palette[pal]->loadDynamicGradientPalette(tcp);
}

// strings to reduce flash memory usage (used more than twice)
const char AudioReactive::_name[] PROGMEM = "AudioReactive";
const char AudioReactive::_enabled[] PROGMEM = "enabled";
Expand All @@ -1827,5 +1930,6 @@ const char AudioReactive::_inputLvl[] PROGMEM = "inputLevel";
const char AudioReactive::_analogmic[] PROGMEM = "analogmic";
#endif
const char AudioReactive::_digitalmic[] PROGMEM = "digitalmic";
const char AudioReactive::_addPalettes[] PROGMEM = "add-palettes";
const char AudioReactive::UDP_SYNC_HEADER[] PROGMEM = "00002"; // new sync header version, as format no longer compatible with previous structure
const char AudioReactive::UDP_SYNC_HEADER_v1[] PROGMEM = "00001"; // old sync header version - need to add backwards-compatibility feature
Loading

0 comments on commit cc68e6b

Please sign in to comment.