@@ -8551,8 +8551,7 @@ uint16_t mode_particlefall(void)
85518551 particles[i].vy = -(SEGMENT.speed >> 1 );
85528552 particles[i].hue = random8 (); // set random color
85538553 particles[i].sat = ((SEGMENT.custom3 ) << 3 ) + 7 ; // set saturation
8554- particles[i].collide = true ; // particle will collide
8555- break ; // quit loop if all particles of this round emitted
8554+ particles[i].collide = true ; // particle will collide
85568555 }
85578556 i++;
85588557 }
@@ -9316,6 +9315,119 @@ uint16_t mode_particlespray(void)
93169315}
93179316static const char _data_FX_MODE_PARTICLESPRAY[] PROGMEM = " Particle Spray@Particle Speed,Intensity,X Position,Y Position,Angle,Gravity,WrapX/Bounce,Collisions;;!;012;pal=0,sx=180,ix=200,c1=220,c2=30,c3=12,o1=1,o2=0,o3=1" ;
93189317
9318+ /*
9319+ Particle base Graphical Equalizer
9320+ Uses palette for particle color
9321+ by DedeHai (Damian Schneider)
9322+ */
9323+
9324+ uint16_t mode_particleGEQ (void )
9325+ {
9326+
9327+ if (SEGLEN == 1 )
9328+ return mode_static ();
9329+
9330+ const uint16_t cols = strip.isMatrix ? SEGMENT.virtualWidth () : 1 ;
9331+ const uint16_t rows = strip.isMatrix ? SEGMENT.virtualHeight () : SEGMENT.virtualLength ();
9332+
9333+ #ifdef ESP8266
9334+ const uint32_t numParticles = 150 ; // maximum number of particles
9335+ #else
9336+ const uint32_t numParticles = 500 ; // maximum number of particles
9337+ #endif
9338+
9339+ PSparticle *particles;
9340+
9341+ // allocate memory and divide it into proper pointers, max is 32k for all segments.
9342+ uint32_t dataSize = sizeof (PSparticle) * numParticles;
9343+ if (!SEGENV.allocateData (dataSize))
9344+ return mode_static (); // allocation failed; //allocation failed
9345+
9346+ // calculate the end of the spray data and assign it as the data pointer for the particles:
9347+ particles = reinterpret_cast <PSparticle *>(SEGENV.data ); // cast the data array into a particle pointer
9348+
9349+ if (SEGMENT.call == 0 ) // initialization
9350+ {
9351+ for (i = 0 ; i < numParticles; i++)
9352+ {
9353+ particles[i].ttl = 0 ;
9354+ particles[i].sat = 255 ; // full color
9355+ }
9356+ }
9357+
9358+ um_data_t *um_data;
9359+ if (!usermods.getUMData (&um_data, USERMOD_ID_AUDIOREACTIVE))
9360+ {
9361+ // add support for no audio
9362+ um_data = simulateSound (SEGMENT.soundSim );
9363+ }
9364+
9365+ 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
9366+
9367+ // map the bands into 16 positions on x axis, emit some particles according to frequency loudness
9368+ // Idea: emit 20 particles at full loudness, can use a shift for that, for example shift by 4 or 5
9369+ // in order to also emit particles for not so loud bands, get a bunch of particles based on frame counter and current loudness?
9370+ // implement it simply first, then add complexity... need to check what looks good
9371+ uint32_t i = 0 ;
9372+ uint32_t bin; // current bin
9373+ uint8_t binwidth = (cols * PS_P_RADIUS - 1 )>>4 ; // emit poisition variation for one bin (+/-)
9374+
9375+ for (bin = 0 ; bin < 16 ; bin++)
9376+ {
9377+ uint32_t xposition = map (fftResult[band], 0 , 255 , cols * PS_P_RADIUS - 1 ); // emit position according to frequency band
9378+ uint8_t emitspeed = fftResult[band] >> 2 ; // emit speed according to loudness of band TODO: SEGMENT.speed?
9379+ uint8_t emitparticles = 0 ;
9380+ // wie sollen die emitted werden? man könnte anzahl berechnen, dann einen emit loop machen
9381+ if (fftResult[band] > 10 )
9382+ {
9383+ emitparticles = fftResult[band]/10 ;
9384+ }
9385+ else if (fftResult[band] > 0 )// band has low volue
9386+ {
9387+ uint32_t restvolume = 12 - fftResult[band];
9388+ if (random8 () % restvolume == 0 )
9389+ {
9390+ emitparticles = 1 ;
9391+ }
9392+ }
9393+ while (i < numParticles && emitparticles) // emit particles if there are any left, low frequencies take priority
9394+ {
9395+ if (particles[i].ttl == 0 ) // find a dead particle
9396+ {
9397+ // set particle properties
9398+ particles[i].ttl = emitspeed; // set particle alive, particle lifespan is in number of frames
9399+ particles[i].x = xposition + random8 (binwidth) - binwidth>>1 ; // position randomly, deviating half a bin width
9400+ particles[i].y = 0 ; // start at the bottom
9401+ particles[i].vx = rand (9 )-4 ; // x-speed variation
9402+ particles[i].vy = emitspeed;
9403+ particles[i].hue = bin<<4 + random8 (binwidth) - binwidth>>1 ; // color from palette according to bin
9404+ // particles[i].sat = ((SEGMENT.custom3) << 3) + 7; // set saturation
9405+ }
9406+ emitparticles--;
9407+ i++;
9408+ }
9409+ }
9410+
9411+
9412+ uint8_t hardness = SEGMENT.custom2 ; // how hard the collisions are, 255 = full hard.
9413+ // detectCollisions(particles, numParticles, hardness);
9414+
9415+ // now move the particles
9416+ for (i = 0 ; i < numParticles; i++)
9417+ {
9418+ // Particle_Gravity_update(&particles[i], SEGMENT.check1, SEGMENT.check2, SEGMENT.check3, min(hardness, (uint8_t)150)); // surface hardness max is 150
9419+ Particle_Gravity_update (&particles[i], SEGMENT.check1 , SEGMENT.check2 , SEGMENT.check3 , min (hardness, (uint8_t )150 )); // surface hardness max is 150
9420+ }
9421+
9422+ SEGMENT.fill (BLACK); // clear the matrix
9423+
9424+ // render the particles
9425+ ParticleSys_render (particles, numParticles, SEGMENT.check1 , false ); // custom3 slider is saturation, from 7 to 255, 7 is close enough to white (for snow for example)
9426+
9427+ return FRAMETIME;
9428+ }
9429+ static const char _data_FX_MODE_PARTICLEGEQ[] PROGMEM = " Particle GEQ@Speed,Intensity,Randomness,Collision hardness,Saturation,Wrap X,Side bounce,Ground bounce;;!;012;pal=11,sx=100,ix=200,c1=31,c2=0,c3=20,o1=0,o2=0,o3=1" ;
9430+
93199431#endif // WLED_DISABLE_2D
93209432
93219433
@@ -9565,12 +9677,11 @@ void WS2812FX::setupEffectData() {
95659677 addEffect (FX_MODE_PARTICLEPERLIN, &mode_particleperlin, _data_FX_MODE_PARTICLEPERLIN);
95669678 addEffect (FX_MODE_PARTICLEFALL, &mode_particlefall, _data_FX_MODE_PARTICLEFALL);
95679679 addEffect (FX_MODE_PARTICLEBOX, &mode_particlebox, _data_FX_MODE_PARTICLEBOX);
9568-
9569- // experimental
95709680 addEffect (FX_MODE_PARTICLEWATERFALL, &mode_particlewaterfall, _data_FX_MODE_PARTICLEWATERFALL);
95719681 addEffect (FX_MODE_PARTICLEIMPACT, &mode_particleimpact, _data_FX_MODE_PARTICLEIMPACT);
95729682 addEffect (FX_MODE_PARTICLEATTRACTOR, &mode_particleattractor, _data_FX_MODE_PARTICLEATTRACTOR);
95739683 addEffect (FX_MODE_PARTICLESPRAY, &mode_particlespray, _data_FX_MODE_PARTICLESPRAY);
9684+ addEffect (FX_MODE_PARTICLESGEQ, &mode_particleGEQ, _data_FX_MODE_PARTICLEGEQ);
95749685
95759686#endif // WLED_DISABLE_2D
95769687
0 commit comments