Merge remote-tracking branch 'upstream/mdev' into mdev

This commit is contained in:
Brandon502
2024-10-02 17:43:15 -04:00
36 changed files with 1495 additions and 607 deletions

View File

@@ -37,6 +37,9 @@
#define indexToVStrip(index, stripNr) ((index) | (int((stripNr)+1)<<16))
// WLEDMM replace abs8 by abs, as abs8 does not work for numbers >127
#define abs8(x) abs(x)
// effect utility functions
static uint8_t sin_gap(uint16_t in) {
if (in & 0x100) return 0;
@@ -98,6 +101,14 @@ static long map2(long x, long in_min, long in_max, long out_min, long out_max)
}
static um_data_t* getAudioData() {
um_data_t *um_data;
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
// add support for no audio
um_data = simulateSound(SEGMENT.soundSim);
}
return um_data;
}
// effect functions
/*
@@ -1994,11 +2005,7 @@ uint16_t mode_partyjerk() {
* step: pos
*/
um_data_t *um_data;
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
// add support for no audio
um_data = simulateSound(SEGMENT.soundSim);
}
um_data_t *um_data = getAudioData();
float volumeSmth = *(float*) um_data->u_data[0];
SEGENV.aux0++;
@@ -2148,7 +2155,7 @@ uint16_t mode_fire_2012() {
// Step 4. Map from heat cells to LED colors
for (int j = 0; j < SEGLEN; j++) {
SEGMENT.setPixelColor(indexToVStrip(j, stripNr), ColorFromPalette(SEGPALETTE, min(heat[j],byte(240)), 255, NOBLEND));
SEGMENT.setPixelColor(indexToVStrip(j, stripNr), ColorFromPalette(SEGPALETTE, min(heat[j], byte(240)), 255, NOBLEND));
}
}
};
@@ -2156,14 +2163,19 @@ uint16_t mode_fire_2012() {
for (int stripNr=0; stripNr<strips; stripNr++)
virtualStrip::runStrip(stripNr, &heat[stripNr * SEGLEN], it);
if (SEGMENT.is2D()) SEGMENT.blur(32);
if (SEGMENT.is2D()) {
uint8_t blurAmount = SEGMENT.custom2 >> 2;
if (blurAmount > 48) blurAmount += blurAmount-48; // extra blur when slider > 192 (bush burn)
if (blurAmount < 16) SEGMENT.blurCols(SEGMENT.custom2 >> 1); // no side-burn when slider < 64 (faster)
else SEGMENT.blur(blurAmount);
}
if (it != SEGENV.step)
SEGENV.step = it;
return FRAMETIME;
}
static const char _data_FX_MODE_FIRE_2012[] PROGMEM = "Fire 2012@Cooling,Spark rate,,,Boost;;!;1.5d;sx=64,ix=160,m12=1"; // bars WLEDMM 1.5d,
static const char _data_FX_MODE_FIRE_2012[] PROGMEM = "Fire 2012@Cooling,Spark rate,,2D Blur,Boost;;!;1.5d;sx=64,ix=160,c2=128,m12=1"; // bars WLEDMM 1.5d,
// ColorWavesWithPalettes by Mark Kriegsman: https://gist.github.com/kriegsman/8281905786e8b2632aeb
@@ -4922,17 +4934,18 @@ uint16_t mode_2DBlackHole(void) { // By: Stepko https://editor.soulma
}
SEGMENT.fadeToBlackBy(16 + (SEGMENT.speed>>3)); // create fading trails
unsigned long t = strip.now/128; // timebase
const unsigned long ratio = 128; // rotation speed
unsigned long t = strip.now; // timebase
// outer stars
for (size_t i = 0; i < 8; i++) {
x = beatsin8(SEGMENT.custom1>>3, 0, cols - 1, 0, ((i % 2) ? 128 : 0) + t * i);
y = beatsin8(SEGMENT.intensity>>3, 0, rows - 1, 0, ((i % 2) ? 192 : 64) + t * i);
for (unsigned i = 0; i < 8; i++) {
x = beatsin8(SEGMENT.custom1>>3, 0, cols - 1, 0, ((i % 2) ? 128 : 0) + (t * i)/ratio);
y = beatsin8(SEGMENT.intensity>>3, 0, rows - 1, 0, ((i % 2) ? 192 : 64) + (t * i)/ratio);
SEGMENT.addPixelColorXY(x, y, CHSV(i*32, 255, 255));
}
// inner stars
for (size_t i = 0; i < 4; i++) {
x = beatsin8(SEGMENT.custom2>>3, cols/4, cols - 1 - cols/4, 0, ((i % 2) ? 128 : 0) + t * i);
y = beatsin8(SEGMENT.custom3 , rows/4, rows - 1 - rows/4, 0, ((i % 2) ? 192 : 64) + t * i);
x = beatsin8(SEGMENT.custom2>>3, cols/4, cols - 1 - cols/4, 0, ((i % 2) ? 128 : 0) + (t * i)/ratio);
y = beatsin8(SEGMENT.custom3 , rows/4, rows - 1 - rows/4, 0, ((i % 2) ? 192 : 64) + (t * i)/ratio);
SEGMENT.addPixelColorXY(x, y, CHSV(i*32, 255, 255));
}
// central white dot
@@ -4969,8 +4982,8 @@ uint16_t mode_2DColoredBursts() { // By: ldirko https://editor.so
SEGMENT.fadeToBlackBy(40);
for (size_t i = 0; i < numLines; i++) {
byte x1 = beatsin8(2 + SEGMENT.speed/16, 0, (cols - 1));
byte x2 = beatsin8(1 + SEGMENT.speed/16, 0, (cols - 1));
byte y1 = beatsin8(5 + SEGMENT.speed/16, 0, (rows - 1), 0, i * 24);
byte x2 = beatsin8(1 + SEGMENT.speed/16, 0, (rows - 1));
byte y1 = beatsin8(5 + SEGMENT.speed/16, 0, (cols - 1), 0, i * 24);
byte y2 = beatsin8(3 + SEGMENT.speed/16, 0, (rows - 1), 0, i * 48 + 64);
CRGB color = ColorFromPalette(SEGPALETTE, i * 255 / numLines + (SEGENV.aux0&0xFF), 255, LINEARBLEND);
@@ -5054,10 +5067,12 @@ uint16_t mode_2DDNASpiral() { // By: ldirko https://editor.soulma
if ((i + ms / 8) & 3) {
// draw a gradient line between x and x1
x = x / 2; x1 = x1 / 2;
uint8_t steps = abs8(x - x1) + 1;
unsigned steps = abs8(x - x1) + 1;
bool positive = (x1 >= x); // direction of drawing
for (size_t k = 1; k <= steps; k++) {
uint8_t rate = k * 255 / steps;
uint8_t dx = lerp8by8(x, x1, rate);
unsigned rate = k * 255 / steps;
//unsigned dx = lerp8by8(x, x1, rate);
unsigned dx = positive? (x + k-1) : (x - k+1); // behaves the same as "lerp8by8" but does not create holes
//SEGMENT.setPixelColorXY(dx, i, ColorFromPalette(SEGPALETTE, hue, 255, LINEARBLEND).nscale8_video(rate));
SEGMENT.addPixelColorXY(dx, i, ColorFromPalette(SEGPALETTE, hue, 255, LINEARBLEND)); // use setPixelColorXY for different look
SEGMENT.fadePixelColorXY(dx, i, rate);
@@ -5364,7 +5379,7 @@ uint16_t mode_2Dgameoflife(void) { // Written by Ewoud Wijma, inspired by https:
SEGENV.step = strip.now;
return FRAMETIME;
} // mode_2Dgameoflife()
static const char _data_FX_MODE_2DGAMEOFLIFE[] PROGMEM = "Game Of Life@!,Color Mutation ☾,Blur ☾,,,All Colors ☾,Overlay BG ☾,Wrap ☾,;!,!;!;2;sx=56,ix=2,c1=128,o1=0,o2=0,o3=1";
static const char _data_FX_MODE_2DGAMEOFLIFE[] PROGMEM = "Game Of Life@!,Color Mutation ☾,Blur ☾,,,All Colors ☾,Overlay BG ☾,Wrap ☾;!,!;!;2;sx=56,ix=2,c1=128,o1=0,o2=0,o3=1";
/////////////////////////
// 2D SnowFall //
@@ -5637,7 +5652,10 @@ uint16_t mode_2DLissajous(void) { // By: Andrew Tuline
float ylocn = float(cos8(phase/2 + i*2)) / 255.0f;
//SEGMENT.setPixelColorXY(xlocn, ylocn, SEGMENT.color_from_palette(strip.now/100+i, false, PALETTE_SOLID_WRAP, 0)); // draw pixel with anti-aliasing
unsigned palIndex = (256*ylocn) + phase/2 + (i* SEGMENT.speed)/64;
SEGMENT.setPixelColorXY(xlocn, ylocn, SEGMENT.color_from_palette(palIndex, false, PALETTE_SOLID_WRAP, 0)); // draw pixel with anti-aliasing - color follows rotation
//SEGMENT.setPixelColorXY(xlocn, ylocn, SEGMENT.color_from_palette(palIndex, false, PALETTE_SOLID_WRAP, 0)); // draw pixel with anti-aliasing - color follows rotation
// WLEDMM wu_pixel is 50% faster, and still lokks better
SEGMENT.wu_pixel(uint32_t(xlocn * (cols <<8)), uint32_t(ylocn * (rows <<8)),
CRGB(SEGMENT.color_from_palette(palIndex, false, PALETTE_SOLID_WRAP, 0)));
}
} else
for (int i=0; i < 256; i ++) {
@@ -6381,6 +6399,10 @@ uint16_t mode_2Dfloatingblobs(void) {
}
SEGMENT.fadeToBlackBy(20);
bool drawAA = (SEGMENT.custom1 > 0) && (SEGMENT.custom1 < 6); //WLEDMM
const uint16_t minDim = min(cols, rows); // WLEDMM use smaller dimension to find good blob size
float max_grow = min(minDim/4.f,2.f);
if (minDim>=24) max_grow =(minDim/8.0f); // WLEDMM allow bigger blobs
// Bounce balls around
for (size_t i = 0; i < Amount; i++) {
@@ -6389,18 +6411,18 @@ uint16_t mode_2Dfloatingblobs(void) {
if (blob->grow[i]) {
// enlarge radius until it is >= 4
blob->r[i] += (fabsf(blob->sX[i]) > fabsf(blob->sY[i]) ? fabsf(blob->sX[i]) : fabsf(blob->sY[i])) * 0.05f;
if (blob->r[i] >= min(cols/4.f,2.f)) {
if (blob->r[i] >= max_grow) {
blob->grow[i] = false;
}
} else {
// reduce radius until it is < 1
blob->r[i] -= (fabsf(blob->sX[i]) > fabsf(blob->sY[i]) ? fabsf(blob->sX[i]) : fabsf(blob->sY[i])) * 0.05f;
if (blob->r[i] < 1.f) {
if (blob->r[i] < 0.8f) {
blob->grow[i] = true;
}
}
uint32_t c = SEGMENT.color_from_palette(blob->color[i], false, false, 0);
if (blob->r[i] > 1.f) SEGMENT.fillCircle(roundf(blob->x[i]), roundf(blob->y[i]), roundf(blob->r[i]), c);
if (blob->r[i] > 1.f) SEGMENT.fillCircle(roundf(blob->x[i]), roundf(blob->y[i]), roundf(blob->r[i]), c, drawAA);
else SEGMENT.setPixelColorXY((int)roundf(blob->x[i]), (int)roundf(blob->y[i]), c);
// move x
if (blob->x[i] + blob->r[i] >= cols - 1) blob->x[i] += (blob->sX[i] * ((cols - 1 - blob->x[i]) / blob->r[i] + 0.005f));
@@ -6468,7 +6490,7 @@ uint16_t mode_2Dscrollingtext(void) {
if (SEGMENT.name) for (size_t i=0,j=0; i<maxLen; i++) if (SEGMENT.name[i]>31 && SEGMENT.name[i]<128) text[j++] = SEGMENT.name[i];
const bool zero = strchr(text, '0') != nullptr;
if (!strlen(text) || !strncmp_P(text,PSTR("#F"),2) || !strncmp_P(text,PSTR("#P"),2) || !strncmp_P(text,PSTR("#DATE"),5) || !strncmp_P(text,PSTR("#DDMM"),5) || !strncmp_P(text,PSTR("#MMDD"),5) || !strncmp_P(text,PSTR("#TIME"),5) || !strncmp_P(text,PSTR("#HH"),3) || !strncmp_P(text,PSTR("#MM"),3)) { // fallback if empty segment name: display date and time
if (!strlen(text) || !strncmp_P(text,PSTR("#F"),2) || !strncmp_P(text,PSTR("#P"),2) || !strncmp_P(text,PSTR("#A"),2) || !strncmp_P(text,PSTR("#DATE"),5) || !strncmp_P(text,PSTR("#DDMM"),5) || !strncmp_P(text,PSTR("#MMDD"),5) || !strncmp_P(text,PSTR("#TIME"),5) || !strncmp_P(text,PSTR("#HH"),3) || !strncmp_P(text,PSTR("#MM"),3)) { // fallback if empty segment name: display date and time
char sec[5]= {'\0'};
byte AmPmHour = hour(localTime);
boolean isitAM = true;
@@ -6501,6 +6523,7 @@ uint16_t mode_2Dscrollingtext(void) {
SEGMENT.blendPixelColorXY(x, y, SEGCOLOR(1), 255 - (SEGMENT.custom1>>1));
}
}
bool drawShadow = (SEGMENT.check2) && (SEGMENT.custom1 == 0);
for (int i = 0; i < numberOfLetters; i++) {
if (int(cols) - int(SEGENV.aux0) + letterWidth*(i+1) < 0) continue; // don't draw characters off-screen
uint32_t col1 = SEGMENT.color_from_palette(SEGENV.aux1, false, PALETTE_SOLID_WRAP, 0);
@@ -6509,7 +6532,7 @@ uint16_t mode_2Dscrollingtext(void) {
col1 = SEGCOLOR(0);
col2 = SEGCOLOR(2);
}
SEGMENT.drawCharacter(text[i], int(cols) - int(SEGENV.aux0) + letterWidth*i, yoffset, letterWidth, letterHeight, col1, col2);
SEGMENT.drawCharacter(text[i], int(cols) - int(SEGENV.aux0) + letterWidth*i, yoffset, letterWidth, letterHeight, col1, col2, drawShadow);
}
return FRAMETIME;
@@ -6620,11 +6643,7 @@ uint16_t mode_ripplepeak(void) { // * Ripple peak. By Andrew Tuli
if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed
Ripple* ripples = reinterpret_cast<Ripple*>(SEGENV.data);
um_data_t *um_data;
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
// add support for no audio
um_data = simulateSound(SEGMENT.soundSim);
}
um_data_t *um_data = getAudioData();
uint8_t samplePeak = *(uint8_t*)um_data->u_data[3];
#ifdef ESP32
float FFT_MajorPeak = *(float*) um_data->u_data[4];
@@ -6720,11 +6739,7 @@ uint16_t mode_2DSwirl(void) {
uint8_t nj = (cols - 1) - j;
uint16_t ms = strip.now;
um_data_t *um_data;
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
// add support for no audio
um_data = simulateSound(SEGMENT.soundSim);
}
um_data_t *um_data = getAudioData();
float volumeSmth = *(float*) um_data->u_data[0]; //ewowi: use instead of sampleAvg???
int16_t volumeRaw = *(int16_t*) um_data->u_data[1];
@@ -6757,11 +6772,7 @@ uint16_t mode_2DWaverly(void) {
SEGMENT.fill(BLACK);
}
um_data_t *um_data;
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
// add support for no audio
um_data = simulateSound(SEGMENT.soundSim);
}
um_data_t *um_data = getAudioData();
float volumeSmth = *(float*) um_data->u_data[0];
float soundPressure = *(float*) um_data->u_data[9];
float agcSensitivity= *(float*) um_data->u_data[10];
@@ -6773,20 +6784,26 @@ uint16_t mode_2DWaverly(void) {
long t = strip.now / 2;
for (int i = 0; i < cols; i++) {
uint16_t thisVal = volumeSmth*SEGMENT.intensity/64 * inoise8(i * 45 , t , t)/64; // WLEDMM back to SR code
uint16_t thisMax = map(thisVal, 0, 512, 0, rows);
//uint16_t thisVal = volumeSmth*SEGMENT.intensity/64 * inoise8(i * 45 , t , t)/64; // WLEDMM back to SR code
unsigned thisVal = unsigned(volumeSmth*SEGMENT.intensity) * inoise8(i * 45 , t , t) / (64*64); // WLEDMM same result but more accurate
for (int j = 0; j < thisMax; j++) {
//int thisMax = map(thisVal, 0, 512, 0, rows);
int thisMax = (thisVal * rows) / 512; // WLEDMM same result, just faster
int thisMax2 = min(int(rows), thisMax); // WLEDMM limit height to visible are
for (int j = 0; j < thisMax2; j++) {
//int jmap = map(j, 0, thisMax, 250, 0);
int jmap = 250 - ((j * 250) / thisMax); // WLEDMM same result, just faster
if (!SEGENV.check1)
SEGMENT.addPixelColorXY(i, j, ColorFromPalette(SEGPALETTE, map(j, 0, thisMax, 250, 0), 255, LINEARBLEND));
SEGMENT.addPixelColorXY((cols - 1) - i, (rows - 1) - j, ColorFromPalette(SEGPALETTE, map(j, 0, thisMax, 250, 0), 255, LINEARBLEND));
SEGMENT.addPixelColorXY(i, j, ColorFromPalette(SEGPALETTE, jmap, 255, LINEARBLEND));
SEGMENT.addPixelColorXY((cols - 1) - i, (rows - 1) - j, ColorFromPalette(SEGPALETTE, jmap, 255, LINEARBLEND));
}
}
SEGMENT.blur(16);
return FRAMETIME;
} // mode_2DWaverly()
static const char _data_FX_MODE_2DWAVERLY[] PROGMEM = "Waverly ☾@Amplification,Sensitivity,,,,No Clouds,Sound Pressure,AGC debug;;!;2v;ix=64,si=0"; // Beatsin
static const char _data_FX_MODE_2DWAVERLY[] PROGMEM = "Waverly ☾@Fade Rate,Amplification,,,,No Clouds,Sound Pressure,AGC debug;;!;2v;ix=64,si=0"; // Beatsin
#endif // WLED_DISABLE_2D
@@ -6809,11 +6826,7 @@ uint16_t mode_gravcenter(void) { // Gravcenter. By Andrew Tuline.
SEGMENT.fill(BLACK);
}
um_data_t *um_data;
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
// add support for no audio
um_data = simulateSound(SEGMENT.soundSim);
}
um_data_t *um_data = getAudioData();
float volumeSmth = *(float*) um_data->u_data[0];
//SEGMENT.fade_out(240);
@@ -6861,11 +6874,7 @@ uint16_t mode_gravcentric(void) { // Gravcentric. By Andrew
SEGMENT.fill(BLACK);
}
um_data_t *um_data;
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
// add support for no audio
um_data = simulateSound(SEGMENT.soundSim);
}
um_data_t *um_data = getAudioData();
float volumeSmth = *(float*) um_data->u_data[0];
// printUmData();
@@ -6912,11 +6921,7 @@ uint16_t mode_gravimeter(void) { // Gravmeter. By Andrew Tuline.
if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed
Gravity* gravcen = reinterpret_cast<Gravity*>(SEGENV.data);
um_data_t *um_data;
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
// add support for no audio
um_data = simulateSound(SEGMENT.soundSim);
}
um_data_t *um_data = getAudioData();
float volumeSmth = *(float*) um_data->u_data[0];
// int16_t volumeRaw = *(int16_t*)um_data->u_data[1]; //WLEDMM: this variable not used here
float soundPressure = *(float*) um_data->u_data[9];
@@ -6989,11 +6994,7 @@ static const char _data_FX_MODE_GRAVIMETER[] PROGMEM = "Gravimeter ☾@Rate of f
// * JUGGLES //
//////////////////////
uint16_t mode_juggles(void) { // Juggles. By Andrew Tuline.
um_data_t *um_data;
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
// add support for no audio
um_data = simulateSound(SEGMENT.soundSim);
}
um_data_t *um_data = getAudioData();
float volumeSmth = *(float*) um_data->u_data[0];
if (SEGENV.call == 0) {SEGENV.setUpLeds(); SEGMENT.fill(BLACK);} // WLEDMM use lossless getPixelColor()
@@ -7016,11 +7017,7 @@ static const char _data_FX_MODE_JUGGLES[] PROGMEM = "Juggles@!,# of balls;!,!;!;
uint16_t mode_matripix(void) { // Matripix. By Andrew Tuline. With some enhancements by @softhack007
// even with 1D effect we have to take logic for 2D segments for allocation as fill_solid() fills whole segment
um_data_t *um_data;
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
// add support for no audio
um_data = simulateSound(SEGMENT.soundSim);
}
um_data_t *um_data = getAudioData();
int16_t volumeRaw = *(int16_t*)um_data->u_data[1];
float volumeSmth = *(float*) um_data->u_data[0];
float soundPressure = *(float*) um_data->u_data[9];
@@ -7072,11 +7069,7 @@ static const char _data_FX_MODE_MATRIPIX[] PROGMEM = "Matripix ☾@!,Brightness,
uint16_t mode_midnoise(void) { // Midnoise. By Andrew Tuline.
// Changing xdist to SEGENV.aux0 and ydist to SEGENV.aux1.
um_data_t *um_data;
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
// add support for no audio
um_data = simulateSound(SEGMENT.soundSim);
}
um_data_t *um_data = getAudioData();
float volumeSmth = *(float*) um_data->u_data[0];
if (SEGENV.call == 0) {
@@ -7115,11 +7108,7 @@ uint16_t mode_noisefire(void) { // Noisefire. By Andrew Tuline.
CRGB::DarkOrange, CRGB::DarkOrange, CRGB::Orange, CRGB::Orange,
CRGB::Yellow, CRGB::Orange, CRGB::Yellow, CRGB::Yellow);
um_data_t *um_data;
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
// add support for no audio
um_data = simulateSound(SEGMENT.soundSim);
}
um_data_t *um_data = getAudioData();
float volumeSmth = *(float*) um_data->u_data[0];
if (SEGENV.call == 0) SEGMENT.fill(BLACK);
@@ -7143,11 +7132,7 @@ static const char _data_FX_MODE_NOISEFIRE[] PROGMEM = "Noisefire@!,!;;;01v;m12=2
///////////////////////
uint16_t mode_noisemeter(void) { // Noisemeter. By Andrew Tuline.
um_data_t *um_data;
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
// add support for no audio
um_data = simulateSound(SEGMENT.soundSim);
}
um_data_t *um_data = getAudioData();
float volumeSmth = *(float*) um_data->u_data[0];
int16_t volumeRaw = *(int16_t*)um_data->u_data[1];
if (SEGENV.call == 0) {SEGENV.setUpLeds(); SEGMENT.fill(BLACK);} // WLEDMM use lossless getPixelColor()
@@ -7185,11 +7170,7 @@ uint16_t mode_pixelwave(void) { // Pixelwave. By Andrew Tuline.
SEGMENT.fill(BLACK);
}
um_data_t *um_data;
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
// add support for no audio
um_data = simulateSound(SEGMENT.soundSim);
}
um_data_t *um_data = getAudioData();
int16_t volumeRaw = *(int16_t*)um_data->u_data[1];
uint8_t secondHand = micros()/(256-SEGMENT.speed)/500+1 % 16;
@@ -7223,11 +7204,7 @@ uint16_t mode_plasmoid(void) { // Plasmoid. By Andrew Tuline.
if (!SEGENV.allocateData(sizeof(plasphase))) return mode_static(); //allocation failed
Plasphase* plasmoip = reinterpret_cast<Plasphase*>(SEGENV.data);
um_data_t *um_data;
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
// add support for no audio
um_data = simulateSound(SEGMENT.soundSim);
}
um_data_t *um_data = getAudioData();
float volumeSmth = *(float*) um_data->u_data[0];
if (SEGENV.call == 0) {
@@ -7266,11 +7243,7 @@ uint16_t mode_puddlepeak(void) { // Puddlepeak. By Andrew Tuline.
uint8_t fadeVal = map2(SEGMENT.speed,0,255, 224, 254);
uint16_t pos = random16(SEGLEN); // Set a random starting position.
um_data_t *um_data;
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
// add support for no audio
um_data = simulateSound(SEGMENT.soundSim);
}
um_data_t *um_data = getAudioData();
uint8_t samplePeak = *(uint8_t*)um_data->u_data[3];
uint8_t *maxVol = (uint8_t*)um_data->u_data[6];
uint8_t *binNum = (uint8_t*)um_data->u_data[7];
@@ -7318,11 +7291,7 @@ uint16_t mode_puddles(void) { // Puddles. By Andrew Tuline.
}
SEGMENT.fade_out(fadeVal);
um_data_t *um_data;
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
// add support for no audio
um_data = simulateSound(SEGMENT.soundSim);
}
um_data_t *um_data = getAudioData();
int16_t volumeRaw = *(int16_t*)um_data->u_data[1];
if (volumeRaw > 1) {
@@ -7347,10 +7316,7 @@ uint16_t mode_pixels(void) { // Pixels. By Andrew Tuline.
if (!SEGENV.allocateData(32*sizeof(uint8_t))) return mode_static(); //allocation failed
uint8_t *myVals = reinterpret_cast<uint8_t*>(SEGENV.data); // Used to store a pile of samples because WLED frame rate and WLED sample rate are not synchronized. Frame rate is too low.
um_data_t *um_data;
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
um_data = simulateSound(SEGMENT.soundSim);
}
um_data_t *um_data = getAudioData();
float volumeSmth = *(float*) um_data->u_data[0];
if (SEGENV.call == 0) {SEGENV.setUpLeds(); SEGMENT.fill(BLACK);} // WLEDMM use lossless getPixelColor()
@@ -7380,11 +7346,7 @@ static const char _data_FX_MODE_PIXELS[] PROGMEM = "Pixels@Fade rate,# of pixels
uint16_t mode_blurz(void) { // Blurz. By Andrew Tuline.
// even with 1D effect we have to take logic for 2D segments for allocation as fill_solid() fills whole segment
um_data_t *um_data;
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
// add support for no audio
um_data = simulateSound(SEGMENT.soundSim);
}
um_data_t *um_data = getAudioData();
uint8_t *fftResult = (uint8_t*)um_data->u_data[2];
if (SEGENV.call == 0) {
@@ -7414,11 +7376,7 @@ static const char _data_FX_MODE_BLURZ[] PROGMEM = "Blurz@Fade rate,Blur;!,Color
uint16_t mode_blurz(void) { // Blurz. By Andrew Tuline.
// Hint: Looks best with segment brightness set to max (use global brightness to reduce brightness)
// even with 1D effect we have to take logic for 2D segments for allocation as fill_solid() fills whole segment
um_data_t *um_data;
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
// add support for no audio
um_data = simulateSound(SEGMENT.soundSim);
}
um_data_t *um_data = getAudioData();
uint8_t *fftResult = (uint8_t*)um_data->u_data[2];
float volumeSmth = *(float*)um_data->u_data[0];
@@ -7466,11 +7424,7 @@ uint16_t mode_DJLight(void) { // Written by Stefan Petrick, Ad
// No need to prevent from executing on single led strips, only mid will be set (mid = 0)
const int mid = SEGLEN / 2;
um_data_t *um_data;
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
// add support for no audio
um_data = simulateSound(SEGMENT.soundSim);
}
um_data_t *um_data = getAudioData();
uint8_t *fftResult = (uint8_t*)um_data->u_data[2];
float volumeSmth = *(float*)um_data->u_data[0];
@@ -7536,11 +7490,7 @@ uint16_t mode_freqmap(void) { // Map FFT_MajorPeak to SEGLEN.
// Start frequency = 60 Hz and log10(60) = 1.78
// End frequency = MAX_FREQUENCY in Hz and lo10(MAX_FREQUENCY) = MAX_FREQ_LOG10
um_data_t *um_data;
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
// add support for no audio
um_data = simulateSound(SEGMENT.soundSim);
}
um_data_t *um_data = getAudioData();
float FFT_MajorPeak = *(float*)um_data->u_data[SEGENV.check1 ? 8:4]; // WLEDMM may use FFT_MajorPeakSmth
float my_magnitude = *(float*)um_data->u_data[5] / 4.0f;
if (FFT_MajorPeak < 1) FFT_MajorPeak = 1; // log10(0) is "forbidden" (throws exception)
@@ -7581,11 +7531,7 @@ static const char _data_FX_MODE_FREQMAP[] PROGMEM = "Freqmap@Fade rate,Starting
///////////////////////
uint16_t mode_freqmatrix(void) { // Freqmatrix. By Andreas Pleschung.
// No need to prevent from executing on single led strips, we simply change pixel 0 each time and avoid the shift
um_data_t *um_data;
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
// add support for no audio
um_data = simulateSound(SEGMENT.soundSim);
}
um_data_t *um_data = getAudioData();
float FFT_MajorPeak = *(float*)um_data->u_data[4];
float volumeSmth = *(float*)um_data->u_data[0];
@@ -7622,9 +7568,9 @@ uint16_t mode_freqmatrix(void) { // Freqmatrix. By Andreas Plesch
}
// shift the pixels one pixel up
SEGMENT.setPixelColor(0, color);
// if SEGLEN equals 1 this loop won't execute
for (int i = SEGLEN - 1; i > 0; i--) SEGMENT.setPixelColor(i, SEGMENT.getPixelColor(i-1)); //move to the left
SEGMENT.setPixelColor(0, color);
}
return FRAMETIME;
@@ -7640,11 +7586,7 @@ static const char _data_FX_MODE_FREQMATRIX[] PROGMEM = "Freqmatrix@Speed,Sound e
// SEGMENT.speed select faderate
// SEGMENT.intensity select colour index
uint16_t mode_freqpixels(void) { // Freqpixel. By Andrew Tuline.
um_data_t *um_data;
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
// add support for no audio
um_data = simulateSound(SEGMENT.soundSim);
}
um_data_t *um_data = getAudioData();
float FFT_MajorPeak = *(float*)um_data->u_data[4];
float my_magnitude = *(float*)um_data->u_data[5] / 16.0f;
if (FFT_MajorPeak < 1) FFT_MajorPeak = 1; // log10(0) is "forbidden" (throws exception)
@@ -7687,11 +7629,7 @@ static const char _data_FX_MODE_FREQPIXELS[] PROGMEM = "Freqpixels@Fade rate,Sta
// Depending on the music stream you have you might find it useful to change the frequency mapping.
uint16_t mode_freqwave(void) { // Freqwave. By Andreas Pleschung. With some enhancements by @softhack007
// As before, this effect can also work on single pixels, we just lose the shifting effect
um_data_t *um_data;
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
// add support for no audio
um_data = simulateSound(SEGMENT.soundSim);
}
um_data_t *um_data = getAudioData();
float FFT_MajorPeak = *(float*)um_data->u_data[4];
float volumeSmth = *(float*)um_data->u_data[0];
@@ -7761,11 +7699,7 @@ uint16_t mode_gravfreq(void) { // Gravfreq. By Andrew Tuline.
if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed
Gravity* gravcen = reinterpret_cast<Gravity*>(SEGENV.data);
um_data_t *um_data;
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
// add support for no audio
um_data = simulateSound(SEGMENT.soundSim);
}
um_data_t *um_data = getAudioData();
float FFT_MajorPeak = *(float*)um_data->u_data[4];
float volumeSmth = *(float*)um_data->u_data[0];
if (FFT_MajorPeak < 1) FFT_MajorPeak = 1; // log10(0) is "forbidden" (throws exception)
@@ -7814,11 +7748,7 @@ static const char _data_FX_MODE_GRAVFREQ[] PROGMEM = "Gravfreq ☾@Rate of fall,
// ** Noisemove //
//////////////////////
uint16_t mode_noisemove(void) { // Noisemove. By: Andrew Tuline
um_data_t *um_data;
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
// add support for no audio
um_data = simulateSound(SEGMENT.soundSim);
}
um_data_t *um_data = getAudioData();
uint8_t fftResult[NUM_GEQ_CHANNELS] = {0};
if (um_data->u_data != nullptr) memcpy(fftResult, um_data->u_data[2], sizeof(fftResult)); // WLEDMM buffer curent values
@@ -7847,11 +7777,7 @@ static const char _data_FX_MODE_NOISEMOVE[] PROGMEM = "Noisemove@Speed of perlin
// ** Rocktaves //
//////////////////////
uint16_t mode_rocktaves(void) { // Rocktaves. Same note from each octave is same colour. By: Andrew Tuline
um_data_t *um_data;
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
// add support for no audio
um_data = simulateSound(SEGMENT.soundSim);
}
um_data_t *um_data = getAudioData();
float FFT_MajorPeak = *(float*) um_data->u_data[8]; // WLEDMM use FFT_MajorPeakSmth
float my_magnitude = *(float*) um_data->u_data[5] / 16.0f;
@@ -7895,11 +7821,7 @@ uint16_t mode_waterfall(void) { // Waterfall. By: Andrew Tulin
// effect can work on single pixels, we just lose the shifting effect
if (SEGENV.call == 0) SEGMENT.fill(BLACK);
um_data_t *um_data;
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
// add support for no audio
um_data = simulateSound(SEGMENT.soundSim);
}
um_data_t *um_data = getAudioData();
uint8_t samplePeak = *(uint8_t*)um_data->u_data[3];
float FFT_MajorPeak = *(float*) um_data->u_data[4];
uint8_t *maxVol = (uint8_t*)um_data->u_data[6];
@@ -7960,11 +7882,7 @@ uint16_t mode_2DGEQ(void) { // By Will Tatam. Code reduction by Ewoud Wijma.
if (!SEGENV.allocateData(cols*sizeof(uint16_t))) return mode_static(); //allocation failed
uint16_t *previousBarHeight = reinterpret_cast<uint16_t*>(SEGENV.data); //array of previous bar heights per frequency band
um_data_t *um_data;
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
// add support for no audio
um_data = simulateSound(SEGMENT.soundSim);
}
um_data_t *um_data = getAudioData();
uint8_t fftResult[NUM_GEQ_CHANNELS] = {0};
if (um_data->u_data != nullptr) memcpy(fftResult, um_data->u_data[2], sizeof(fftResult)); // WLEDMM buffer curent values
@@ -8071,11 +7989,7 @@ uint16_t mode_2DFunkyPlank(void) { // Written by ??? Adapted by Wil
bandInc = (NUMB_BANDS / cols);
}
um_data_t *um_data;
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
// add support for no audio
um_data = simulateSound(SEGMENT.soundSim);
}
um_data_t *um_data = getAudioData();
uint8_t fftResult[NUM_GEQ_CHANNELS] = {0};
if (um_data->u_data != nullptr) memcpy(fftResult, um_data->u_data[2], sizeof(fftResult)); // WLEDMM buffer curent values
@@ -8156,7 +8070,7 @@ uint16_t mode_2DAkemi(void) {
const uint16_t cols = SEGMENT.virtualWidth();
const uint16_t rows = SEGMENT.virtualHeight();
if (SEGENV.call == 0) {SEGMENT.setUpLeds(); SEGMENT.fill(BLACK);}
if (SEGENV.call == 0) {SEGMENT.fill(BLACK);}
uint16_t counter = (strip.now * ((SEGMENT.speed >> 2) +2)) & 0xFFFF;
counter = counter >> 8;
@@ -8164,10 +8078,7 @@ uint16_t mode_2DAkemi(void) {
const float lightFactor = 0.15f;
const float normalFactor = 0.4f;
um_data_t *um_data = nullptr;
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
um_data = simulateSound(SEGMENT.soundSim);
}
um_data_t *um_data = getAudioData();
uint8_t fftResult[NUM_GEQ_CHANNELS] = {0};
if (um_data->u_data != nullptr) memcpy(fftResult, um_data->u_data[2], sizeof(fftResult)); // WLEDMM buffer curent values
float base = fftResult[0]/255.0f;
@@ -8200,11 +8111,12 @@ uint16_t mode_2DAkemi(void) {
//add geq left and right
if (um_data) {
for (int x=0; x < cols/8; x++) {
uint16_t band = x * cols/8;
int xMax = cols/8;
for (int x=0; x < xMax; x++) {
size_t band = map2(x, 0, max(xMax,4), 0, 15); // map 0..cols/8 to 16 GEQ bands
CRGB color = SEGMENT.color_from_palette((band * 35), false, PALETTE_SOLID_WRAP, 0);
band = constrain(band, 0, 15);
uint16_t barHeight = map(fftResult[band], 0, 255, 0, 17*rows/32);
CRGB color = SEGMENT.color_from_palette((band * 35), false, PALETTE_SOLID_WRAP, 0);
for (int y=0; y < barHeight; y++) {
SEGMENT.setPixelColorXY(x, rows/2-y, color);
@@ -8553,11 +8465,7 @@ uint16_t mode_GEQLASER(void) {
uint16_t horizon = map2(SEGMENT.custom1,0,255,rows-1,0);
uint8_t depth = SEGMENT.custom2; // depth of perspective. 255 = infinite ("laser")
um_data_t *um_data;
if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) {
// add support for no audio
um_data = simulateSound(SEGMENT.soundSim);
}
um_data_t *um_data = getAudioData();
uint8_t *fftResult = (uint8_t*)um_data->u_data[2];
uint8_t heights[NUM_GEQ_CHANNELS] = { 0 };
@@ -8661,6 +8569,84 @@ static const char _data_FX_MODE_GEQLASER[] PROGMEM = "GEQ 3D ☾@Speed,Front Fil
#endif // WLED_DISABLE_2D
/*
@title MoonModules WLED - Painbrush Effect
@file included in FX.cpp
@repo https://github.com/MoonModules/WLED, submit changes to this file as PRs to MoonModules/WLED
@Authors https://github.com/MoonModules/WLED/commits/mdev/
@Copyright © 2024 Github MoonModules Commit Authors (contact moonmodules@icloud.com for details)
@license GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007
This function is part of the MoonModules WLED fork also known as "WLED-MM".
WLED-MM is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License
as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
WLED-MM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with WLED-MM. If not, see <https://www.gnu.org/licenses/>.
*/
///////////////////////
// 2D Paintbrush //
///////////////////////
uint16_t mode_2DPaintbrush() {
// Author: @TroyHacks
// @license GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007
if (!strip.isMatrix) return mode_static(); // not a 2D set-up
const uint16_t cols = SEGMENT.virtualWidth();
const uint16_t rows = SEGMENT.virtualHeight();
if (!SEGENV.allocateData(4)) return mode_static(); //allocation failed
if (SEGENV.call == 0) {
SEGMENT.setUpLeds();
SEGMENT.fill(BLACK);
SEGENV.aux0 = 0;
}
bool phase_chaos = SEGMENT.check3;
bool soft = SEGMENT.check2;
bool color_chaos = SEGMENT.check1;
CRGB color;
byte numLines = map8(SEGMENT.intensity,1,16);
SEGENV.aux0++; // hue
SEGMENT.fadeToBlackBy(map8(SEGENV.custom1,10,128));
um_data_t *um_data = getAudioData();
uint8_t *fftResult = (uint8_t*)um_data->u_data[2];
SEGENV.aux1 = phase_chaos?random8():0;
for (size_t i = 0; i < numLines; i++) {
byte bin = map(i,0,numLines,0,15);
byte x1 = beatsin8(max(16,int(SEGMENT.speed))/16*1 + fftResult[0]/16, 0, (cols-1), fftResult[bin], SEGENV.aux1);
byte x2 = beatsin8(max(16,int(SEGMENT.speed))/16*2 + fftResult[0]/16, 0, (cols-1), fftResult[bin], SEGENV.aux1);
byte y1 = beatsin8(max(16,int(SEGMENT.speed))/16*3 + fftResult[0]/16, 0, (rows-1), fftResult[bin], SEGENV.aux1);
byte y2 = beatsin8(max(16,int(SEGMENT.speed))/16*4 + fftResult[0]/16, 0, (rows-1), fftResult[bin], SEGENV.aux1);
int length = sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1));
length = map8(fftResult[bin],0,length);
if (length > max(1,int(SEGMENT.custom3))) {
if (color_chaos) {
color = ColorFromPalette(SEGPALETTE, i * 255 / numLines + (SEGENV.aux0&0xFF), 255, LINEARBLEND);
} else {
uint16_t colorIndex = map(i,0,numLines,0,255);
color = SEGMENT.color_from_palette(colorIndex, false, PALETTE_SOLID_WRAP, 0);
}
SEGMENT.drawLine(x1,y1,x2,y2,color,soft,length);
}
}
return FRAMETIME;
} // mode_2DPaintbrush()
static const char _data_FX_MODE_2DPAINTBRUSH[] PROGMEM = "Paintbrush ☾@Oscillator Offset,# of lines,Fade Rate,,Min Length,Color Chaos,Anti-aliasing,Phase Chaos;!,,Peaks;!;2f;sx=160,ix=255,c1=80,c2=255,c3=0,pal=72,o1=0,o2=1,o3=0";
//////////////////////////////////////////////////////////////////////////////////////////
// mode data
@@ -8908,6 +8894,8 @@ void WS2812FX::setupEffectData() {
addEffect(FX_MODE_GEQLASER, &mode_GEQLASER, _data_FX_MODE_GEQLASER); // audio
addEffect(FX_MODE_2DPAINTBRUSH, &mode_2DPaintbrush, _data_FX_MODE_2DPAINTBRUSH); // audio
#endif // WLED_DISABLE_2D
}