PulseEffect
Source:
PulseEffect.h
Pulse¶
src/light/effects/PulseEffect.h:159One expanding shell: when it started, how bright it is, and where in the palette it sits.
Public Attributes¶
uint32_t born = 0
uint8_t strength = 0
uint8_t hue = 0
bool live = false
PulseEffect¶
src/light/effects/PulseEffect.h:46Inherits:
EffectBase
Expanding shells from a drifting origin, one per beat, alive with or without sound.

A pulse is a thin shell that grows from a point and dims as it travels. The same shell is a wave on a strip, a ring on a panel and a sphere in a volume. A shell is a distance, and every layout has distances. Between sounds the shells keep arriving on the idle clock, so a silent room still moves.
Public Attributes¶
uint8_t bpm = 40
: Pulses per minute while nothing is heard, where 0 waits for sound alone.
uint8_t speed = 60
: How fast a shell crosses the layout, whatever its size, where 255 crosses it in a second.
uint8_t thickness = 40
: The shell's width as a share of the layout, so it stays a shell at any size.
uint8_t audioGain = 200
: How strongly sound fires a pulse, where 0 leaves the idle clock alone in charge.
uint8_t drift = 120
: How far the origin wanders from the center, where 0 pins it there.
Public Methods¶
virtual inline const char * tags() const override
: Catalog tags: a MoonLight original that reacts to sound.
virtual inline Dim dimensions() const override
: A shell is a distance, which every layout has, so all three axes are used.
virtual inline void defineControls() override
: Publish the rhythm, the shell's shape, and how much the room drives it.
virtual inline void tick() override
: Dim what is there, fire a pulse where one is due, then draw every live shell.
More info¶
Why this is the default effect¶
A first boot shows three things at once: the lights work, the device runs, and it hears the room. A dense field shows the first and hides the other two, since every light is already busy. A shell leaves most of the layout dark, so one beat is unmistakable, and the drifting origin proves the device runs before any sound arrives.
One shell, three dimensions¶
The radius is a Euclidean distance over whatever axes the layout has, so the code branches on nothing. A 300-light strip has one axis, where a shell becomes a pair of fronts running outward from the origin. A panel gives a ring and a volume gives a sphere, from the same three subtractions.
One set of defaults fits every layout¶
Both the travel and the shell's width are shares of the layout's own diagonal rather than counts of lights. A fixed lights-a-second speed crosses a 16x16 panel in half a second and a 300-light strip in seven, so one set of defaults cannot suit both. As a share, a shell takes the same time to cross whatever it is on, and roughly three are alive at any moment on every geometry.
The square root is paid per shell, not per light¶
Comparing a radius against a distance and comparing their squares decide the same thing, so the shell test runs in squared space. The root is then taken only for a light that some shell already contains, which is a few percent of the grid. That matters on an in-order pipeline, where a 16-iteration root is 16 branch stalls a light rather than a speculated handful.
What drives a pulse, and what will drive it later¶
Three inputs decide everything: when a pulse fires, where it starts, and what color it takes. Audio fills all three today, where an onset fires it, the drift places it, and the dominant frequency colors it. A sensor added later fills the same three, which is why emit takes exactly those arguments.