diff --git a/wled00/FX.cpp b/wled00/FX.cpp index ce5bdc7302..b7b61daf48 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -7589,6 +7589,8 @@ uint16_t mode_blurz(void) { // Blurz. By Andrew Tuline. um_data_t *um_data = getAudioData(); uint8_t *fftResult = (uint8_t*)um_data->u_data[2]; float volumeSmth = *(float*)um_data->u_data[0]; + float FFT_MajorPeak = *(float*)um_data->u_data[4]; + if (FFT_MajorPeak < 1) FFT_MajorPeak = 1; if (SEGENV.call == 0) { SEGMENT.setUpLeds(); // not sure if necessary @@ -7598,6 +7600,10 @@ uint16_t mode_blurz(void) { // Blurz. By Andrew Tuline. SEGENV.step = 0; // last pixel color } + #if defined(ARDUINO_ARCH_ESP32) + random16_add_entropy(esp_random() & 0xFFFF); // improves randonmess + #endif + int fadeoutDelay = (256 - SEGMENT.speed) / 24; if ((fadeoutDelay <= 1 ) || ((SEGENV.call % fadeoutDelay) == 0)) SEGMENT.fadeToBlackBy(max(SEGMENT.speed, (uint8_t)1)); @@ -7606,10 +7612,25 @@ uint16_t mode_blurz(void) { // Blurz. By Andrew Tuline. } if ((SEGENV.aux1 < SEGLEN) && (volumeSmth > 1.0f)) SEGMENT.setPixelColor(SEGENV.aux1,SEGENV.step); // "repaint" last pixel after blur + unsigned freqBand = SEGENV.aux0 % 16; uint16_t segLoc = random16(SEGLEN); + + if (SEGENV.check1) { // FreqMap mode : blob location by major frequency + int freqLocn; + unsigned maxLen = (SEGENV.check2) ? max(1, SEGLEN-16): SEGLEN; // usable segment length - leave 16 pixels when embedding "GEQ scan" + freqLocn = roundf((log10f((float)FFT_MajorPeak) - 1.78f) * float(maxLen)/(MAX_FREQ_LOG10 - 1.78f)); // log10 frequency range is from 1.78 to 3.71. Let's scale to SEGLEN. // WLEDMM proper rounding + if (freqLocn < 1) freqLocn = 0; // avoid underflow + segLoc = (SEGENV.check2) ? freqLocn + freqBand : freqLocn; + } else if (SEGENV.check2) { // GEQ Scanner mode: blob location is defined by frequency band + random offset + float bandWidth = float(SEGLEN) / 16.0f; + int bandStart = roundf(bandWidth * freqBand); + segLoc = bandStart + random16(max(1, int(bandWidth))); + } + segLoc = max(uint16_t(0), min(uint16_t(SEGLEN-1), segLoc)); // fix overflows + if (SEGLEN < 2) segLoc = 0; // WLEDMM just to be sure - unsigned pixColor = (2*fftResult[SEGENV.aux0%16]*240)/max(1, SEGLEN-1); // WLEDMM avoid uint8 overflow, and preserve pixel parameters for redraw - unsigned pixIntensity = min((unsigned)(2.0f*fftResult[SEGENV.aux0%16]), 255U); + unsigned pixColor = (2*fftResult[freqBand]*240)/max(1, SEGLEN-1); // WLEDMM avoid uint8 overflow, and preserve pixel parameters for redraw + unsigned pixIntensity = min((unsigned)(2.0f*fftResult[freqBand]), 255U); if (volumeSmth > 1.0f) { SEGMENT.setPixelColor(segLoc, color_blend(SEGCOLOR(1), SEGMENT.color_from_palette((uint16_t)pixColor, false, PALETTE_SOLID_WRAP, 0),(uint8_t)pixIntensity)); @@ -7619,12 +7640,12 @@ uint16_t mode_blurz(void) { // Blurz. By Andrew Tuline. SEGMENT.blur(max(SEGMENT.intensity, (uint8_t)1)); SEGENV.aux0 ++; SEGENV.aux0 %= 16; // make sure it doesn't cross 16 - SEGMENT.setPixelColor(segLoc, color_blend(SEGCOLOR(1), SEGMENT.color_from_palette((uint16_t)pixColor, false, PALETTE_SOLID_WRAP, 0),(uint8_t)pixIntensity)); // repaint center pixel after blur + SEGMENT.addPixelColor(segLoc, color_blend(SEGCOLOR(1), SEGMENT.color_from_palette((uint16_t)pixColor, false, PALETTE_SOLID_WRAP, 0),(uint8_t)pixIntensity/2)); // repaint center pixel after blur } else SEGMENT.blur(max(SEGMENT.intensity, (uint8_t)1)); // silence - just blur it again - return FRAMETIME_FIXED; + return SEGENV.check2 ? FRAMETIME : (3*FRAMETIME_FIXED/4); // faster updates in GEQ Scanner mode } // mode_blurz() -static const char _data_FX_MODE_BLURZ[] PROGMEM = "Blurz ☾@Fade rate,Blur;!,Color mix;!;01f;sx=48,ix=127,m12=0,si=0"; // Pixels, Beatsin +static const char _data_FX_MODE_BLURZ[] PROGMEM = "Blurz Plus ☾@Fade rate,Blur,,,,FreqMap ☾,GEQ Scanner ☾,;!,Color mix;!;01f;sx=48,ix=127,m12=7,si=0"; // Pinwheel, Beatsin #endif /////////////////////////