Skip to content

Commit 87adbed

Browse files
committed
added particle GEQ effect (untested)
1 parent bdfb1a9 commit 87adbed

File tree

2 files changed

+117
-5
lines changed

2 files changed

+117
-5
lines changed

wled00/FX.cpp

Lines changed: 115 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -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
}
93179316
static 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

wled00/FX.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,8 @@
329329
#define FX_MODE_PARTICLEIMPACT 195
330330
#define FX_MODE_PARTICLEWATERFALL 196
331331
#define FX_MODE_PARTICLESPRAY 197
332-
#define MODE_COUNT 198
332+
#define FX_MODE_PARTICLESGEQ 198
333+
#define MODE_COUNT 199
333334

334335
typedef enum mapping1D2D {
335336
M12_Pixels = 0,

0 commit comments

Comments
 (0)