From 411df4ec5132516ab9eee1f782d227314b778da1 Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Thu, 12 Sep 2024 21:22:16 +0200 Subject: [PATCH 01/13] Improvements & merges of FX - Waving Cell: Improved with higher temporal resolution (smoother at lower speeds) and added additional mode setting and optional blurring - Merged puddles and puddlepeak - Merged Gravcenter, Gravcentric, Gravfreq and Gravimeter (saves 1.2k of flash) - Merged meteor and meteor smooth - Renamed police_base into mode_two_dots as that was just an alias - Changed default of Palette effect: Animate rotation is now unchecked by default (it looks weird and confusing in 1D as a default) - Added or enhanced blurring of - DNA - DNA Spiral - Drift - Drift Rose - Crazy Bees - Ripple - Colored Bursts - Frizzles - Lissajous - Sindots - Spaceships - Added palette support to - Crazy Bees - Polar Lights - Drift Rose - Some code cleanup (removed unused / commented stuff) - Renamed police_base into mode_two_dots (was just an alias not used by anything else) - Moved dev info for AR to the top so ist easier to find as a reference, also added link to KB there --- wled00/FX.cpp | 666 ++++++++++++++++++++------------------------------ wled00/FX.h | 2 +- 2 files changed, 267 insertions(+), 401 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 807594e430..53ce8686cf 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -24,12 +24,56 @@ Modified heavily for WLED */ +/* + ////////////// + // DEV INFO // + ////////////// + + information for FX metadata strings: https://kno.wled.ge/interfaces/json-api/#effect-metadata + + Audio Reactive: use the following code to pass usermod variables to effect + + uint8_t *binNum = (uint8_t*)&SEGENV.aux1, *maxVol = (uint8_t*)(&SEGENV.aux1+1); // just in case assignment + bool samplePeak = false; + float FFT_MajorPeak = 1.0; + uint8_t *fftResult = nullptr; + float *fftBin = nullptr; + um_data_t *um_data; + if (usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { + volumeSmth = *(float*) um_data->u_data[0]; + volumeRaw = *(float*) um_data->u_data[1]; + fftResult = (uint8_t*) um_data->u_data[2]; + samplePeak = *(uint8_t*) um_data->u_data[3]; + FFT_MajorPeak = *(float*) um_data->u_data[4]; + my_magnitude = *(float*) um_data->u_data[5]; + maxVol = (uint8_t*) um_data->u_data[6]; // requires UI element (SEGMENT.customX?), changes source element + binNum = (uint8_t*) um_data->u_data[7]; // requires UI element (SEGMENT.customX?), changes source element + fftBin = (float*) um_data->u_data[8]; + } else { + // add support for no audio data + um_data = simulateSound(SEGMENT.soundSim); + } +*/ + #include "wled.h" #include "FX.h" #include "fcn_declare.h" #define IBN 5100 +// a few constants needed for AudioReactive effects +// for 22Khz sampling +#define MAX_FREQUENCY 11025 // sample frequency / 2 (as per Nyquist criterion) +#define MAX_FREQ_LOG10 4.04238f // log10(MAX_FREQUENCY) + +// for 20Khz sampling +//#define MAX_FREQUENCY 10240 +//#define MAX_FREQ_LOG10 4.0103f + +// for 10Khz sampling +//#define MAX_FREQUENCY 5120 +//#define MAX_FREQ_LOG10 3.71f + // paletteBlend: 0 - wrap when moving, 1 - always wrap, 2 - never wrap, 3 - none (undefined) #define PALETTE_SOLID_WRAP (strip.paletteBlend == 1 || strip.paletteBlend == 3) #define PALETTE_MOVING_WRAP !(strip.paletteBlend == 2 || (strip.paletteBlend == 0 && SEGMENT.speed == 0)) @@ -1375,15 +1419,17 @@ uint16_t mode_loading(void) { static const char _data_FX_MODE_LOADING[] PROGMEM = "Loading@!,Fade;!,!;!;;ix=16"; -//American Police Light with all LEDs Red and Blue -uint16_t police_base(uint32_t color1, uint32_t color2) { - if (SEGLEN == 1) return mode_static(); +//Police Lights with custom colors +uint16_t mode_two_dots() { + if (SEGLEN == 1) return mode_static(); unsigned delay = 1 + (FRAMETIME<<3) / SEGLEN; // longer segments should change faster uint32_t it = strip.now / map(SEGMENT.speed, 0, 255, delay<<4, delay); unsigned offset = it % SEGLEN; - unsigned width = ((SEGLEN*(SEGMENT.intensity+1))>>9); //max width is half the strip if (!width) width = 1; + if (!SEGMENT.check2) SEGMENT.fill(SEGCOLOR(2)); + uint32_t color1 = SEGCOLOR(0); + uint32_t color2 = (SEGCOLOR(1) == SEGCOLOR(2)) ? color1 : SEGCOLOR(1); for (unsigned i = 0; i < width; i++) { unsigned indexR = (offset + i) % SEGLEN; unsigned indexB = (offset + i + (SEGLEN>>1)) % SEGLEN; @@ -1392,23 +1438,6 @@ uint16_t police_base(uint32_t color1, uint32_t color2) { } return FRAMETIME; } - - -//Police Lights Red and Blue -//uint16_t mode_police() -//{ -// SEGMENT.fill(SEGCOLOR(1)); -// return police_base(RED, BLUE); -//} -//static const char _data_FX_MODE_POLICE[] PROGMEM = "Police@!,Width;,Bg;0"; - - -//Police Lights with custom colors -uint16_t mode_two_dots() { - if (!SEGMENT.check2) SEGMENT.fill(SEGCOLOR(2)); - uint32_t color2 = (SEGCOLOR(1) == SEGCOLOR(2)) ? SEGCOLOR(0) : SEGCOLOR(1); - return police_base(SEGCOLOR(0), color2); -} static const char _data_FX_MODE_TWO_DOTS[] PROGMEM = "Two Dots@!,Dot size,,,,,Overlay;1,2,Bg;!"; @@ -2042,7 +2071,7 @@ uint16_t mode_palette() { } return FRAMETIME; } -static const char _data_FX_MODE_PALETTE[] PROGMEM = "Palette@Shift,Size,Rotation,,,Animate Shift,Animate Rotation,Anamorphic;;!;12;c1=128,c2=128,c3=128,o1=1,o2=1,o3=0"; +static const char _data_FX_MODE_PALETTE[] PROGMEM = "Palette@Shift,Size,Rotation,,,Animate Shift,Animate Rotation,Anamorphic;;!;12;c1=128,c2=128,c3=128,o1=1,o2=0,o3=0"; // WLED limitation: Analog Clock overlay will NOT work when Fire2012 is active @@ -2351,7 +2380,7 @@ uint16_t mode_lake() { static const char _data_FX_MODE_LAKE[] PROGMEM = "Lake@!;Fx;!"; -// meteor effect +// meteor effect & meteor smooth (merged by @dedehai) // send a meteor from begining to to the end of the strip with a trail that randomly decays. // adapted from https://www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/#LEDStripEffectMeteorRain uint16_t mode_meteor() { @@ -2360,85 +2389,59 @@ uint16_t mode_meteor() { byte* trail = SEGENV.data; - const unsigned meteorSize = 1 + SEGLEN / 20; // 5% - unsigned counter = strip.now * ((SEGMENT.speed >> 2) +8); - uint16_t in = counter * SEGLEN >> 16; - - const int max = SEGMENT.palette==5 ? 239 : 255; // "* Colors only" palette blends end with start - // fade all leds to colors[1] in LEDs one step - for (int i = 0; i < SEGLEN; i++) { - if (random8() <= 255 - SEGMENT.intensity) { - int meteorTrailDecay = 128 + random8(127); - trail[i] = scale8(trail[i], meteorTrailDecay); - int index = trail[i]; - int idx = 255; - int bri = SEGMENT.palette==35 || SEGMENT.palette==36 ? 255 : trail[i]; - if (!SEGMENT.check1) { - idx = 0; - index = map(i,0,SEGLEN,0,max); - bri = trail[i]; - } - uint32_t col = SEGMENT.color_from_palette(index, false, false, idx, bri); // full brightness for Fire - SEGMENT.setPixelColor(i, col); - } - } - - // draw meteor - for (unsigned j = 0; j < meteorSize; j++) { - int index = (in + j) % SEGLEN; - int idx = 255; - int i = trail[index] = max; - if (!SEGMENT.check1) { - i = map(index,0,SEGLEN,0,max); - idx = 0; - } - uint32_t col = SEGMENT.color_from_palette(i, false, false, idx, 255); // full brightness - SEGMENT.setPixelColor(index, col); - } - - return FRAMETIME; -} -static const char _data_FX_MODE_METEOR[] PROGMEM = "Meteor@!,Trail,,,,Gradient;!;!;1"; - - -// smooth meteor effect -// send a meteor from begining to to the end of the strip with a trail that randomly decays. -// adapted from https://www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/#LEDStripEffectMeteorRain -uint16_t mode_meteor_smooth() { - if (SEGLEN == 1) return mode_static(); - if (!SEGENV.allocateData(SEGLEN)) return mode_static(); //allocation failed - - byte* trail = SEGENV.data; - const unsigned meteorSize = 1+ SEGLEN / 20; // 5% uint16_t in = map((SEGENV.step >> 6 & 0xFF), 0, 255, 0, SEGLEN -1); - const int max = SEGMENT.palette==5 || !SEGMENT.check1 ? 240 : 255; + const int max = SEGMENT.palette==5 || !SEGMENT.check1 ? 240 : 255; // fade all leds to colors[1] in LEDs one step for (unsigned i = 0; i < SEGLEN; i++) { - if (/*trail[i] != 0 &&*/ random8() <= 255 - SEGMENT.intensity) { - int change = trail[i] + 4 - random8(24); //change each time between -20 and +4 - trail[i] = constrain(change, 0, max); - uint32_t col = SEGMENT.check1 ? SEGMENT.color_from_palette(i, true, false, 0, trail[i]) : SEGMENT.color_from_palette(trail[i], false, true, 255); + uint32_t col; + if (random8() <= 255 - SEGMENT.intensity) { + if(SEGMENT.check3) { + int change = trail[i] + 4 - random8(24); //change each time between -20 and +4 + trail[i] = constrain(change, 0, max);; + col = SEGMENT.check1 ? SEGMENT.color_from_palette(i, true, false, 0, trail[i]) : SEGMENT.color_from_palette(trail[i], false, true, 255); + } + else { + trail[i] = scale8(trail[i], 128 + random8(127)); + int index = trail[i]; + int idx = 255; + int bri = SEGMENT.palette==35 || SEGMENT.palette==36 ? 255 : trail[i]; + if (!SEGMENT.check1) { + idx = 0; + index = map(i,0,SEGLEN,0,max); + bri = trail[i]; + } + col = SEGMENT.color_from_palette(index, false, false, idx, bri); // full brightness for Fire + } SEGMENT.setPixelColor(i, col); } } // draw meteor for (unsigned j = 0; j < meteorSize; j++) { - unsigned index = in + j; - if (index >= SEGLEN) { - index -= SEGLEN; + unsigned index = (in + j) % SEGLEN; + if(SEGMENT.check3) { //smooth + trail[index] = max; + uint32_t col = SEGMENT.check1 ? SEGMENT.color_from_palette(index, true, false, 0, trail[index]) : SEGMENT.color_from_palette(trail[index], false, true, 255); + SEGMENT.setPixelColor(index, col); + } + else{ + int idx = 255; + int i = trail[index] = max; + if (!SEGMENT.check1) { + i = map(index,0,SEGLEN,0,max); + idx = 0; + } + uint32_t col = SEGMENT.color_from_palette(i, false, false, idx, 255); // full brightness + SEGMENT.setPixelColor(index, col); } - trail[index] = max; - uint32_t col = SEGMENT.check1 ? SEGMENT.color_from_palette(index, true, false, 0, trail[index]) : SEGMENT.color_from_palette(trail[index], false, true, 255); - SEGMENT.setPixelColor(index, col); } SEGENV.step += SEGMENT.speed +1; return FRAMETIME; } -static const char _data_FX_MODE_METEOR_SMOOTH[] PROGMEM = "Meteor Smooth@!,Trail,,,,Gradient;;!;1"; +static const char _data_FX_MODE_METEOR[] PROGMEM = "Meteor@!,Trail,,,,Gradient,,Smooth;;!;1"; //Railway Crossing / Christmas Fairy lights @@ -2489,7 +2492,7 @@ typedef struct Ripple { #else #define MAX_RIPPLES 100 #endif -static uint16_t ripple_base() { +static uint16_t ripple_base(bool blur) { unsigned maxRipples = min(1 + (SEGLEN >> 2), MAX_RIPPLES); // 56 max for 16 segment ESP8266 unsigned dataSize = sizeof(ripple) * maxRipples; @@ -2537,7 +2540,7 @@ static uint16_t ripple_base() { } } } - + if(blur) SEGMENT.blur(SEGMENT.custom1>>1); return FRAMETIME; } #undef MAX_RIPPLES @@ -2547,9 +2550,9 @@ uint16_t mode_ripple(void) { if (SEGLEN == 1) return mode_static(); if (!SEGMENT.check2) SEGMENT.fill(SEGCOLOR(1)); else SEGMENT.fade_out(250); - return ripple_base(); + return ripple_base(true); } -static const char _data_FX_MODE_RIPPLE[] PROGMEM = "Ripple@!,Wave #,,,,,Overlay;,!;!;12"; +static const char _data_FX_MODE_RIPPLE[] PROGMEM = "Ripple@!,Wave #,Blur,,,,Overlay;,!;!;12;c1=0"; uint16_t mode_ripple_rainbow(void) { @@ -2566,7 +2569,7 @@ uint16_t mode_ripple_rainbow(void) { SEGENV.aux0--; } SEGMENT.fill(color_blend(SEGMENT.color_wheel(SEGENV.aux0),BLACK,235)); - return ripple_base(); + return ripple_base(false); } static const char _data_FX_MODE_RIPPLE_RAINBOW[] PROGMEM = "Ripple Rainbow@!,Wave #;;!;12"; @@ -4954,11 +4957,11 @@ uint16_t mode_2DColoredBursts() { // By: ldirko https://editor.so SEGMENT.setPixelColorXY(y1, y2, DARKSLATEGRAY); } } - if (SEGMENT.custom3) SEGMENT.blur(SEGMENT.custom3/2); + SEGMENT.blur(SEGMENT.custom3<<1, SEGMENT.check2); return FRAMETIME; } // mode_2DColoredBursts() -static const char _data_FX_MODE_2DCOLOREDBURSTS[] PROGMEM = "Colored Bursts@Speed,# of lines,,,Blur,Gradient,,Dots;;!;2;c3=16"; +static const char _data_FX_MODE_2DCOLOREDBURSTS[] PROGMEM = "Colored Bursts@Speed,# of lines,,,Blur,Gradient,Smear,Dots;;!;2;c3=16"; ///////////////////// @@ -4971,16 +4974,16 @@ uint16_t mode_2Ddna(void) { // dna originally by by ldirko at https://pa const int rows = SEGMENT.virtualHeight(); SEGMENT.fadeToBlackBy(64); + SEGMENT.blur(SEGMENT.intensity>>1, SEGMENT.check1); for (int i = 0; i < cols; i++) { SEGMENT.setPixelColorXY(i, beatsin8(SEGMENT.speed/8, 0, rows-1, 0, i*4 ), ColorFromPalette(SEGPALETTE, i*5+strip.now/17, beatsin8(5, 55, 255, 0, i*10), LINEARBLEND)); SEGMENT.setPixelColorXY(i, beatsin8(SEGMENT.speed/8, 0, rows-1, 0, i*4+128), ColorFromPalette(SEGPALETTE, i*5+128+strip.now/17, beatsin8(5, 55, 255, 0, i*10+128), LINEARBLEND)); } - SEGMENT.blur(SEGMENT.intensity>>3); + return FRAMETIME; } // mode_2Ddna() -static const char _data_FX_MODE_2DDNA[] PROGMEM = "DNA@Scroll speed,Blur;;!;2"; - +static const char _data_FX_MODE_2DDNA[] PROGMEM = "DNA@Scroll speed,Blur,,,,Smear;;!;2;ix=0"; ///////////////////////// // 2D DNA Spiral // @@ -5021,10 +5024,11 @@ uint16_t mode_2DDNASpiral() { // By: ldirko https://editor.soulma SEGMENT.setPixelColorXY(x1, i, WHITE); } } + SEGMENT.blur(SEGMENT.custom1 >> (!SEGMENT.check1), SEGMENT.check1); return FRAMETIME; } // mode_2DDNASpiral() -static const char _data_FX_MODE_2DDNASPIRAL[] PROGMEM = "DNA Spiral@Scroll speed,Y frequency;;!;2"; +static const char _data_FX_MODE_2DDNASPIRAL[] PROGMEM = "DNA Spiral@Scroll speed,Y frequency,Blur,,,Smear;;!;2;c1=0"; ///////////////////////// @@ -5048,13 +5052,13 @@ uint16_t mode_2DDrift() { // By: Stepko https://editor.soulmateli int mySin = sin_t(angle) * i; int myCos = cos_t(angle) * i; SEGMENT.setPixelColorXY(colsCenter + mySin, rowsCenter + myCos, ColorFromPalette(SEGPALETTE, (i * 20) + t_20, 255, LINEARBLEND)); - if (SEGMENT.check1) SEGMENT.setPixelColorXY(colsCenter + myCos, rowsCenter + mySin, ColorFromPalette(SEGPALETTE, (i * 20) + t_20, 255, LINEARBLEND)); + if (SEGMENT.check2) SEGMENT.setPixelColorXY(colsCenter + myCos, rowsCenter + mySin, ColorFromPalette(SEGPALETTE, (i * 20) + t_20, 255, LINEARBLEND)); } - SEGMENT.blur(SEGMENT.intensity>>3); + SEGMENT.blur(SEGMENT.intensity>>(!SEGMENT.check1), SEGMENT.check1); return FRAMETIME; } // mode_2DDrift() -static const char _data_FX_MODE_2DDRIFT[] PROGMEM = "Drift@Rotation speed,Blur amount,,,,Twin;;!;2"; +static const char _data_FX_MODE_2DDRIFT[] PROGMEM = "Drift@Rotation speed,Blur amount,,,,Smear,Twin;;!;2;ix=0"; ////////////////////////// @@ -5100,17 +5104,17 @@ uint16_t mode_2DFrizzles(void) { // By: Stepko https://editor.so const int cols = SEGMENT.virtualWidth(); const int rows = SEGMENT.virtualHeight(); - SEGMENT.fadeToBlackBy(16); + SEGMENT.fadeToBlackBy(18); + SEGMENT.blur(SEGMENT.custom1 >> (2 + SEGMENT.check1), SEGMENT.check1); for (size_t i = 8; i > 0; i--) { SEGMENT.addPixelColorXY(beatsin8(SEGMENT.speed/8 + i, 0, cols - 1), beatsin8(SEGMENT.intensity/8 - i, 0, rows - 1), ColorFromPalette(SEGPALETTE, beatsin8(12, 0, 255), 255, LINEARBLEND)); } - SEGMENT.blur(SEGMENT.custom1>>3); return FRAMETIME; } // mode_2DFrizzles() -static const char _data_FX_MODE_2DFRIZZLES[] PROGMEM = "Frizzles@X frequency,Y frequency,Blur;;!;2"; +static const char _data_FX_MODE_2DFRIZZLES[] PROGMEM = "Frizzles@X frequency,Y frequency,Blur,,,Smear;;!;2"; /////////////////////////////////////////// @@ -5384,10 +5388,11 @@ uint16_t mode_2DLissajous(void) { // By: Andrew Tuline ylocn = (rows < 2) ? 1 : (map(2*ylocn, 0,511, 0,2*(rows-1)) +1) /2; // "rows > 1" is needed to avoid div/0 in map() SEGMENT.setPixelColorXY((uint8_t)xlocn, (uint8_t)ylocn, SEGMENT.color_from_palette(strip.now/100+i, false, PALETTE_SOLID_WRAP, 0)); } + SEGMENT.blur(SEGMENT.custom1>>1); return FRAMETIME; } // mode_2DLissajous() -static const char _data_FX_MODE_2DLISSAJOUS[] PROGMEM = "Lissajous@X frequency,Fade rate,,,Speed;!;!;2;c3=15"; +static const char _data_FX_MODE_2DLISSAJOUS[] PROGMEM = "Lissajous@X frequency,Fade rate,Blur,,Speed;!;!;2;c1=0"; /////////////////////// @@ -5572,7 +5577,7 @@ uint16_t mode_2DPlasmaball(void) { // By: Stepko https://edito (rows - 1 - cy == 0)) ? ColorFromPalette(SEGPALETTE, beat8(5), thisVal, LINEARBLEND) : CRGB::Black); } } - SEGMENT.blur(SEGMENT.custom2>>5); + SEGMENT.blur(SEGMENT.custom2>>2); return FRAMETIME; } // mode_2DPlasmaball() @@ -5582,16 +5587,14 @@ static const char _data_FX_MODE_2DPLASMABALL[] PROGMEM = "Plasma Ball@Speed,,Fad //////////////////////////////// // 2D Polar Lights // //////////////////////////////// -//static float fmap(const float x, const float in_min, const float in_max, const float out_min, const float out_max) { -// return (out_max - out_min) * (x - in_min) / (in_max - in_min) + out_min; -//} -uint16_t mode_2DPolarLights(void) { // By: Kostyantyn Matviyevskyy https://editor.soulmatelights.com/gallery/762-polar-lights , Modified by: Andrew Tuline + +uint16_t mode_2DPolarLights(void) { // By: Kostyantyn Matviyevskyy https://editor.soulmatelights.com/gallery/762-polar-lights , Modified by: Andrew Tuline & @dedehai (palette support) if (!strip.isMatrix || !SEGMENT.is2D()) return mode_static(); // not a 2D set-up const int cols = SEGMENT.virtualWidth(); const int rows = SEGMENT.virtualHeight(); - CRGBPalette16 auroraPalette = {0x000000, 0x003300, 0x006600, 0x009900, 0x00cc00, 0x00ff00, 0x33ff00, 0x66ff00, 0x99ff00, 0xccff00, 0xffff00, 0xffcc00, 0xff9900, 0xff6600, 0xff3300, 0xff0000}; + // CRGBPalette16 auroraPalette = {0x000000, 0x003300, 0x006600, 0x009900, 0x00cc00, 0x00ff00, 0x33ff00, 0x66ff00, 0x99ff00, 0xccff00, 0xffff00, 0xffcc00, 0xff9900, 0xff6600, 0xff3300, 0xff0000}; if (SEGENV.call == 0) { SEGMENT.fill(BLACK); @@ -5600,37 +5603,22 @@ uint16_t mode_2DPolarLights(void) { // By: Kostyantyn Matviyevskyy https float adjustHeight = (float)map(rows, 8, 32, 28, 12); // maybe use mapf() ??? unsigned adjScale = map(cols, 8, 64, 310, 63); -/* - if (SEGENV.aux1 != SEGMENT.custom1/12) { // Hacky palette rotation. We need that black. - SEGENV.aux1 = SEGMENT.custom1/12; - for (int i = 0; i < 16; i++) { - long ilk; - ilk = (long)currentPalette[i].r << 16; - ilk += (long)currentPalette[i].g << 8; - ilk += (long)currentPalette[i].b; - ilk = (ilk << SEGENV.aux1) | (ilk >> (24 - SEGENV.aux1)); - currentPalette[i].r = ilk >> 16; - currentPalette[i].g = ilk >> 8; - currentPalette[i].b = ilk; - } - } -*/ unsigned _scale = map(SEGMENT.intensity, 0, 255, 30, adjScale); int _speed = map(SEGMENT.speed, 0, 255, 128, 16); for (int x = 0; x < cols; x++) { for (int y = 0; y < rows; y++) { SEGENV.step++; - SEGMENT.setPixelColorXY(x, y, ColorFromPalette(auroraPalette, - qsub8( - inoise8((SEGENV.step%2) + x * _scale, y * 16 + SEGENV.step % 16, SEGENV.step / _speed), - fabsf((float)rows / 2.0f - (float)y) * adjustHeight))); + uint8_t palindex = qsub8(inoise8((SEGENV.step%2) + x * _scale, y * 16 + SEGENV.step % 16, SEGENV.step / _speed), fabsf((float)rows / 2.0f - (float)y) * adjustHeight); + uint8_t palbrightness = palindex; + if(SEGMENT.check1) palindex = 255 - palindex; //flip palette + SEGMENT.setPixelColorXY(x, y, ColorFromPalette(SEGPALETTE,palindex,palbrightness)); } } return FRAMETIME; } // mode_2DPolarLights() -static const char _data_FX_MODE_2DPOLARLIGHTS[] PROGMEM = "Polar Lights@!,Scale;;;2"; +static const char _data_FX_MODE_2DPOLARLIGHTS[] PROGMEM = "Polar Lights@!,Scale,,,,Flip Palette;;!;2;pal=50"; ///////////////////////// @@ -5677,11 +5665,11 @@ uint16_t mode_2DSindots(void) { // By: ldirko http int y = sin8(t2 + i * SEGMENT.intensity/8)*(rows-1)/255; // max index now 255x15/255=15! SEGMENT.setPixelColorXY(x, y, ColorFromPalette(SEGPALETTE, i * 255 / 13, 255, LINEARBLEND)); } - SEGMENT.blur(SEGMENT.custom2>>3); + SEGMENT.blur(SEGMENT.custom2>>1); return FRAMETIME; } // mode_2DSindots() -static const char _data_FX_MODE_2DSINDOTS[] PROGMEM = "Sindots@!,Dot distance,Fade rate,Blur;;!;2"; +static const char _data_FX_MODE_2DSINDOTS[] PROGMEM = "Sindots@!,Dot distance,Fade rate,Blur;;!;2;c2=64"; ////////////////////////////// @@ -5840,17 +5828,17 @@ uint16_t mode_2Dspaceships(void) { //// Space ships by stepko (c)05.02.21 [ht SEGMENT.addPixelColorXY(x, y-1, color); } } - SEGMENT.blur(SEGMENT.intensity>>3); + SEGMENT.blur(SEGMENT.intensity>>2, SEGMENT.check1); return FRAMETIME; } -static const char _data_FX_MODE_2DSPACESHIPS[] PROGMEM = "Spaceships@!,Blur;;!;2"; +static const char _data_FX_MODE_2DSPACESHIPS[] PROGMEM = "Spaceships@!,Blur,,,,Smear;;!;2"; ///////////////////////// // 2D Crazy Bees // ///////////////////////// -//// Crazy bees by stepko (c)12.02.21 [https://editor.soulmatelights.com/gallery/651-crazy-bees], adapted by Blaz Kristan (AKA blazoncek) +//// Crazy bees by stepko (c)12.02.21 [https://editor.soulmatelights.com/gallery/651-crazy-bees], adapted by Blaz Kristan (AKA blazoncek), improved by @dedehai #define MAX_BEES 5 uint16_t mode_2Dcrazybees(void) { if (!strip.isMatrix || !SEGMENT.is2D()) return mode_static(); // not a 2D set-up @@ -5890,14 +5878,14 @@ uint16_t mode_2Dcrazybees(void) { if (strip.now > SEGENV.step) { SEGENV.step = strip.now + (FRAMETIME * 16 / ((SEGMENT.speed>>4)+1)); - - SEGMENT.fadeToBlackBy(32); - + SEGMENT.fadeToBlackBy(32 + ((SEGMENT.check1*SEGMENT.intensity) >> 2)); + SEGMENT.blur(SEGMENT.intensity >> 1, SEGMENT.check1); for (size_t i = 0; i < n; i++) { - SEGMENT.addPixelColorXY(bee[i].aimX + 1, bee[i].aimY, CHSV(bee[i].hue, 255, 255)); - SEGMENT.addPixelColorXY(bee[i].aimX, bee[i].aimY + 1, CHSV(bee[i].hue, 255, 255)); - SEGMENT.addPixelColorXY(bee[i].aimX - 1, bee[i].aimY, CHSV(bee[i].hue, 255, 255)); - SEGMENT.addPixelColorXY(bee[i].aimX, bee[i].aimY - 1, CHSV(bee[i].hue, 255, 255)); + CRGB flowerCcolor = ColorFromPalette(SEGPALETTE,bee[i].hue); + SEGMENT.addPixelColorXY(bee[i].aimX + 1, bee[i].aimY, flowerCcolor); + SEGMENT.addPixelColorXY(bee[i].aimX, bee[i].aimY + 1, flowerCcolor); + SEGMENT.addPixelColorXY(bee[i].aimX - 1, bee[i].aimY, flowerCcolor); + SEGMENT.addPixelColorXY(bee[i].aimX, bee[i].aimY - 1, flowerCcolor); if (bee[i].posX != bee[i].aimX || bee[i].posY != bee[i].aimY) { SEGMENT.setPixelColorXY(bee[i].posX, bee[i].posY, CRGB(CHSV(bee[i].hue, 60, 255))); int error2 = bee[i].error * 2; @@ -5913,13 +5901,13 @@ uint16_t mode_2Dcrazybees(void) { bee[i].aimed(cols, rows); } } - SEGMENT.blur(SEGMENT.intensity>>4); } return FRAMETIME; } -static const char _data_FX_MODE_2DCRAZYBEES[] PROGMEM = "Crazy Bees@!,Blur;;;2"; +static const char _data_FX_MODE_2DCRAZYBEES[] PROGMEM = "Crazy Bees@!,Blur,,,,Smear;;!;2;pal=11,ix=0"; #undef MAX_BEES + ///////////////////////// // 2D Ghost Rider // ///////////////////////// @@ -6213,7 +6201,7 @@ static const char _data_FX_MODE_2DSCROLLTEXT[] PROGMEM = "Scrolling Text@!,Y Off //////////////////////////// // 2D Drift Rose // //////////////////////////// -//// Drift Rose by stepko (c)2021 [https://editor.soulmatelights.com/gallery/1369-drift-rose-pattern], adapted by Blaz Kristan (AKA blazoncek) +//// Drift Rose by stepko (c)2021 [https://editor.soulmatelights.com/gallery/1369-drift-rose-pattern], adapted by Blaz Kristan (AKA blazoncek) improved by @dedehai uint16_t mode_2Ddriftrose(void) { if (!strip.isMatrix || !SEGMENT.is2D()) return mode_static(); // not a 2D set-up @@ -6229,13 +6217,13 @@ uint16_t mode_2Ddriftrose(void) { float angle = radians(i * 10); uint32_t x = (CX + (sin_t(angle) * (beatsin8(i, 0, L*2)-L))) * 255.f; uint32_t y = (CY + (cos_t(angle) * (beatsin8(i, 0, L*2)-L))) * 255.f; - SEGMENT.wu_pixel(x, y, CHSV(i * 10, 255, 255)); + SEGMENT.wu_pixel(x, y, ColorFromPalette(SEGPALETTE, i * 10)); } - SEGMENT.blur(SEGMENT.intensity>>4); + SEGMENT.blur(SEGMENT.intensity >> (2 + SEGMENT.check1), SEGMENT.check1); return FRAMETIME; } -static const char _data_FX_MODE_2DDRIFTROSE[] PROGMEM = "Drift Rose@Fade,Blur;;;2"; +static const char _data_FX_MODE_2DDRIFTROSE[] PROGMEM = "Drift Rose@Fade,Blur,,,,Smear;;!;2;pal=11,ix=0"; ///////////////////////////// // 2D PLASMA ROTOZOOMER // @@ -6290,46 +6278,6 @@ static const char _data_FX_MODE_2DPLASMAROTOZOOM[] PROGMEM = "Rotozoomer@!,Scale /////////////////////////////////////////////////////////////////////////////// -/* use the following code to pass AudioReactive usermod variables to effect - - uint8_t *binNum = (uint8_t*)&SEGENV.aux1, *maxVol = (uint8_t*)(&SEGENV.aux1+1); // just in case assignment - bool samplePeak = false; - float FFT_MajorPeak = 1.0; - uint8_t *fftResult = nullptr; - float *fftBin = nullptr; - um_data_t *um_data; - if (usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - volumeSmth = *(float*) um_data->u_data[0]; - volumeRaw = *(float*) um_data->u_data[1]; - fftResult = (uint8_t*) um_data->u_data[2]; - samplePeak = *(uint8_t*) um_data->u_data[3]; - FFT_MajorPeak = *(float*) um_data->u_data[4]; - my_magnitude = *(float*) um_data->u_data[5]; - maxVol = (uint8_t*) um_data->u_data[6]; // requires UI element (SEGMENT.customX?), changes source element - binNum = (uint8_t*) um_data->u_data[7]; // requires UI element (SEGMENT.customX?), changes source element - fftBin = (float*) um_data->u_data[8]; - } else { - // add support for no audio data - um_data = simulateSound(SEGMENT.soundSim); - } -*/ - - -// a few constants needed for AudioReactive effects - -// for 22Khz sampling -#define MAX_FREQUENCY 11025 // sample frequency / 2 (as per Nyquist criterion) -#define MAX_FREQ_LOG10 4.04238f // log10(MAX_FREQUENCY) - -// for 20Khz sampling -//#define MAX_FREQUENCY 10240 -//#define MAX_FREQ_LOG10 4.0103f - -// for 10Khz sampling -//#define MAX_FREQUENCY 5120 -//#define MAX_FREQ_LOG10 3.71f - - ///////////////////////////////// // * Ripple Peak // ///////////////////////////////// @@ -6497,7 +6445,10 @@ typedef struct Gravity { /////////////////////// // * GRAVCENTER // /////////////////////// -uint16_t mode_gravcenter(void) { // Gravcenter. By Andrew Tuline. +// Gravcenter effects By Andrew Tuline. +// Gravcenter base function for Gravcenter (0), Gravcentric (1), Gravimeter (2), Gravfreq (3) (merged by @dedehai) + +uint16_t mode_gravcenter_base(unsigned mode) { if (SEGLEN == 1) return mode_static(); const unsigned dataSize = sizeof(gravity); @@ -6506,84 +6457,91 @@ uint16_t mode_gravcenter(void) { // Gravcenter. By Andrew Tuline. um_data_t *um_data = getAudioData(); float volumeSmth = *(float*) um_data->u_data[0]; - - //SEGMENT.fade_out(240); - SEGMENT.fade_out(251); // 30% - + float FFT_MajorPeak = *(float*)um_data->u_data[4]; // used in mode 3: Gravfreq + if (FFT_MajorPeak < 1) FFT_MajorPeak = 1; + + if(mode == 1) SEGMENT.fade_out(253); // //Gravcentric + else if(mode == 2) SEGMENT.fade_out(249); // Gravimeter + else if(mode == 3) SEGMENT.fade_out(250); // Gravfreq + else SEGMENT.fade_out(251); // Gravcenter + float mySampleAvg; + int tempsamp; float segmentSampleAvg = volumeSmth * (float)SEGMENT.intensity / 255.0f; - segmentSampleAvg *= 0.125; // divide by 8, to compensate for later "sensitivity" upscaling - - float mySampleAvg = mapf(segmentSampleAvg*2.0, 0, 32, 0, (float)SEGLEN/2.0f); // map to pixels available in current segment - int tempsamp = constrain(mySampleAvg, 0, SEGLEN/2); // Keep the sample from overflowing. + if(mode == 2) { //Gravimeter + segmentSampleAvg *= 0.25; // divide by 4, to compensate for later "sensitivity" upscaling + mySampleAvg = mapf(segmentSampleAvg*2.0, 0, 64, 0, (SEGLEN-1)); // map to pixels availeable in current segment + tempsamp = constrain(mySampleAvg,0,SEGLEN-1); // Keep the sample from overflowing. + } + else { // Gravcenter or Gravcentric or Gravfreq + segmentSampleAvg *= 0.125f; // divide by 8, to compensate for later "sensitivity" upscaling + mySampleAvg = mapf(segmentSampleAvg*2.0, 0.0f, 32.0f, 0.0f, (float)SEGLEN/2.0f); // map to pixels availeable in current segment + tempsamp = constrain(mySampleAvg, 0, SEGLEN/2); // Keep the sample from overflowing. + } uint8_t gravity = 8 - SEGMENT.speed/32; + int offset = 1; + if(mode == 2) offset = 0; // Gravimeter + if (tempsamp >= gravcen->topLED) gravcen->topLED = tempsamp-offset; + else if (gravcen->gravityCounter % gravity == 0) gravcen->topLED--; + - for (int i=0; itopLED >= 0) { + SEGMENT.setPixelColor(gravcen->topLED+SEGLEN/2, CRGB::Gray); + SEGMENT.setPixelColor(SEGLEN/2-1-gravcen->topLED, CRGB::Gray); + } } - - if (tempsamp >= gravcen->topLED) - gravcen->topLED = tempsamp-1; - else if (gravcen->gravityCounter % gravity == 0) - gravcen->topLED--; - - if (gravcen->topLED >= 0) { - SEGMENT.setPixelColor(gravcen->topLED+SEGLEN/2, SEGMENT.color_from_palette(strip.now, false, PALETTE_SOLID_WRAP, 0)); - SEGMENT.setPixelColor(SEGLEN/2-1-gravcen->topLED, SEGMENT.color_from_palette(strip.now, false, PALETTE_SOLID_WRAP, 0)); + else if(mode == 2) { //Gravimeter + for (int i=0; itopLED > 0) { + SEGMENT.setPixelColor(gravcen->topLED, SEGMENT.color_from_palette(strip.now, false, PALETTE_SOLID_WRAP, 0)); + } } + else if(mode == 3) { //Gravfreq + for (int i=0; itopLED >= 0) { + SEGMENT.setPixelColor(gravcen->topLED+SEGLEN/2, CRGB::Gray); + SEGMENT.setPixelColor(SEGLEN/2-1-gravcen->topLED, CRGB::Gray); + } + } + else { //Gravcenter + for (int i=0; itopLED >= 0) { + SEGMENT.setPixelColor(gravcen->topLED+SEGLEN/2, SEGMENT.color_from_palette(strip.now, false, PALETTE_SOLID_WRAP, 0)); + SEGMENT.setPixelColor(SEGLEN/2-1-gravcen->topLED, SEGMENT.color_from_palette(strip.now, false, PALETTE_SOLID_WRAP, 0)); + } + } gravcen->gravityCounter = (gravcen->gravityCounter + 1) % gravity; return FRAMETIME; -} // mode_gravcenter() -static const char _data_FX_MODE_GRAVCENTER[] PROGMEM = "Gravcenter@Rate of fall,Sensitivity;!,!;!;1v;ix=128,m12=2,si=0"; // Circle, Beatsin +} +uint16_t mode_gravcenter(void) { // Gravcenter. By Andrew Tuline. + return mode_gravcenter_base(0); +} +static const char _data_FX_MODE_GRAVCENTER[] PROGMEM = "Gravcenter@Rate of fall,Sensitivity;!,!;!;1v;ix=128,m12=2,si=0"; // Circle, Beatsin /////////////////////// // * GRAVCENTRIC // /////////////////////// -uint16_t mode_gravcentric(void) { // Gravcentric. By Andrew Tuline. - if (SEGLEN == 1) return mode_static(); - - unsigned dataSize = sizeof(gravity); - if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed - Gravity* gravcen = reinterpret_cast(SEGENV.data); - - um_data_t *um_data = getAudioData(); - float volumeSmth = *(float*) um_data->u_data[0]; - - // printUmData(); - - //SEGMENT.fade_out(240); - //SEGMENT.fade_out(240); // twice? really? - SEGMENT.fade_out(253); // 50% - - float segmentSampleAvg = volumeSmth * (float)SEGMENT.intensity / 255.0f; - segmentSampleAvg *= 0.125f; // divide by 8, to compensate for later "sensitivity" upscaling - - float mySampleAvg = mapf(segmentSampleAvg*2.0, 0.0f, 32.0f, 0.0f, (float)SEGLEN/2.0f); // map to pixels availeable in current segment - int tempsamp = constrain(mySampleAvg, 0, SEGLEN/2); // Keep the sample from overflowing. - uint8_t gravity = 8 - SEGMENT.speed/32; - - for (int i=0; i= gravcen->topLED) - gravcen->topLED = tempsamp-1; - else if (gravcen->gravityCounter % gravity == 0) - gravcen->topLED--; - - if (gravcen->topLED >= 0) { - SEGMENT.setPixelColor(gravcen->topLED+SEGLEN/2, CRGB::Gray); - SEGMENT.setPixelColor(SEGLEN/2-1-gravcen->topLED, CRGB::Gray); - } - gravcen->gravityCounter = (gravcen->gravityCounter + 1) % gravity; - - return FRAMETIME; -} // mode_gravcentric() +uint16_t mode_gravcentric(void) { // Gravcentric. By Andrew Tuline. + return mode_gravcenter_base(1); +} static const char _data_FX_MODE_GRAVCENTRIC[] PROGMEM = "Gravcentric@Rate of fall,Sensitivity;!,!;!;1v;ix=128,m12=3,si=0"; // Corner, Beatsin @@ -6591,43 +6549,18 @@ static const char _data_FX_MODE_GRAVCENTRIC[] PROGMEM = "Gravcentric@Rate of fal // * GRAVIMETER // /////////////////////// uint16_t mode_gravimeter(void) { // Gravmeter. By Andrew Tuline. - if (SEGLEN == 1) return mode_static(); - - unsigned dataSize = sizeof(gravity); - if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed - Gravity* gravcen = reinterpret_cast(SEGENV.data); - - um_data_t *um_data = getAudioData(); - float volumeSmth = *(float*) um_data->u_data[0]; - - //SEGMENT.fade_out(240); - SEGMENT.fade_out(249); // 25% - - float segmentSampleAvg = volumeSmth * (float)SEGMENT.intensity / 255.0; - segmentSampleAvg *= 0.25; // divide by 4, to compensate for later "sensitivity" upscaling - - float mySampleAvg = mapf(segmentSampleAvg*2.0, 0, 64, 0, (SEGLEN-1)); // map to pixels availeable in current segment - int tempsamp = constrain(mySampleAvg,0,SEGLEN-1); // Keep the sample from overflowing. - uint8_t gravity = 8 - SEGMENT.speed/32; - - for (int i=0; i= gravcen->topLED) - gravcen->topLED = tempsamp; - else if (gravcen->gravityCounter % gravity == 0) - gravcen->topLED--; + return mode_gravcenter_base(2); +} +static const char _data_FX_MODE_GRAVIMETER[] PROGMEM = "Gravimeter@Rate of fall,Sensitivity;!,!;!;1v;ix=128,m12=2,si=0"; // Circle, Beatsin - if (gravcen->topLED > 0) { - SEGMENT.setPixelColor(gravcen->topLED, SEGMENT.color_from_palette(strip.now, false, PALETTE_SOLID_WRAP, 0)); - } - gravcen->gravityCounter = (gravcen->gravityCounter + 1) % gravity; - return FRAMETIME; -} // mode_gravimeter() -static const char _data_FX_MODE_GRAVIMETER[] PROGMEM = "Gravimeter@Rate of fall,Sensitivity;!,!;!;1v;ix=128,m12=2,si=0"; // Circle, Beatsin +/////////////////////// +// ** Gravfreq // +/////////////////////// +uint16_t mode_gravfreq(void) { // Gravfreq. By Andrew Tuline. + return mode_gravcenter_base(3); +} +static const char _data_FX_MODE_GRAVFREQ[] PROGMEM = "Gravfreq@Rate of fall,Sensitivity;!,!;!;1f;ix=128,m12=0,si=0"; // Pixels, Beatsin ////////////////////// @@ -6837,72 +6770,54 @@ uint16_t mode_plasmoid(void) { // Plasmoid. By Andrew Tuline. static const char _data_FX_MODE_PLASMOID[] PROGMEM = "Plasmoid@Phase,# of pixels;!,!;!;01v;sx=128,ix=128,m12=0,si=0"; // Pixels, Beatsin -/////////////////////// -// * PUDDLEPEAK // -/////////////////////// -// Andrew's crappy peak detector. If I were 40+ years younger, I'd learn signal processing. -uint16_t mode_puddlepeak(void) { // Puddlepeak. By Andrew Tuline. +////////////////////// +// * PUDDLES // +////////////////////// +// Puddles/Puddlepeak By Andrew Tuline. Merged by @dedehai +uint16_t mode_puddles_base(bool peakdetect) { if (SEGLEN == 1) return mode_static(); - unsigned size = 0; - uint8_t fadeVal = map(SEGMENT.speed,0,255, 224, 254); - unsigned pos = random16(SEGLEN); // Set a random starting position. + uint8_t fadeVal = map(SEGMENT.speed, 0, 255, 224, 254); + unsigned pos = random16(SEGLEN); // Set a random starting position. + SEGMENT.fade_out(fadeVal); um_data_t *um_data = getAudioData(); + int volumeRaw = *(int16_t*)um_data->u_data[1]; 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]; float volumeSmth = *(float*) um_data->u_data[0]; - if (SEGENV.call == 0) { - SEGMENT.custom1 = *binNum; - SEGMENT.custom2 = *maxVol * 2; + if(peakdetect) { // puddles peak + *binNum = SEGMENT.custom1; // Select a bin. + *maxVol = SEGMENT.custom2 / 2; // Our volume comparator. + if (samplePeak == 1) { + size = volumeSmth * SEGMENT.intensity /256 /4 + 1; // Determine size of the flash based on the volume. + if (pos+size>= SEGLEN) size = SEGLEN - pos; + } } - - *binNum = SEGMENT.custom1; // Select a bin. - *maxVol = SEGMENT.custom2 / 2; // Our volume comparator. - - SEGMENT.fade_out(fadeVal); - - if (samplePeak == 1) { - size = volumeSmth * SEGMENT.intensity /256 /4 + 1; // Determine size of the flash based on the volume. - if (pos+size>= SEGLEN) size = SEGLEN - pos; + else { // puddles + if (volumeRaw > 1) { + size = volumeRaw * SEGMENT.intensity /256 /8 + 1; // Determine size of the flash based on the volume. + if (pos+size >= SEGLEN) size = SEGLEN - pos; + } } - - for (unsigned i=0; iu_data[1]; - - if (volumeRaw > 1) { - size = volumeRaw * SEGMENT.intensity /256 /8 + 1; // Determine size of the flash based on the volume. - if (pos+size >= SEGLEN) size = SEGLEN - pos; - } - - for (unsigned i=0; i(SEGENV.data); - - 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) - - SEGMENT.fade_out(250); - - float segmentSampleAvg = volumeSmth * (float)SEGMENT.intensity / 255.0f; - segmentSampleAvg *= 0.125f; // divide by 8, to compensate for later "sensitivity" upscaling - - float mySampleAvg = mapf(segmentSampleAvg*2.0f, 0,32, 0, (float)SEGLEN/2.0f); // map to pixels availeable in current segment - int tempsamp = constrain(mySampleAvg,0,SEGLEN/2); // Keep the sample from overflowing. - uint8_t gravity = 8 - SEGMENT.speed/32; - - for (int i=0; i= gravcen->topLED) - gravcen->topLED = tempsamp-1; - else if (gravcen->gravityCounter % gravity == 0) - gravcen->topLED--; - - if (gravcen->topLED >= 0) { - SEGMENT.setPixelColor(gravcen->topLED+SEGLEN/2, CRGB::Gray); - SEGMENT.setPixelColor(SEGLEN/2-1-gravcen->topLED, CRGB::Gray); - } - gravcen->gravityCounter = (gravcen->gravityCounter + 1) % gravity; - - return FRAMETIME; -} // mode_gravfreq() -static const char _data_FX_MODE_GRAVFREQ[] PROGMEM = "Gravfreq@Rate of fall,Sensitivity;!,!;!;1f;ix=128,m12=0,si=0"; // Pixels, Beatsin - - ////////////////////// // ** Noisemove // ////////////////////// @@ -7776,23 +7637,28 @@ static const char _data_FX_MODE_2DOCTOPUS[] PROGMEM = "Octopus@!,,Offset X,Offse //Waving Cell //@Stepko (https://editor.soulmatelights.com/gallery/1704-wavingcells) -// adapted for WLED by @blazoncek +// adapted for WLED by @blazoncek, improvements by @dedehai uint16_t mode_2Dwavingcell() { if (!strip.isMatrix || !SEGMENT.is2D()) return mode_static(); // not a 2D set-up const int cols = SEGMENT.virtualWidth(); const int rows = SEGMENT.virtualHeight(); - uint32_t t = strip.now/(257-SEGMENT.speed); - uint8_t aX = SEGMENT.custom1/16 + 9; - uint8_t aY = SEGMENT.custom2/16 + 1; - uint8_t aZ = SEGMENT.custom3 + 1; - for (int x = 0; x < cols; x++) for (int y = 0; y >3; + uint32_t aX = SEGMENT.custom1/16 + 9; + uint32_t aY = SEGMENT.custom2/16 + 1; + uint32_t aZ = SEGMENT.custom3 + 1; + for (int x = 0; x < cols; x++) { + for (int y = 0; y < rows; y++) { + uint32_t wave = sin8((x * aX) + sin8((((y<<8) + t) * aY)>>8)) + cos8(y * aZ); // bit shifts to increase temporal resolution + uint8_t colorIndex = wave + (t>>(8-(SEGMENT.check2*3))); + SEGMENT.setPixelColorXY(x, y, ColorFromPalette(SEGPALETTE, colorIndex)); + } + } + SEGMENT.blur(SEGMENT.intensity); return FRAMETIME; } -static const char _data_FX_MODE_2DWAVINGCELL[] PROGMEM = "Waving Cell@!,,Amplitude 1,Amplitude 2,Amplitude 3;;!;2"; +static const char _data_FX_MODE_2DWAVINGCELL[] PROGMEM = "Waving Cell@!,Blur,Amplitude 1,Amplitude 2,Amplitude 3,,Flow;;!;2;ix=0"; #endif // WLED_DISABLE_2D @@ -7913,7 +7779,7 @@ void WS2812FX::setupEffectData() { addEffect(FX_MODE_COLORTWINKLE, &mode_colortwinkle, _data_FX_MODE_COLORTWINKLE); addEffect(FX_MODE_LAKE, &mode_lake, _data_FX_MODE_LAKE); addEffect(FX_MODE_METEOR, &mode_meteor, _data_FX_MODE_METEOR); - addEffect(FX_MODE_METEOR_SMOOTH, &mode_meteor_smooth, _data_FX_MODE_METEOR_SMOOTH); + //addEffect(FX_MODE_METEOR_SMOOTH, &mode_meteor_smooth, _data_FX_MODE_METEOR_SMOOTH); // merged with mode_meteor addEffect(FX_MODE_RAILWAY, &mode_railway, _data_FX_MODE_RAILWAY); addEffect(FX_MODE_RIPPLE, &mode_ripple, _data_FX_MODE_RIPPLE); addEffect(FX_MODE_TWINKLEFOX, &mode_twinklefox, _data_FX_MODE_TWINKLEFOX); diff --git a/wled00/FX.h b/wled00/FX.h index 3c28274d60..5ddad51222 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -203,7 +203,7 @@ #define FX_MODE_COLORTWINKLE 74 #define FX_MODE_LAKE 75 #define FX_MODE_METEOR 76 -#define FX_MODE_METEOR_SMOOTH 77 +//#define FX_MODE_METEOR_SMOOTH 77 // merged with meteor #define FX_MODE_RAILWAY 78 #define FX_MODE_RIPPLE 79 #define FX_MODE_TWINKLEFOX 80 From 2db67f3c0fef886f7fc1f1c08ff751c64ff4fcb4 Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Mon, 16 Sep 2024 06:26:33 +0200 Subject: [PATCH 02/13] bugfix --- wled00/ir.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/ir.cpp b/wled00/ir.cpp index 9e19743668..0216c32be6 100644 --- a/wled00/ir.cpp +++ b/wled00/ir.cpp @@ -435,7 +435,7 @@ static void decodeIR44(uint32_t code) case IR44_DIY2 : presetFallback(2, FX_MODE_BREATH, 0); break; case IR44_DIY3 : presetFallback(3, FX_MODE_FIRE_FLICKER, 0); break; case IR44_DIY4 : presetFallback(4, FX_MODE_RAINBOW, 0); break; - case IR44_DIY5 : presetFallback(5, FX_MODE_METEOR_SMOOTH, 0); break; + case IR44_DIY5 : presetFallback(5, FX_MODE_METEOR, 0); break; case IR44_DIY6 : presetFallback(6, FX_MODE_RAIN, 0); break; case IR44_AUTO : changeEffect(FX_MODE_STATIC); break; case IR44_FLASH : changeEffect(FX_MODE_PALETTE); break; From 9e2840f02bdadc0f6d1c1aadf190684c2e372c01 Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Tue, 17 Sep 2024 07:20:43 +0200 Subject: [PATCH 03/13] Updated to not change original looks - reverted blurring to old values (where applicable) - added 'Traffic Light' palette (originally defined in Polar Lights FX) - Bugfix in Meteor: starting point was not the same before merge - made blurring in ripple_base a passing argument instead of a bool - Code cleanup --- wled00/FX.cpp | 146 +++++++++++++++++++++++----------------------- wled00/FX_fcn.cpp | 2 +- wled00/const.h | 2 +- wled00/palettes.h | 10 +++- 4 files changed, 85 insertions(+), 75 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 53ce8686cf..adb2c77ca5 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -24,14 +24,18 @@ Modified heavily for WLED */ -/* +#include "wled.h" +#include "FX.h" +#include "fcn_declare.h" + + ////////////// // DEV INFO // ////////////// +/* + information for FX metadata strings: https://kno.wled.ge/interfaces/json-api/#effect-metadata - information for FX metadata strings: https://kno.wled.ge/interfaces/json-api/#effect-metadata - - Audio Reactive: use the following code to pass usermod variables to effect + Audio Reactive: use the following code to pass usermod variables to effect uint8_t *binNum = (uint8_t*)&SEGENV.aux1, *maxVol = (uint8_t*)(&SEGENV.aux1+1); // just in case assignment bool samplePeak = false; @@ -55,31 +59,25 @@ } */ -#include "wled.h" -#include "FX.h" -#include "fcn_declare.h" #define IBN 5100 +// paletteBlend: 0 - wrap when moving, 1 - always wrap, 2 - never wrap, 3 - none (undefined) +#define PALETTE_SOLID_WRAP (strip.paletteBlend == 1 || strip.paletteBlend == 3) +#define PALETTE_MOVING_WRAP !(strip.paletteBlend == 2 || (strip.paletteBlend == 0 && SEGMENT.speed == 0)) + +#define indexToVStrip(index, stripNr) ((index) | (int((stripNr)+1)<<16)) // a few constants needed for AudioReactive effects // for 22Khz sampling #define MAX_FREQUENCY 11025 // sample frequency / 2 (as per Nyquist criterion) #define MAX_FREQ_LOG10 4.04238f // log10(MAX_FREQUENCY) - // for 20Khz sampling //#define MAX_FREQUENCY 10240 //#define MAX_FREQ_LOG10 4.0103f - // for 10Khz sampling //#define MAX_FREQUENCY 5120 //#define MAX_FREQ_LOG10 3.71f -// paletteBlend: 0 - wrap when moving, 1 - always wrap, 2 - never wrap, 3 - none (undefined) -#define PALETTE_SOLID_WRAP (strip.paletteBlend == 1 || strip.paletteBlend == 3) -#define PALETTE_MOVING_WRAP !(strip.paletteBlend == 2 || (strip.paletteBlend == 0 && SEGMENT.speed == 0)) - -#define indexToVStrip(index, stripNr) ((index) | (int((stripNr)+1)<<16)) - // effect utility functions uint8_t sin_gap(uint16_t in) { if (in & 0x100) return 0; @@ -1418,8 +1416,9 @@ uint16_t mode_loading(void) { } static const char _data_FX_MODE_LOADING[] PROGMEM = "Loading@!,Fade;!,!;!;;ix=16"; - -//Police Lights with custom colors +/* + * Two dots running + */ uint16_t mode_two_dots() { if (SEGLEN == 1) return mode_static(); unsigned delay = 1 + (FRAMETIME<<3) / SEGLEN; // longer segments should change faster @@ -1428,8 +1427,8 @@ uint16_t mode_two_dots() { unsigned width = ((SEGLEN*(SEGMENT.intensity+1))>>9); //max width is half the strip if (!width) width = 1; if (!SEGMENT.check2) SEGMENT.fill(SEGCOLOR(2)); - uint32_t color1 = SEGCOLOR(0); - uint32_t color2 = (SEGCOLOR(1) == SEGCOLOR(2)) ? color1 : SEGCOLOR(1); + const uint32_t color1 = SEGCOLOR(0); + const uint32_t color2 = (SEGCOLOR(1) == SEGCOLOR(2)) ? color1 : SEGCOLOR(1); for (unsigned i = 0; i < width; i++) { unsigned indexR = (offset + i) % SEGLEN; unsigned indexB = (offset + i + (SEGLEN>>1)) % SEGLEN; @@ -2159,7 +2158,7 @@ uint16_t mode_fire_2012() { return FRAMETIME; } -static const char _data_FX_MODE_FIRE_2012[] PROGMEM = "Fire 2012@Cooling,Spark rate,,2D Blur,Boost;;!;1;sx=64,ix=160,m12=1,c2=128"; // bars +static const char _data_FX_MODE_FIRE_2012[] PROGMEM = "Fire 2012@Cooling,Spark rate,,2D Blur,Boost;;!;1;pal=35,sx=64,ix=160,m12=1,c2=128"; // bars // ColorWavesWithPalettes by Mark Kriegsman: https://gist.github.com/kriegsman/8281905786e8b2632aeb @@ -2386,22 +2385,27 @@ static const char _data_FX_MODE_LAKE[] PROGMEM = "Lake@!;Fx;!"; uint16_t mode_meteor() { if (SEGLEN == 1) return mode_static(); if (!SEGENV.allocateData(SEGLEN)) return mode_static(); //allocation failed - + const bool meteorSmooth = SEGMENT.check3; byte* trail = SEGENV.data; - const unsigned meteorSize = 1+ SEGLEN / 20; // 5% - uint16_t in = map((SEGENV.step >> 6 & 0xFF), 0, 255, 0, SEGLEN -1); + const unsigned meteorSize = 1 + SEGLEN / 20; // 5% + uint16_t meteorstart; + if(meteorSmooth) meteorstart = map((SEGENV.step >> 6 & 0xFF), 0, 255, 0, SEGLEN -1); + else { + unsigned counter = strip.now * ((SEGMENT.speed >> 2) + 8); + meteorstart = (counter * SEGLEN) >> 16; + } - const int max = SEGMENT.palette==5 || !SEGMENT.check1 ? 240 : 255; + const int max = SEGMENT.palette==5 || !SEGMENT.check1 ? 240 : 255; // fade all leds to colors[1] in LEDs one step for (unsigned i = 0; i < SEGLEN; i++) { uint32_t col; if (random8() <= 255 - SEGMENT.intensity) { - if(SEGMENT.check3) { + if(meteorSmooth) { int change = trail[i] + 4 - random8(24); //change each time between -20 and +4 - trail[i] = constrain(change, 0, max);; + trail[i] = constrain(change, 0, max); col = SEGMENT.check1 ? SEGMENT.color_from_palette(i, true, false, 0, trail[i]) : SEGMENT.color_from_palette(trail[i], false, true, 255); - } + } else { trail[i] = scale8(trail[i], 128 + random8(127)); int index = trail[i]; @@ -2420,8 +2424,8 @@ uint16_t mode_meteor() { // draw meteor for (unsigned j = 0; j < meteorSize; j++) { - unsigned index = (in + j) % SEGLEN; - if(SEGMENT.check3) { //smooth + unsigned index = (meteorstart + j) % SEGLEN; + if(meteorSmooth) { trail[index] = max; uint32_t col = SEGMENT.check1 ? SEGMENT.color_from_palette(index, true, false, 0, trail[index]) : SEGMENT.color_from_palette(trail[index], false, true, 255); SEGMENT.setPixelColor(index, col); @@ -2492,7 +2496,7 @@ typedef struct Ripple { #else #define MAX_RIPPLES 100 #endif -static uint16_t ripple_base(bool blur) { +static uint16_t ripple_base(uint8_t blurAmount = 0) { unsigned maxRipples = min(1 + (SEGLEN >> 2), MAX_RIPPLES); // 56 max for 16 segment ESP8266 unsigned dataSize = sizeof(ripple) * maxRipples; @@ -2540,7 +2544,7 @@ static uint16_t ripple_base(bool blur) { } } } - if(blur) SEGMENT.blur(SEGMENT.custom1>>1); + SEGMENT.blur(blurAmount); return FRAMETIME; } #undef MAX_RIPPLES @@ -2550,7 +2554,7 @@ uint16_t mode_ripple(void) { if (SEGLEN == 1) return mode_static(); if (!SEGMENT.check2) SEGMENT.fill(SEGCOLOR(1)); else SEGMENT.fade_out(250); - return ripple_base(true); + return ripple_base(SEGMENT.custom1>>1); } static const char _data_FX_MODE_RIPPLE[] PROGMEM = "Ripple@!,Wave #,Blur,,,,Overlay;,!;!;12;c1=0"; @@ -2569,7 +2573,7 @@ uint16_t mode_ripple_rainbow(void) { SEGENV.aux0--; } SEGMENT.fill(color_blend(SEGMENT.color_wheel(SEGENV.aux0),BLACK,235)); - return ripple_base(false); + return ripple_base(); } static const char _data_FX_MODE_RIPPLE_RAINBOW[] PROGMEM = "Ripple Rainbow@!,Wave #;;!;12"; @@ -4957,7 +4961,7 @@ uint16_t mode_2DColoredBursts() { // By: ldirko https://editor.so SEGMENT.setPixelColorXY(y1, y2, DARKSLATEGRAY); } } - SEGMENT.blur(SEGMENT.custom3<<1, SEGMENT.check2); + SEGMENT.blur(SEGMENT.custom3>>1, SEGMENT.check2); return FRAMETIME; } // mode_2DColoredBursts() @@ -4973,13 +4977,12 @@ uint16_t mode_2Ddna(void) { // dna originally by by ldirko at https://pa const int cols = SEGMENT.virtualWidth(); const int rows = SEGMENT.virtualHeight(); - SEGMENT.fadeToBlackBy(64); - SEGMENT.blur(SEGMENT.intensity>>1, SEGMENT.check1); + SEGMENT.fadeToBlackBy(64); for (int i = 0; i < cols; i++) { SEGMENT.setPixelColorXY(i, beatsin8(SEGMENT.speed/8, 0, rows-1, 0, i*4 ), ColorFromPalette(SEGPALETTE, i*5+strip.now/17, beatsin8(5, 55, 255, 0, i*10), LINEARBLEND)); SEGMENT.setPixelColorXY(i, beatsin8(SEGMENT.speed/8, 0, rows-1, 0, i*4+128), ColorFromPalette(SEGPALETTE, i*5+128+strip.now/17, beatsin8(5, 55, 255, 0, i*10+128), LINEARBLEND)); } - + SEGMENT.blur(SEGMENT.intensity>>(3-(SEGMENT.check1 * 2)), SEGMENT.check1); return FRAMETIME; } // mode_2Ddna() @@ -5052,13 +5055,13 @@ uint16_t mode_2DDrift() { // By: Stepko https://editor.soulmateli int mySin = sin_t(angle) * i; int myCos = cos_t(angle) * i; SEGMENT.setPixelColorXY(colsCenter + mySin, rowsCenter + myCos, ColorFromPalette(SEGPALETTE, (i * 20) + t_20, 255, LINEARBLEND)); - if (SEGMENT.check2) SEGMENT.setPixelColorXY(colsCenter + myCos, rowsCenter + mySin, ColorFromPalette(SEGPALETTE, (i * 20) + t_20, 255, LINEARBLEND)); + if (SEGMENT.check1) SEGMENT.setPixelColorXY(colsCenter + myCos, rowsCenter + mySin, ColorFromPalette(SEGPALETTE, (i * 20) + t_20, 255, LINEARBLEND)); } - SEGMENT.blur(SEGMENT.intensity>>(!SEGMENT.check1), SEGMENT.check1); + SEGMENT.blur(SEGMENT.intensity>>((!SEGMENT.check2) * 3), SEGMENT.check2); return FRAMETIME; } // mode_2DDrift() -static const char _data_FX_MODE_2DDRIFT[] PROGMEM = "Drift@Rotation speed,Blur amount,,,,Smear,Twin;;!;2;ix=0"; +static const char _data_FX_MODE_2DDRIFT[] PROGMEM = "Drift@Rotation speed,Blur,,,,Twin,Smear;;!;2;ix=0"; ////////////////////////// @@ -5103,15 +5106,13 @@ uint16_t mode_2DFrizzles(void) { // By: Stepko https://editor.so const int cols = SEGMENT.virtualWidth(); const int rows = SEGMENT.virtualHeight(); - - SEGMENT.fadeToBlackBy(18); - SEGMENT.blur(SEGMENT.custom1 >> (2 + SEGMENT.check1), SEGMENT.check1); + SEGMENT.fadeToBlackBy(16); for (size_t i = 8; i > 0; i--) { SEGMENT.addPixelColorXY(beatsin8(SEGMENT.speed/8 + i, 0, cols - 1), beatsin8(SEGMENT.intensity/8 - i, 0, rows - 1), ColorFromPalette(SEGPALETTE, beatsin8(12, 0, 255), 255, LINEARBLEND)); } - + SEGMENT.blur(SEGMENT.custom1 >> 3, SEGMENT.check1); return FRAMETIME; } // mode_2DFrizzles() static const char _data_FX_MODE_2DFRIZZLES[] PROGMEM = "Frizzles@X frequency,Y frequency,Blur,,,Smear;;!;2"; @@ -5577,7 +5578,7 @@ uint16_t mode_2DPlasmaball(void) { // By: Stepko https://edito (rows - 1 - cy == 0)) ? ColorFromPalette(SEGPALETTE, beat8(5), thisVal, LINEARBLEND) : CRGB::Black); } } - SEGMENT.blur(SEGMENT.custom2>>2); + SEGMENT.blur(SEGMENT.custom2>>5); return FRAMETIME; } // mode_2DPlasmaball() @@ -5594,8 +5595,6 @@ uint16_t mode_2DPolarLights(void) { // By: Kostyantyn Matviyevskyy https const int cols = SEGMENT.virtualWidth(); const int rows = SEGMENT.virtualHeight(); - // CRGBPalette16 auroraPalette = {0x000000, 0x003300, 0x006600, 0x009900, 0x00cc00, 0x00ff00, 0x33ff00, 0x66ff00, 0x99ff00, 0xccff00, 0xffff00, 0xffcc00, 0xff9900, 0xff6600, 0xff3300, 0xff0000}; - if (SEGENV.call == 0) { SEGMENT.fill(BLACK); SEGENV.step = 0; @@ -5612,13 +5611,13 @@ uint16_t mode_2DPolarLights(void) { // By: Kostyantyn Matviyevskyy https uint8_t palindex = qsub8(inoise8((SEGENV.step%2) + x * _scale, y * 16 + SEGENV.step % 16, SEGENV.step / _speed), fabsf((float)rows / 2.0f - (float)y) * adjustHeight); uint8_t palbrightness = palindex; if(SEGMENT.check1) palindex = 255 - palindex; //flip palette - SEGMENT.setPixelColorXY(x, y, ColorFromPalette(SEGPALETTE,palindex,palbrightness)); + SEGMENT.setPixelColorXY(x, y, SEGMENT.color_from_palette(palindex, false, false, 255, palbrightness)); } } return FRAMETIME; } // mode_2DPolarLights() -static const char _data_FX_MODE_2DPOLARLIGHTS[] PROGMEM = "Polar Lights@!,Scale,,,,Flip Palette;;!;2;pal=50"; +static const char _data_FX_MODE_2DPOLARLIGHTS[] PROGMEM = "Polar Lights@!,Scale,,,,Flip Palette;;!;2;pal=71"; ///////////////////////// @@ -5665,11 +5664,11 @@ uint16_t mode_2DSindots(void) { // By: ldirko http int y = sin8(t2 + i * SEGMENT.intensity/8)*(rows-1)/255; // max index now 255x15/255=15! SEGMENT.setPixelColorXY(x, y, ColorFromPalette(SEGPALETTE, i * 255 / 13, 255, LINEARBLEND)); } - SEGMENT.blur(SEGMENT.custom2>>1); + SEGMENT.blur(SEGMENT.custom2 >> (3 - (SEGMENT.check1<<1))); return FRAMETIME; } // mode_2DSindots() -static const char _data_FX_MODE_2DSINDOTS[] PROGMEM = "Sindots@!,Dot distance,Fade rate,Blur;;!;2;c2=64"; +static const char _data_FX_MODE_2DSINDOTS[] PROGMEM = "Sindots@!,Dot distance,Fade rate,Blur,,Extra Blur;;!;2;"; ////////////////////////////// @@ -5828,7 +5827,7 @@ uint16_t mode_2Dspaceships(void) { //// Space ships by stepko (c)05.02.21 [ht SEGMENT.addPixelColorXY(x, y-1, color); } } - SEGMENT.blur(SEGMENT.intensity>>2, SEGMENT.check1); + SEGMENT.blur(SEGMENT.intensity >> (3 - SEGMENT.check1), SEGMENT.check1); return FRAMETIME; } @@ -5881,7 +5880,7 @@ uint16_t mode_2Dcrazybees(void) { SEGMENT.fadeToBlackBy(32 + ((SEGMENT.check1*SEGMENT.intensity) >> 2)); SEGMENT.blur(SEGMENT.intensity >> 1, SEGMENT.check1); for (size_t i = 0; i < n; i++) { - CRGB flowerCcolor = ColorFromPalette(SEGPALETTE,bee[i].hue); + uint32_t flowerCcolor = SEGMENT.color_from_palette(bee[i].hue, false, true, 255); SEGMENT.addPixelColorXY(bee[i].aimX + 1, bee[i].aimY, flowerCcolor); SEGMENT.addPixelColorXY(bee[i].aimX, bee[i].aimY + 1, flowerCcolor); SEGMENT.addPixelColorXY(bee[i].aimX - 1, bee[i].aimY, flowerCcolor); @@ -6217,13 +6216,14 @@ uint16_t mode_2Ddriftrose(void) { float angle = radians(i * 10); uint32_t x = (CX + (sin_t(angle) * (beatsin8(i, 0, L*2)-L))) * 255.f; uint32_t y = (CY + (cos_t(angle) * (beatsin8(i, 0, L*2)-L))) * 255.f; - SEGMENT.wu_pixel(x, y, ColorFromPalette(SEGPALETTE, i * 10)); + if(SEGMENT.palette == 0) SEGMENT.wu_pixel(x, y, CHSV(i * 10, 255, 255)); + else SEGMENT.wu_pixel(x, y, ColorFromPalette(SEGPALETTE, i * 10)); } - SEGMENT.blur(SEGMENT.intensity >> (2 + SEGMENT.check1), SEGMENT.check1); + SEGMENT.blur(SEGMENT.intensity >> (4 - SEGMENT.check1), SEGMENT.check1); return FRAMETIME; } -static const char _data_FX_MODE_2DDRIFTROSE[] PROGMEM = "Drift Rose@Fade,Blur,,,,Smear;;!;2;pal=11,ix=0"; +static const char _data_FX_MODE_2DDRIFTROSE[] PROGMEM = "Drift Rose@Fade,Blur,,,,Smear;;!;2;pal=11"; ///////////////////////////// // 2D PLASMA ROTOZOOMER // @@ -6448,7 +6448,7 @@ typedef struct Gravity { // Gravcenter effects By Andrew Tuline. // Gravcenter base function for Gravcenter (0), Gravcentric (1), Gravimeter (2), Gravfreq (3) (merged by @dedehai) -uint16_t mode_gravcenter_base(unsigned mode) { +uint16_t mode_gravcenter_base(unsigned mode) { if (SEGLEN == 1) return mode_static(); const unsigned dataSize = sizeof(gravity); @@ -6457,16 +6457,16 @@ uint16_t mode_gravcenter_base(unsigned mode) { um_data_t *um_data = getAudioData(); float volumeSmth = *(float*) um_data->u_data[0]; - float FFT_MajorPeak = *(float*)um_data->u_data[4]; // used in mode 3: Gravfreq - if (FFT_MajorPeak < 1) FFT_MajorPeak = 1; if(mode == 1) SEGMENT.fade_out(253); // //Gravcentric else if(mode == 2) SEGMENT.fade_out(249); // Gravimeter else if(mode == 3) SEGMENT.fade_out(250); // Gravfreq else SEGMENT.fade_out(251); // Gravcenter + float mySampleAvg; int tempsamp; float segmentSampleAvg = volumeSmth * (float)SEGMENT.intensity / 255.0f; + if(mode == 2) { //Gravimeter segmentSampleAvg *= 0.25; // divide by 4, to compensate for later "sensitivity" upscaling mySampleAvg = mapf(segmentSampleAvg*2.0, 0, 64, 0, (SEGLEN-1)); // map to pixels availeable in current segment @@ -6474,16 +6474,16 @@ uint16_t mode_gravcenter_base(unsigned mode) { } else { // Gravcenter or Gravcentric or Gravfreq segmentSampleAvg *= 0.125f; // divide by 8, to compensate for later "sensitivity" upscaling - mySampleAvg = mapf(segmentSampleAvg*2.0, 0.0f, 32.0f, 0.0f, (float)SEGLEN/2.0f); // map to pixels availeable in current segment + mySampleAvg = mapf(segmentSampleAvg*2.0, 0.0f, 32.0f, 0.0f, (float)SEGLEN/2.0f); // map to pixels availeable in current segment tempsamp = constrain(mySampleAvg, 0, SEGLEN/2); // Keep the sample from overflowing. } + uint8_t gravity = 8 - SEGMENT.speed/32; int offset = 1; if(mode == 2) offset = 0; // Gravimeter - if (tempsamp >= gravcen->topLED) gravcen->topLED = tempsamp-offset; + if (tempsamp >= gravcen->topLED) gravcen->topLED = tempsamp-offset; else if (gravcen->gravityCounter % gravity == 0) gravcen->topLED--; - if(mode == 1) { //Gravcentric for (int i=0; iu_data[4]; // used in mode 3: Gravfreq + if (FFT_MajorPeak < 1) FFT_MajorPeak = 1; + uint8_t index = (log10f(FFT_MajorPeak) - (MAX_FREQ_LOG10 - 1.78f)) * 255; SEGMENT.setPixelColor(i+SEGLEN/2, SEGMENT.color_from_palette(index, false, PALETTE_SOLID_WRAP, 0)); SEGMENT.setPixelColor(SEGLEN/2-i-1, SEGMENT.color_from_palette(index, false, PALETTE_SOLID_WRAP, 0)); } @@ -6529,11 +6531,11 @@ uint16_t mode_gravcenter_base(unsigned mode) { gravcen->gravityCounter = (gravcen->gravityCounter + 1) % gravity; return FRAMETIME; -} +} uint16_t mode_gravcenter(void) { // Gravcenter. By Andrew Tuline. return mode_gravcenter_base(0); -} +} static const char _data_FX_MODE_GRAVCENTER[] PROGMEM = "Gravcenter@Rate of fall,Sensitivity;!,!;!;1v;ix=128,m12=2,si=0"; // Circle, Beatsin /////////////////////// @@ -6541,7 +6543,7 @@ static const char _data_FX_MODE_GRAVCENTER[] PROGMEM = "Gravcenter@Rate of fall, /////////////////////// uint16_t mode_gravcentric(void) { // Gravcentric. By Andrew Tuline. return mode_gravcenter_base(1); -} +} static const char _data_FX_MODE_GRAVCENTRIC[] PROGMEM = "Gravcentric@Rate of fall,Sensitivity;!,!;!;1v;ix=128,m12=3,si=0"; // Corner, Beatsin @@ -6559,7 +6561,7 @@ static const char _data_FX_MODE_GRAVIMETER[] PROGMEM = "Gravimeter@Rate of fall, /////////////////////// uint16_t mode_gravfreq(void) { // Gravfreq. By Andrew Tuline. return mode_gravcenter_base(3); -} +} static const char _data_FX_MODE_GRAVFREQ[] PROGMEM = "Gravfreq@Rate of fall,Sensitivity;!,!;!;1f;ix=128,m12=0,si=0"; // Pixels, Beatsin @@ -6774,7 +6776,7 @@ static const char _data_FX_MODE_PLASMOID[] PROGMEM = "Plasmoid@Phase,# of pixels // * PUDDLES // ////////////////////// // Puddles/Puddlepeak By Andrew Tuline. Merged by @dedehai -uint16_t mode_puddles_base(bool peakdetect) { +uint16_t mode_puddles_base(bool peakdetect) { if (SEGLEN == 1) return mode_static(); unsigned size = 0; uint8_t fadeVal = map(SEGMENT.speed, 0, 255, 224, 254); @@ -6788,7 +6790,7 @@ uint16_t mode_puddles_base(bool peakdetect) { uint8_t *binNum = (uint8_t*)um_data->u_data[7]; float volumeSmth = *(float*) um_data->u_data[0]; - if(peakdetect) { // puddles peak + if(peakdetect) { // puddles peak *binNum = SEGMENT.custom1; // Select a bin. *maxVol = SEGMENT.custom2 / 2; // Our volume comparator. if (samplePeak == 1) { @@ -6796,7 +6798,7 @@ uint16_t mode_puddles_base(bool peakdetect) { if (pos+size>= SEGLEN) size = SEGLEN - pos; } } - else { // puddles + else { // puddles if (volumeRaw > 1) { size = volumeRaw * SEGMENT.intensity /256 /8 + 1; // Determine size of the flash based on the volume. if (pos+size >= SEGLEN) size = SEGLEN - pos; @@ -7779,7 +7781,7 @@ void WS2812FX::setupEffectData() { addEffect(FX_MODE_COLORTWINKLE, &mode_colortwinkle, _data_FX_MODE_COLORTWINKLE); addEffect(FX_MODE_LAKE, &mode_lake, _data_FX_MODE_LAKE); addEffect(FX_MODE_METEOR, &mode_meteor, _data_FX_MODE_METEOR); - //addEffect(FX_MODE_METEOR_SMOOTH, &mode_meteor_smooth, _data_FX_MODE_METEOR_SMOOTH); // merged with mode_meteor + //addEffect(FX_MODE_METEOR_SMOOTH, &mode_meteor_smooth, _data_FX_MODE_METEOR_SMOOTH); // merged with mode_meteor addEffect(FX_MODE_RAILWAY, &mode_railway, _data_FX_MODE_RAILWAY); addEffect(FX_MODE_RIPPLE, &mode_ripple, _data_FX_MODE_RIPPLE); addEffect(FX_MODE_TWINKLEFOX, &mode_twinklefox, _data_FX_MODE_TWINKLEFOX); diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index fe47ee5297..1fac69473e 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -1883,5 +1883,5 @@ const char JSON_palette_names[] PROGMEM = R"=====([ "Magenta","Magred","Yelmag","Yelblu","Orange & Teal","Tiamat","April Night","Orangery","C9","Sakura", "Aurora","Atlantica","C9 2","C9 New","Temperature","Aurora 2","Retro Clown","Candy","Toxy Reaf","Fairy Reaf", "Semi Blue","Pink Candy","Red Reaf","Aqua Flash","Yelblu Hot","Lite Light","Red Flash","Blink Red","Red Shift","Red Tide", -"Candy2" +"Candy2","Traffic Light" ])====="; diff --git a/wled00/const.h b/wled00/const.h index 14ec23b58a..c443aaab51 100644 --- a/wled00/const.h +++ b/wled00/const.h @@ -5,7 +5,7 @@ * Readability defines and their associated numerical values + compile-time constants */ -#define GRADIENT_PALETTE_COUNT 58 +#define GRADIENT_PALETTE_COUNT 59 // You can define custom product info from build flags. // This is useful to allow API consumer to identify what type of WLED version diff --git a/wled00/palettes.h b/wled00/palettes.h index 41dfbbc163..cb8499f20a 100644 --- a/wled00/palettes.h +++ b/wled00/palettes.h @@ -1,5 +1,6 @@ /* * Color palettes for FastLED effects (65-73). + * 4 bytes per color: index, red, green, blue */ // From ColorWavesWithPalettes by Mark Kriegsman: https://gist.github.com/kriegsman/8281905786e8b2632aeb @@ -844,6 +845,12 @@ const byte candy2_gp[] PROGMEM = { 211, 39, 33, 34, 255, 1, 1, 1}; + const byte trafficlight_gp[] PROGMEM = { + 0, 0, 0, 0, //black + 85, 0, 255, 0, //green + 170, 255, 255, 0, //yellow + 255, 255, 0, 0}; //red + // Single array of defined cpt-city color palettes. // This will let us programmatically choose one based on // a number, rather than having to activate each explicitly @@ -906,7 +913,8 @@ const byte* const gGradientPalettes[] PROGMEM = { blink_red_gp, //67-54 Blink Red red_shift_gp, //68-55 Red Shift red_tide_gp, //69-56 Red Tide - candy2_gp //70-57 Candy2 + candy2_gp, //70-57 Candy2 + trafficlight_gp //71-58 Traffic Light }; #endif From d82ad4847d01dce3635fd3d1504bf4c7e0d90611 Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Tue, 17 Sep 2024 17:27:52 +0200 Subject: [PATCH 04/13] Removed local palette from Firenoise (and fixed a bug there) uses fire palette by default, looks is 95% identical. also the /cols should be /rows or it will look different depending on matrix dimensions (brightness changes, also there are weird lines if width != height) --- wled00/FX.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index adb2c77ca5..d713c1aa8b 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -5081,15 +5081,11 @@ uint16_t mode_2Dfirenoise(void) { // firenoise2d. By Andrew Tuline unsigned yscale = SEGMENT.speed*8; unsigned indexx = 0; - CRGBPalette16 pal = SEGMENT.check1 ? SEGPALETTE : CRGBPalette16(CRGB::Black, CRGB::Black, CRGB::Black, CRGB::Black, - CRGB::Red, CRGB::Red, CRGB::Red, CRGB::DarkOrange, - CRGB::DarkOrange,CRGB::DarkOrange, CRGB::Orange, CRGB::Orange, - CRGB::Yellow, CRGB::Orange, CRGB::Yellow, CRGB::Yellow); - + CRGBPalette16 pal = SEGMENT.check1 ? SEGPALETTE : SEGMENT.loadPalette(pal, 35); for (int j=0; j < cols; j++) { for (int i=0; i < rows; i++) { indexx = inoise8(j*yscale*rows/255, i*xscale+strip.now/4); // We're moving along our Perlin map. - SEGMENT.setPixelColorXY(j, i, ColorFromPalette(pal, min(i*(indexx)>>4, 255U), i*255/cols, LINEARBLEND)); // With that value, look up the 8 bit colour palette value and assign it to the current LED. + SEGMENT.setPixelColorXY(j, i, ColorFromPalette(pal, min(i*indexx/11, 225U), i*255/rows, LINEARBLEND)); // With that value, look up the 8 bit colour palette value and assign it to the current LED. } // for i } // for j From 5a46e93e8fd1a183f5563bc7da220fb97ea9b8db Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Tue, 17 Sep 2024 17:29:27 +0200 Subject: [PATCH 05/13] smear added to sindots --- wled00/FX.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index d713c1aa8b..65adb2148c 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -5651,7 +5651,7 @@ uint16_t mode_2DSindots(void) { // By: ldirko http SEGMENT.fill(BLACK); } - SEGMENT.fadeToBlackBy(SEGMENT.custom1>>3); + SEGMENT.fadeToBlackBy((SEGMENT.custom1>>3) + (SEGMENT.check1 * (SEGMENT.custom2>>5))); byte t1 = strip.now / (257 - SEGMENT.speed); // 20; byte t2 = sin8(t1) / 4 * 2; @@ -5660,11 +5660,11 @@ uint16_t mode_2DSindots(void) { // By: ldirko http int y = sin8(t2 + i * SEGMENT.intensity/8)*(rows-1)/255; // max index now 255x15/255=15! SEGMENT.setPixelColorXY(x, y, ColorFromPalette(SEGPALETTE, i * 255 / 13, 255, LINEARBLEND)); } - SEGMENT.blur(SEGMENT.custom2 >> (3 - (SEGMENT.check1<<1))); + SEGMENT.blur(SEGMENT.custom2>>3, SEGMENT.check1); return FRAMETIME; } // mode_2DSindots() -static const char _data_FX_MODE_2DSINDOTS[] PROGMEM = "Sindots@!,Dot distance,Fade rate,Blur,,Extra Blur;;!;2;"; +static const char _data_FX_MODE_2DSINDOTS[] PROGMEM = "Sindots@!,Dot distance,Fade rate,Blur,,Smear;;!;2;"; ////////////////////////////// From 6cd500bfb4d2c79cd54d056b6524b981af960675 Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Thu, 19 Sep 2024 09:59:16 +0200 Subject: [PATCH 06/13] Added _default_palette parameter so pass FX setting to pal0 no penalty in size of `Segment` struct (if it is kept just at the place I added it, compiler does not optimize struct alignment order and just adds padding if not aligned, there it falls into a padding) --- wled00/FX.cpp | 18 +++++++++--------- wled00/FX.h | 3 ++- wled00/FX_fcn.cpp | 24 ++++++++---------------- 3 files changed, 19 insertions(+), 26 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 65adb2148c..070ce21bca 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -2204,7 +2204,7 @@ uint16_t mode_colorwaves() { return FRAMETIME; } -static const char _data_FX_MODE_COLORWAVES[] PROGMEM = "Colorwaves@!,Hue;!;!"; +static const char _data_FX_MODE_COLORWAVES[] PROGMEM = "Colorwaves@!,Hue;!;!;;pal=26"; // colored stripes pulsing at a defined Beats-Per-Minute (BPM) @@ -2251,7 +2251,7 @@ uint16_t mode_noise16_1() { return FRAMETIME; } -static const char _data_FX_MODE_NOISE16_1[] PROGMEM = "Noise 1@!;!;!"; +static const char _data_FX_MODE_NOISE16_1[] PROGMEM = "Noise 1@!;!;!;;pal=20"; uint16_t mode_noise16_2() { @@ -2269,7 +2269,7 @@ uint16_t mode_noise16_2() { return FRAMETIME; } -static const char _data_FX_MODE_NOISE16_2[] PROGMEM = "Noise 2@!;!;!"; +static const char _data_FX_MODE_NOISE16_2[] PROGMEM = "Noise 2@!;!;!;;pal=43"; uint16_t mode_noise16_3() { @@ -2290,7 +2290,7 @@ uint16_t mode_noise16_3() { return FRAMETIME; } -static const char _data_FX_MODE_NOISE16_3[] PROGMEM = "Noise 3@!;!;!"; +static const char _data_FX_MODE_NOISE16_3[] PROGMEM = "Noise 3@!;!;!;;pal=35"; //https://github.com/aykevl/ledstrip-spark/blob/master/ledstrip.ino @@ -2302,7 +2302,7 @@ uint16_t mode_noise16_4() { } return FRAMETIME; } -static const char _data_FX_MODE_NOISE16_4[] PROGMEM = "Noise 4@!;!;!"; +static const char _data_FX_MODE_NOISE16_4[] PROGMEM = "Noise 4@!;!;!;;pal=26"; //based on https://gist.github.com/kriegsman/5408ecd397744ba0393e @@ -2477,7 +2477,7 @@ uint16_t mode_railway() { SEGENV.step += FRAMETIME; return FRAMETIME; } -static const char _data_FX_MODE_RAILWAY[] PROGMEM = "Railway@!,Smoothness;1,2;!"; +static const char _data_FX_MODE_RAILWAY[] PROGMEM = "Railway@!,Smoothness;1,2;!;;pal=3"; //Water ripple @@ -3234,7 +3234,7 @@ uint16_t mode_glitter() glitter_base(SEGMENT.intensity, SEGCOLOR(2) ? SEGCOLOR(2) : ULTRAWHITE); return FRAMETIME; } -static const char _data_FX_MODE_GLITTER[] PROGMEM = "Glitter@!,!,,,,,Overlay;,,Glitter color;!;;pal=0,m12=0"; //pixels +static const char _data_FX_MODE_GLITTER[] PROGMEM = "Glitter@!,!,,,,,Overlay;,,Glitter color;!;;pal=11,m12=0"; //pixels //Solid colour background with glitter (can be replaced by Glitter) @@ -4144,7 +4144,7 @@ uint16_t mode_sunrise() { return FRAMETIME; } -static const char _data_FX_MODE_SUNRISE[] PROGMEM = "Sunrise@Time [min],Width;;!;;sx=60"; +static const char _data_FX_MODE_SUNRISE[] PROGMEM = "Sunrise@Time [min],Width;;!;;pal=35,sx=60"; /* @@ -7573,7 +7573,7 @@ uint16_t mode_2Dsoap() { return FRAMETIME; } -static const char _data_FX_MODE_2DSOAP[] PROGMEM = "Soap@!,Smoothness;;!;2"; +static const char _data_FX_MODE_2DSOAP[] PROGMEM = "Soap@!,Smoothness;;!;2;pal=11"; //Idea from https://www.youtube.com/watch?v=HsA-6KIbgto&ab_channel=GreatScott%21 diff --git a/wled00/FX.h b/wled00/FX.h index 5ddad51222..94b84cae2c 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -414,6 +414,7 @@ typedef struct Segment { uint8_t _reserved : 4; }; }; + uint8_t _default_palette; // palette number that gets assigned to pal0 uint16_t _dataLen; static uint16_t _usedSegmentData; @@ -544,7 +545,7 @@ typedef struct Segment { void setOpacity(uint8_t o); void setOption(uint8_t n, bool val); void setMode(uint8_t fx, bool loadDefaults = false); - void setPalette(uint8_t pal); + void setPalette(uint8_t pal, bool setdefault = false); uint8_t differs(Segment& b) const; void refreshLightCapabilities(); diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 1fac69473e..7ddf9367eb 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -213,24 +213,12 @@ CRGBPalette16 &Segment::loadPalette(CRGBPalette16 &targetPalette, uint8_t pal) { if (pal < 245 && pal > GRADIENT_PALETTE_COUNT+13) pal = 0; if (pal > 245 && (strip.customPalettes.size() == 0 || 255U-pal > strip.customPalettes.size()-1)) pal = 0; // TODO remove strip dependency by moving customPalettes out of strip //default palette. Differs depending on effect - if (pal == 0) switch (mode) { - case FX_MODE_FIRE_2012 : pal = 35; break; // heat palette - case FX_MODE_COLORWAVES : pal = 26; break; // landscape 33 - case FX_MODE_FILLNOISE8 : pal = 9; break; // ocean colors - case FX_MODE_NOISE16_1 : pal = 20; break; // Drywet - case FX_MODE_NOISE16_2 : pal = 43; break; // Blue cyan yellow - case FX_MODE_NOISE16_3 : pal = 35; break; // heat palette - case FX_MODE_NOISE16_4 : pal = 26; break; // landscape 33 - case FX_MODE_GLITTER : pal = 11; break; // rainbow colors - case FX_MODE_SUNRISE : pal = 35; break; // heat palette - case FX_MODE_RAILWAY : pal = 3; break; // prim + sec - case FX_MODE_2DSOAP : pal = 11; break; // rainbow colors - } + if (pal == 0) pal = _default_palette; //load default palette set in FX _data, party colors as default switch (pal) { case 0: //default palette. Exceptions for specific effects above targetPalette = PartyColors_p; break; case 1: //randomly generated palette - targetPalette = _randomPalette; //random palette is generated at intervals in handleRandomPalette() + targetPalette = _randomPalette; //random palette is generated at intervals in handleRandomPalette() break; case 2: {//primary color only CRGB prim = gamma32(colors[0]); @@ -593,14 +581,14 @@ void Segment::setMode(uint8_t fx, bool loadDefaults) { sOpt = extractModeDefaults(fx, "mi"); if (sOpt >= 0) mirror = (bool)sOpt; // NOTE: setting this option is a risky business sOpt = extractModeDefaults(fx, "rY"); if (sOpt >= 0) reverse_y = (bool)sOpt; sOpt = extractModeDefaults(fx, "mY"); if (sOpt >= 0) mirror_y = (bool)sOpt; // NOTE: setting this option is a risky business - sOpt = extractModeDefaults(fx, "pal"); if (sOpt >= 0) setPalette(sOpt); //else setPalette(0); + sOpt = extractModeDefaults(fx, "pal"); if (sOpt >= 0) setPalette(sOpt, true); //else setPalette(0); } markForReset(); stateChanged = true; // send UDP/WS broadcast } } -void Segment::setPalette(uint8_t pal) { +void Segment::setPalette(uint8_t pal, bool setdefault) { if (pal < 245 && pal > GRADIENT_PALETTE_COUNT+13) pal = 0; // built in palettes if (pal > 245 && (strip.customPalettes.size() == 0 || 255U-pal > strip.customPalettes.size()-1)) pal = 0; // custom palettes if (pal != palette) { @@ -608,6 +596,10 @@ void Segment::setPalette(uint8_t pal) { palette = pal; stateChanged = true; // send UDP/WS broadcast } + if(setdefault) { + if(pal == 0) pal = 6; //partycolors + _default_palette = pal; + } } // 2D matrix From c98679f41be152cc7e97c530a2a6c642688bf230 Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Thu, 19 Sep 2024 20:05:12 +0200 Subject: [PATCH 07/13] Gradient Palette support for scrolling text checking 'gradient' applies the selected palette as a gradient, default palette still does color gradient. --- wled00/FX.cpp | 18 +++++++++++------- wled00/FX.h | 8 ++++---- wled00/FX_2Dfcn.cpp | 3 ++- 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 070ce21bca..df14adb3a0 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -6175,17 +6175,21 @@ uint16_t mode_2Dscrollingtext(void) { } if (!SEGMENT.check2) SEGMENT.fade_out(255 - (SEGMENT.custom1>>4)); // trail + bool usePaletteGradient = false; + uint32_t col1 = SEGMENT.color_from_palette(SEGENV.aux1, false, PALETTE_SOLID_WRAP, 0); + uint32_t col2 = BLACK; + if (SEGMENT.check1) { // use gradient + if(SEGMENT.palette == 0) { // use colors for gradient + col1 = SEGCOLOR(0); + col2 = SEGCOLOR(2); + } + else usePaletteGradient = true; + } for (int i = 0; i < numberOfLetters; i++) { int xoffset = int(cols) - int(SEGENV.aux0) + rotLW*i; if (xoffset + rotLW < 0) continue; // don't draw characters off-screen - uint32_t col1 = SEGMENT.color_from_palette(SEGENV.aux1, false, PALETTE_SOLID_WRAP, 0); - uint32_t col2 = BLACK; - if (SEGMENT.check1 && SEGMENT.palette == 0) { - col1 = SEGCOLOR(0); - col2 = SEGCOLOR(2); - } - SEGMENT.drawCharacter(text[i], xoffset, yoffset, letterWidth, letterHeight, col1, col2, map(SEGMENT.custom3, 0, 31, -2, 2)); + SEGMENT.drawCharacter(text[i], xoffset, yoffset, letterWidth, letterHeight, col1, col2, map(SEGMENT.custom3, 0, 31, -2, 2), usePaletteGradient); } return FRAMETIME; diff --git a/wled00/FX.h b/wled00/FX.h index 94b84cae2c..25d9b73a38 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -650,9 +650,9 @@ typedef struct Segment { inline void fillCircle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB c, bool soft = false) { fillCircle(cx, cy, radius, RGBW32(c.r,c.g,c.b,0), soft); } void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint32_t c, bool soft = false); inline void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, CRGB c, bool soft = false) { drawLine(x0, y0, x1, y1, RGBW32(c.r,c.g,c.b,0), soft); } // automatic inline - void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color, uint32_t col2 = 0, int8_t rotate = 0); + void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color, uint32_t col2 = 0, int8_t rotate = 0, bool usePalGrad = false); inline void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, CRGB c) { drawCharacter(chr, x, y, w, h, RGBW32(c.r,c.g,c.b,0)); } // automatic inline - inline void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, CRGB c, CRGB c2, int8_t rotate = 0) { drawCharacter(chr, x, y, w, h, RGBW32(c.r,c.g,c.b,0), RGBW32(c2.r,c2.g,c2.b,0), rotate); } // automatic inline + inline void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, CRGB c, CRGB c2, int8_t rotate = 0, bool usePalGrad = false) { drawCharacter(chr, x, y, w, h, RGBW32(c.r,c.g,c.b,0), RGBW32(c2.r,c2.g,c2.b,0), rotate, usePalGrad); } // automatic inline void wu_pixel(uint32_t x, uint32_t y, CRGB c); inline void blur2d(fract8 blur_amount) { blur(blur_amount); } inline void fill_solid(CRGB c) { fill(RGBW32(c.r,c.g,c.b,0)); } @@ -688,9 +688,9 @@ typedef struct Segment { inline void fillCircle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB c, bool soft = false) {} inline void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint32_t c, bool soft = false) {} inline void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, CRGB c, bool soft = false) {} - inline void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color, uint32_t = 0, int8_t = 0) {} + inline void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color, uint32_t = 0, int8_t = 0, bool = false) {} inline void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, CRGB color) {} - inline void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, CRGB c, CRGB c2, int8_t rotate = 0) {} + inline void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, CRGB c, CRGB c2, int8_t rotate = 0, bool usePalGrad = false) {} inline void wu_pixel(uint32_t x, uint32_t y, CRGB c) {} #endif } segment; diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp index 26ec1d608a..94ea510498 100644 --- a/wled00/FX_2Dfcn.cpp +++ b/wled00/FX_2Dfcn.cpp @@ -654,7 +654,7 @@ void Segment::drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint3 // draws a raster font character on canvas // only supports: 4x6=24, 5x8=40, 5x12=60, 6x8=48 and 7x9=63 fonts ATM -void Segment::drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color, uint32_t col2, int8_t rotate) { +void Segment::drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color, uint32_t col2, int8_t rotate, bool usePalGrad) { if (!isActive()) return; // not active if (chr < 32 || chr > 126) return; // only ASCII 32-126 supported chr -= 32; // align with font table entries @@ -664,6 +664,7 @@ void Segment::drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, CRGB col = CRGB(color); CRGBPalette16 grad = CRGBPalette16(col, col2 ? CRGB(col2) : col); + if(usePalGrad) grad = SEGPALETTE; // selected palette as gradient //if (w<5 || w>6 || h!=8) return; for (int i = 0; i Date: Fri, 20 Sep 2024 21:42:56 +0200 Subject: [PATCH 08/13] bugfixes - _default_palette now always gets properly set to party colors (in that case the FX does not have a 'pal' argument and sOpt is -1) - added initialization to zero for _default_palette (reason to crash) --- wled00/FX.h | 1 + wled00/FX_fcn.cpp | 17 ++++++++++------- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/wled00/FX.h b/wled00/FX.h index 25d9b73a38..47e111ded5 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -482,6 +482,7 @@ typedef struct Segment { aux1(0), data(nullptr), _capabilities(0), + _default_palette(0), _dataLen(0), _t(nullptr) { diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 9fa3611f0f..5da919a605 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -577,7 +577,7 @@ void Segment::setMode(uint8_t fx, bool loadDefaults) { sOpt = extractModeDefaults(fx, "mi"); if (sOpt >= 0) mirror = (bool)sOpt; // NOTE: setting this option is a risky business sOpt = extractModeDefaults(fx, "rY"); if (sOpt >= 0) reverse_y = (bool)sOpt; sOpt = extractModeDefaults(fx, "mY"); if (sOpt >= 0) mirror_y = (bool)sOpt; // NOTE: setting this option is a risky business - sOpt = extractModeDefaults(fx, "pal"); if (sOpt >= 0) setPalette(sOpt, true); //else setPalette(0); + sOpt = extractModeDefaults(fx, "pal"); if (sOpt < 0) sOpt = 0; setPalette(sOpt, true); //else setPalette(0); } markForReset(); stateChanged = true; // send UDP/WS broadcast @@ -585,12 +585,15 @@ void Segment::setMode(uint8_t fx, bool loadDefaults) { } void Segment::setPalette(uint8_t pal, bool setdefault) { - if (pal < 245 && pal > GRADIENT_PALETTE_COUNT+13) pal = 0; // built in palettes - if (pal > 245 && (strip.customPalettes.size() == 0 || 255U-pal > strip.customPalettes.size()-1)) pal = 0; // custom palettes - if (pal != palette) { - if (strip.paletteFade) startTransition(strip.getTransition()); - palette = pal; - stateChanged = true; // send UDP/WS broadcast + if(pal > 0 || !setdefault) // do not change to pal 0 when FX loads + { + if (pal < 245 && pal > GRADIENT_PALETTE_COUNT+13) pal = 0; // built in palettes + if (pal > 245 && (strip.customPalettes.size() == 0 || 255U-pal > strip.customPalettes.size()-1)) pal = 0; // custom palettes + if (pal != palette) { + if (strip.paletteFade) startTransition(strip.getTransition()); + palette = pal; + stateChanged = true; // send UDP/WS broadcast + } } if(setdefault) { if(pal == 0) pal = 6; //partycolors From 123ca5b79601d111a5578bdbb7443ab0d9968858 Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Sun, 22 Sep 2024 07:23:23 +0200 Subject: [PATCH 09/13] Fix for correct _default_palette loading on existing presets - 'pal' FX option is always extracted when chaning an FX, _default_palette variable is thus always set in setMode() --- wled00/FX.h | 2 +- wled00/FX_fcn.cpp | 28 ++++++++++++---------------- 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/wled00/FX.h b/wled00/FX.h index 47e111ded5..ccb6d63ad8 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -546,7 +546,7 @@ typedef struct Segment { void setOpacity(uint8_t o); void setOption(uint8_t n, bool val); void setMode(uint8_t fx, bool loadDefaults = false); - void setPalette(uint8_t pal, bool setdefault = false); + void setPalette(uint8_t pal); uint8_t differs(Segment& b) const; void refreshLightCapabilities(); diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 5da919a605..08eb08ad50 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -560,9 +560,9 @@ void Segment::setMode(uint8_t fx, bool loadDefaults) { if (modeBlending) startTransition(strip.getTransition()); // set effect transitions #endif mode = fx; + int sOpt; // load default values from effect string if (loadDefaults) { - int sOpt; sOpt = extractModeDefaults(fx, "sx"); speed = (sOpt >= 0) ? sOpt : DEFAULT_SPEED; sOpt = extractModeDefaults(fx, "ix"); intensity = (sOpt >= 0) ? sOpt : DEFAULT_INTENSITY; sOpt = extractModeDefaults(fx, "c1"); custom1 = (sOpt >= 0) ? sOpt : DEFAULT_C1; @@ -577,27 +577,23 @@ void Segment::setMode(uint8_t fx, bool loadDefaults) { sOpt = extractModeDefaults(fx, "mi"); if (sOpt >= 0) mirror = (bool)sOpt; // NOTE: setting this option is a risky business sOpt = extractModeDefaults(fx, "rY"); if (sOpt >= 0) reverse_y = (bool)sOpt; sOpt = extractModeDefaults(fx, "mY"); if (sOpt >= 0) mirror_y = (bool)sOpt; // NOTE: setting this option is a risky business - sOpt = extractModeDefaults(fx, "pal"); if (sOpt < 0) sOpt = 0; setPalette(sOpt, true); //else setPalette(0); + sOpt = extractModeDefaults(fx, "pal"); if (sOpt >= 0) setPalette(sOpt); //else setPalette(0); } + sOpt = extractModeDefaults(fx, "pal"); // always extract 'pal' to set _default_palette + if(sOpt == 0 || sOpt == 255) sOpt = 6; // partycolors if zero or not set (=255) + _default_palette = sOpt; // _deault_palette is loaded into pal0 in loadPalette() (if selected) markForReset(); stateChanged = true; // send UDP/WS broadcast } } -void Segment::setPalette(uint8_t pal, bool setdefault) { - if(pal > 0 || !setdefault) // do not change to pal 0 when FX loads - { - if (pal < 245 && pal > GRADIENT_PALETTE_COUNT+13) pal = 0; // built in palettes - if (pal > 245 && (strip.customPalettes.size() == 0 || 255U-pal > strip.customPalettes.size()-1)) pal = 0; // custom palettes - if (pal != palette) { - if (strip.paletteFade) startTransition(strip.getTransition()); - palette = pal; - stateChanged = true; // send UDP/WS broadcast - } - } - if(setdefault) { - if(pal == 0) pal = 6; //partycolors - _default_palette = pal; +void Segment::setPalette(uint8_t pal) { + if (pal < 245 && pal > GRADIENT_PALETTE_COUNT+13) pal = 0; // built in palettes + if (pal > 245 && (strip.customPalettes.size() == 0 || 255U-pal > strip.customPalettes.size()-1)) pal = 0; // custom palettes + if (pal != palette) { + if (strip.paletteFade) startTransition(strip.getTransition()); + palette = pal; + stateChanged = true; // send UDP/WS broadcast } } From f1f947d9ffab682d8f37430e83f1a1a7dfc8e55d Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Sun, 22 Sep 2024 12:13:30 +0200 Subject: [PATCH 10/13] bugfix --- wled00/FX_fcn.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 08eb08ad50..40366b016a 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -580,7 +580,7 @@ void Segment::setMode(uint8_t fx, bool loadDefaults) { sOpt = extractModeDefaults(fx, "pal"); if (sOpt >= 0) setPalette(sOpt); //else setPalette(0); } sOpt = extractModeDefaults(fx, "pal"); // always extract 'pal' to set _default_palette - if(sOpt == 0 || sOpt == 255) sOpt = 6; // partycolors if zero or not set (=255) + if(sOpt <= 0) sOpt = 6; // partycolors if zero or not set _default_palette = sOpt; // _deault_palette is loaded into pal0 in loadPalette() (if selected) markForReset(); stateChanged = true; // send UDP/WS broadcast From b536792cb4eeab79f996a1c004d790e40d9f9be3 Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Sat, 5 Oct 2024 08:56:00 +0200 Subject: [PATCH 11/13] add blur option to Julia FX --- wled00/FX.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index c3af15d729..add6725b38 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -5356,11 +5356,12 @@ uint16_t mode_2DJulia(void) { // An animated Julia set } y += dy; } -// SEGMENT.blur(64); + if(SEGMENT.check1) + SEGMENT.blur(128, true); return FRAMETIME; } // mode_2DJulia() -static const char _data_FX_MODE_2DJULIA[] PROGMEM = "Julia@,Max iterations per pixel,X center,Y center,Area size;!;!;2;ix=24,c1=128,c2=128,c3=16"; +static const char _data_FX_MODE_2DJULIA[] PROGMEM = "Julia@,Max iterations per pixel,X center,Y center,Area size, Blur;!;!;2;ix=24,c1=128,c2=128,c3=16"; ////////////////////////////// From 6a269447f6438e53835545b51d4ce2e3ebee5b15 Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Tue, 15 Oct 2024 13:16:18 +0200 Subject: [PATCH 12/13] Fix for Octopus on ESP32 C3 Apparently the C3 can not convert negative floats to uint8_t directly, casting it into an int first fixes it. --- wled00/FX.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index add6725b38..47741131a1 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -7610,7 +7610,7 @@ uint16_t mode_2Doctopus() { const int C_Y = (rows / 2) + ((SEGMENT.custom2 - 128)*rows)/255; for (int x = 0; x < cols; x++) { for (int y = 0; y < rows; y++) { - rMap[XY(x, y)].angle = 40.7436f * atan2f((y - C_Y), (x - C_X)); // avoid 128*atan2()/PI + rMap[XY(x, y)].angle = int(40.7436f * atan2f((y - C_Y), (x - C_X))); // avoid 128*atan2()/PI rMap[XY(x, y)].radius = hypotf((x - C_X), (y - C_Y)) * mapp; //thanks Sutaburosu } } From cf4d1b669eaa0257572f7b0a1fed0359a86038f3 Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Fri, 22 Nov 2024 18:29:47 +0100 Subject: [PATCH 13/13] Changed smearing back to original code, adjusted FX and some improvements - smearing was introduced as a byproduct of my particle-system, it relies on smearing to be the way it was originally: this is in preparation of merging the particle system - adjusted the FX to accomodate the change - fixed bug in ripple FX not correctly blurring - added smearing option to Lissajous - improved blurring / smearing in crazy bees - added fade option to Squared Swirl --- wled00/FX.cpp | 35 +++++++++++++++++++---------------- wled00/FX_2Dfcn.cpp | 2 +- wled00/FX_fcn.cpp | 2 +- 3 files changed, 21 insertions(+), 18 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 47741131a1..460fd6b09d 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -2552,8 +2552,11 @@ static uint16_t ripple_base(uint8_t blurAmount = 0) { uint16_t mode_ripple(void) { if (SEGLEN == 1) return mode_static(); - if (!SEGMENT.check2) SEGMENT.fill(SEGCOLOR(1)); - else SEGMENT.fade_out(250); + if(SEGMENT.custom1 || SEGMENT.check2) // blur or overlay + SEGMENT.fade_out(250); + else + SEGMENT.fill(SEGCOLOR(1)); + return ripple_base(SEGMENT.custom1>>1); } static const char _data_FX_MODE_RIPPLE[] PROGMEM = "Ripple@!,Wave #,Blur,,,,Overlay;,!;!;12;c1=0"; @@ -4982,7 +4985,7 @@ uint16_t mode_2Ddna(void) { // dna originally by by ldirko at https://pa SEGMENT.setPixelColorXY(i, beatsin8(SEGMENT.speed/8, 0, rows-1, 0, i*4 ), ColorFromPalette(SEGPALETTE, i*5+strip.now/17, beatsin8(5, 55, 255, 0, i*10), LINEARBLEND)); SEGMENT.setPixelColorXY(i, beatsin8(SEGMENT.speed/8, 0, rows-1, 0, i*4+128), ColorFromPalette(SEGPALETTE, i*5+128+strip.now/17, beatsin8(5, 55, 255, 0, i*10+128), LINEARBLEND)); } - SEGMENT.blur(SEGMENT.intensity>>(3-(SEGMENT.check1 * 2)), SEGMENT.check1); + SEGMENT.blur(SEGMENT.intensity>>(3-SEGMENT.check1), SEGMENT.check1); return FRAMETIME; } // mode_2Ddna() @@ -5027,7 +5030,7 @@ uint16_t mode_2DDNASpiral() { // By: ldirko https://editor.soulma SEGMENT.setPixelColorXY(x1, i, WHITE); } } - SEGMENT.blur(SEGMENT.custom1 >> (!SEGMENT.check1), SEGMENT.check1); + SEGMENT.blur(SEGMENT.custom1 >> 1, SEGMENT.check1); return FRAMETIME; } // mode_2DDNASpiral() @@ -5057,7 +5060,7 @@ uint16_t mode_2DDrift() { // By: Stepko https://editor.soulmateli SEGMENT.setPixelColorXY(colsCenter + mySin, rowsCenter + myCos, ColorFromPalette(SEGPALETTE, (i * 20) + t_20, 255, LINEARBLEND)); if (SEGMENT.check1) SEGMENT.setPixelColorXY(colsCenter + myCos, rowsCenter + mySin, ColorFromPalette(SEGPALETTE, (i * 20) + t_20, 255, LINEARBLEND)); } - SEGMENT.blur(SEGMENT.intensity>>((!SEGMENT.check2) * 3), SEGMENT.check2); + SEGMENT.blur(SEGMENT.intensity>>(3 - SEGMENT.check2), SEGMENT.check2); return FRAMETIME; } // mode_2DDrift() @@ -5108,7 +5111,7 @@ uint16_t mode_2DFrizzles(void) { // By: Stepko https://editor.so beatsin8(SEGMENT.intensity/8 - i, 0, rows - 1), ColorFromPalette(SEGPALETTE, beatsin8(12, 0, 255), 255, LINEARBLEND)); } - SEGMENT.blur(SEGMENT.custom1 >> 3, SEGMENT.check1); + SEGMENT.blur(SEGMENT.custom1 >> (3 + SEGMENT.check1), SEGMENT.check1); return FRAMETIME; } // mode_2DFrizzles() static const char _data_FX_MODE_2DFRIZZLES[] PROGMEM = "Frizzles@X frequency,Y frequency,Blur,,,Smear;;!;2"; @@ -5357,7 +5360,7 @@ uint16_t mode_2DJulia(void) { // An animated Julia set y += dy; } if(SEGMENT.check1) - SEGMENT.blur(128, true); + SEGMENT.blur(100, true); return FRAMETIME; } // mode_2DJulia() @@ -5386,11 +5389,11 @@ uint16_t mode_2DLissajous(void) { // By: Andrew Tuline ylocn = (rows < 2) ? 1 : (map(2*ylocn, 0,511, 0,2*(rows-1)) +1) /2; // "rows > 1" is needed to avoid div/0 in map() SEGMENT.setPixelColorXY((uint8_t)xlocn, (uint8_t)ylocn, SEGMENT.color_from_palette(strip.now/100+i, false, PALETTE_SOLID_WRAP, 0)); } - SEGMENT.blur(SEGMENT.custom1>>1); + SEGMENT.blur(SEGMENT.custom1>> (1 + SEGMENT.check1 * 2), SEGMENT.check1); return FRAMETIME; } // mode_2DLissajous() -static const char _data_FX_MODE_2DLISSAJOUS[] PROGMEM = "Lissajous@X frequency,Fade rate,Blur,,Speed;!;!;2;c1=0"; +static const char _data_FX_MODE_2DLISSAJOUS[] PROGMEM = "Lissajous@X frequency,Fade rate,Blur,,Speed,Smear;!;!;2;c1=0"; /////////////////////// @@ -5661,7 +5664,7 @@ uint16_t mode_2DSindots(void) { // By: ldirko http int y = sin8(t2 + i * SEGMENT.intensity/8)*(rows-1)/255; // max index now 255x15/255=15! SEGMENT.setPixelColorXY(x, y, ColorFromPalette(SEGPALETTE, i * 255 / 13, 255, LINEARBLEND)); } - SEGMENT.blur(SEGMENT.custom2>>3, SEGMENT.check1); + SEGMENT.blur(SEGMENT.custom2 >> (3 + SEGMENT.check1), SEGMENT.check1); return FRAMETIME; } // mode_2DSindots() @@ -5681,7 +5684,7 @@ uint16_t mode_2Dsquaredswirl(void) { // By: Mark Kriegsman. https://g const uint8_t kBorderWidth = 2; - SEGMENT.fadeToBlackBy(24); + SEGMENT.fadeToBlackBy(1 + SEGMENT.intensity / 5); SEGMENT.blur(SEGMENT.custom3>>1); // Use two out-of-sync sine waves @@ -5698,7 +5701,7 @@ uint16_t mode_2Dsquaredswirl(void) { // By: Mark Kriegsman. https://g return FRAMETIME; } // mode_2Dsquaredswirl() -static const char _data_FX_MODE_2DSQUAREDSWIRL[] PROGMEM = "Squared Swirl@,,,,Blur;;!;2"; +static const char _data_FX_MODE_2DSQUAREDSWIRL[] PROGMEM = "Squared Swirl@,Fade,,,Blur;;!;2"; ////////////////////////////// @@ -5824,7 +5827,7 @@ uint16_t mode_2Dspaceships(void) { //// Space ships by stepko (c)05.02.21 [ht SEGMENT.addPixelColorXY(x, y-1, color); } } - SEGMENT.blur(SEGMENT.intensity >> (3 - SEGMENT.check1), SEGMENT.check1); + SEGMENT.blur(SEGMENT.intensity >> 3, SEGMENT.check1); return FRAMETIME; } @@ -5874,8 +5877,8 @@ uint16_t mode_2Dcrazybees(void) { if (strip.now > SEGENV.step) { SEGENV.step = strip.now + (FRAMETIME * 16 / ((SEGMENT.speed>>4)+1)); - SEGMENT.fadeToBlackBy(32 + ((SEGMENT.check1*SEGMENT.intensity) >> 2)); - SEGMENT.blur(SEGMENT.intensity >> 1, SEGMENT.check1); + SEGMENT.fadeToBlackBy(32 + ((SEGMENT.check1*SEGMENT.intensity) / 25)); + SEGMENT.blur(SEGMENT.intensity >> (1 + SEGMENT.check1 * 2), SEGMENT.check1); for (size_t i = 0; i < n; i++) { uint32_t flowerCcolor = SEGMENT.color_from_palette(bee[i].hue, false, true, 255); SEGMENT.addPixelColorXY(bee[i].aimX + 1, bee[i].aimY, flowerCcolor); @@ -6220,7 +6223,7 @@ uint16_t mode_2Ddriftrose(void) { if(SEGMENT.palette == 0) SEGMENT.wu_pixel(x, y, CHSV(i * 10, 255, 255)); else SEGMENT.wu_pixel(x, y, ColorFromPalette(SEGPALETTE, i * 10)); } - SEGMENT.blur(SEGMENT.intensity >> (4 - SEGMENT.check1), SEGMENT.check1); + SEGMENT.blur(SEGMENT.intensity >> 4, SEGMENT.check1); return FRAMETIME; } diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp index 94ea510498..8b9e0058bf 100644 --- a/wled00/FX_2Dfcn.cpp +++ b/wled00/FX_2Dfcn.cpp @@ -348,7 +348,7 @@ void Segment::blur2D(uint8_t blur_amount, bool smear) { const unsigned rows = virtualHeight(); const uint8_t keep = smear ? 255 : 255 - blur_amount; - const uint8_t seep = blur_amount >> (1 + smear); + const uint8_t seep = blur_amount >> 1; uint32_t lastnew; uint32_t last; for (unsigned row = 0; row < rows; row++) { diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index a7a94b4fa1..8be4652217 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -1116,7 +1116,7 @@ void Segment::blur(uint8_t blur_amount, bool smear) { } #endif uint8_t keep = smear ? 255 : 255 - blur_amount; - uint8_t seep = blur_amount >> (1 + smear); + uint8_t seep = blur_amount >> 1; unsigned vlength = virtualLength(); uint32_t carryover = BLACK; uint32_t lastnew;