From a56d888f8d7c3e7253fb1427dff9ad12039410f0 Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Wed, 20 Mar 2024 19:39:26 +0100 Subject: [PATCH] added rotating GEQ, work in progress -animation works but sliders are too sensitive. need to adjust the ranges --- wled00/FX.cpp | 141 +++++++++++++++++++++++++++++++++++++++++++++++++- wled00/FX.h | 3 +- 2 files changed, 142 insertions(+), 2 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index f881fcf60f..a3ecd2c229 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -9377,7 +9377,7 @@ uint16_t mode_particleGEQ(void) for (bin = 0; bin < 16; bin++) { uint32_t xposition = binwidth*bin + (binwidth>>1); // emit position according to frequency band - uint8_t emitspeed = 5+((uint32_t)fftResult[bin]*(uint32_t)SEGMENT.speed)>>9; // emit speed according to loudness of band + uint8_t emitspeed = 5 + (((uint32_t)fftResult[bin]*(uint32_t)SEGMENT.speed)>>9); // emit speed according to loudness of band emitparticles = 0; if (fftResult[bin] > threshold) @@ -9432,6 +9432,144 @@ uint16_t mode_particleGEQ(void) } static const char _data_FX_MODE_PARTICLEGEQ[] PROGMEM = "Particle GEQ@Speed,Intensity,Randomness,Collision hardness,Gravity,Wrap X,Side bounce,Ground bounce;;!;012;pal=54,sx=100,ix=200,c1=0,c2=0,c3=0,o1=0,o2=0,o3=0"; +/* + * Particle rotating spray + * Particles sprayed from center with a rotating spray + * Uses palette for particle color + * by DedeHai (Damian Schneider) + */ + +uint16_t mode_particlecenterGEQ(void) +{ + + if (SEGLEN == 1) + return mode_static(); + + const uint16_t cols = strip.isMatrix ? SEGMENT.virtualWidth() : 1; + const uint16_t rows = strip.isMatrix ? SEGMENT.virtualHeight() : SEGMENT.virtualLength(); + +#ifdef ESP8266 + const uint32_t numParticles = 50; // maximum number of particles +#else + const uint32_t numParticles = 500; // maximum number of particles +#endif + + const uint8_t numSprays = 16; // maximum number of sprays + + PSparticle *particles; + PSpointsource *spray; + + // allocate memory and divide it into proper pointers, max is 32kB for all segments, 100 particles use 1200bytes + uint32_t dataSize = sizeof(PSparticle) * numParticles; + dataSize += sizeof(PSpointsource) * (numSprays); + if (!SEGENV.allocateData(dataSize)) + return mode_static(); // allocation failed; //allocation failed + + spray = reinterpret_cast(SEGENV.data); + // calculate the end of the spray data and assign it as the data pointer for the particles: + particles = reinterpret_cast(spray + numSprays); // cast the data array into a particle pointer + + uint32_t i = 0; + uint32_t j = 0; + uint8_t spraycount = 1 + (SEGMENT.custom2 >> 5); // number of sprays to display, 1-8 + + if (SEGMENT.call == 0) // initialization + { + SEGMENT.aux0 = 0; // starting angle + SEGMENT.aux1 = 0xFF; // user check + for (i = 0; i < numParticles; i++) + { + particles[i].ttl = 0; + } + for (i = 0; i < numSprays; i++) + { + spray[i].source.hue = i*16; //even color distribution + spray[i].source.sat = 255; // set saturation + spray[i].source.x = (cols * PS_P_RADIUS) / 2; // center + spray[i].source.y = (rows * PS_P_RADIUS) / 2; // center + spray[i].source.vx = 0; + spray[i].source.vy = 0; + spray[i].maxLife = 400; + spray[i].minLife = 200; + spray[i].vx = 0; // emitting speed + spray[i].vy = 0; // emitting speed + spray[i].var = 0; // emitting variation + } + } + + um_data_t *um_data; + if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) + { + // add support for no audio + um_data = simulateSound(SEGMENT.soundSim); + } + + uint8_t *fftResult = (uint8_t *)um_data->u_data[2]; // 16 bins with FFT data, log mapped already, each band contains frequency amplitude 0-255 + + i = 0; + + uint32_t threshold = 300 - SEGMENT.intensity; + + + uint8_t percycle = numSprays; // maximum number of particles emitted per cycle + i = 0; + j = random(numSprays); // start with random spray so all get a chance to emit a particle if maximum number of particles alive is reached. + if (SEGMENT.check2) + SEGMENT.aux0 += SEGMENT.custom1; + else + SEGMENT.aux0 -= SEGMENT.custom1; + + uint32_t angleoffset = SEGMENT.aux0 >> 4; + + while (i < numParticles) + { + if (particles[i].ttl == 0) // find a dead particle + { + uint8_t emitspeed = 5 + (((uint32_t)fftResult[j] * ((uint32_t)SEGMENT.speed+10)) >> 9); // emit speed according to loudness of band + uint8_t emitangle = j * 16 + random(SEGMENT.custom3 >> 1) + angleoffset; + + uint32_t emitparticles = 0; + if (fftResult[j] > threshold) + { + emitparticles = 1; // + (fftResult[bin]>>6); + } + else if (fftResult[j] > 0) // band has low volue + { + uint32_t restvolume = ((threshold - fftResult[j]) >> 2) + 2; + if (random8() % restvolume == 0) + { + emitparticles = 1; + } + } + if (emitparticles) + Emitter_Angle_emit(&spray[j], &particles[i], emitangle, emitspeed); + j = (j + 1) % numSprays; + } + i++; + //todo: could add a break if all 16 sprays have been checked, would speed it up + } + +/* + if (SEGMENT.check2) + SEGMENT.aux0 += SEGMENT.custom1 << 2; + else + SEGMENT.aux0 -= SEGMENT.custom1 << 2; +*/ //TODO: add rotation + + for (i = 0; i < numParticles; i++) + { + Particle_Move_update(&particles[i], true); // move the particles, kill out of bounds particles + } + + SEGMENT.fill(BLACK); // clear the matrix + + // render the particles + ParticleSys_render(particles, numParticles, false, false); + + return FRAMETIME; + } +static const char _data_FX_MODE_PARTICLECCIRCULARGEQ[] PROGMEM = "PS Center GEQ@Speed,Color Change,Particle Speed,Spray Count,Nozzle Size,Random Color, Direction;;!;012;pal=56,sx=0,ix=222,c1=190,c2=200,c3=0,o1=0,o2=0"; + #endif // WLED_DISABLE_2D @@ -9686,6 +9824,7 @@ void WS2812FX::setupEffectData() { addEffect(FX_MODE_PARTICLEATTRACTOR, &mode_particleattractor, _data_FX_MODE_PARTICLEATTRACTOR); addEffect(FX_MODE_PARTICLESPRAY, &mode_particlespray, _data_FX_MODE_PARTICLESPRAY); addEffect(FX_MODE_PARTICLESGEQ, &mode_particleGEQ, _data_FX_MODE_PARTICLEGEQ); + addEffect(FX_MODE_PARTICLECENTERGEQ, &mode_particlecenterGEQ, _data_FX_MODE_PARTICLECCIRCULARGEQ); #endif // WLED_DISABLE_2D diff --git a/wled00/FX.h b/wled00/FX.h index ae17b4a7ba..546d1350cb 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -330,7 +330,8 @@ #define FX_MODE_PARTICLEWATERFALL 196 #define FX_MODE_PARTICLESPRAY 197 #define FX_MODE_PARTICLESGEQ 198 -#define MODE_COUNT 199 +#define FX_MODE_PARTICLECENTERGEQ 199 +#define MODE_COUNT 200 typedef enum mapping1D2D { M12_Pixels = 0,