Skip to content

BeatRipplesEffect

Source: BeatRipplesEffect.h

BeatRipplesEffect

class BeatRipplesEffect
src/light/effects/BeatRipplesEffect.h:27

Inherits: EffectBase

Effect: a wave surface where every detected beat drops a stone, rippling and interfering.

BeatRipplesEffect card BeatRipplesEffect controls

The surface is a real wave simulation, the classic two-buffer scheme. Ripples pass through each other, reflect off the walls, and interfere into standing patterns. A detected onset drops a stone, and between beats the surface keeps ringing on its own.

Prior art: Gomez 2000, the water effect the demoscene settled on.

Public Attributes

uint8_t damping = 200 : How long the water keeps ringing.

uint8_t drop = 180 : How deep a beat's stone falls.

uint8_t rain = 30 : Idle drops, for when there is no music at all.

uint8_t shine = 150 : How strongly the slope lights the surface.

Public Methods

virtual inline const char * tags() const override : Catalog tags for the visual catalog.

virtual inline Dim dimensions() const override : The wave equation is 2D, and a cube takes the plane extruded.

virtual inline void defineControls() override : Publish the damping, the stone's depth, the idle rain and the slope's brightness.

virtual inline void prepare() override : Size both height buffers, clear them, and arm the rain clock.

virtual inline void tick() override : Drop a stone on each onset, rain when idle, then step the surface and render it.

inline void waveStep() : One step of the wave equation, which is what makes ripples pass through each other.

inline void renderSurface(const draw::Canvas & cv, lengthType w, lengthType h) : Render by slope: the gradient between neighbors lights a pixel, not the height itself.

More info

The wave equation, and rendering by slope

Each cell's next height is its four neighbors averaged and doubled, minus its previous height, damped. That discrete wave equation is what a hand-drawn expanding circle cannot give. The field renders by slope rather than height: a surface is visible because it bends light. So the difference between neighboring cells lights a pixel, and crests read as bright lines.

The loudest band picks where a stone lands, bass near the center and treble out at the rim. Layer::extrude fills a cube with the plane, as Particles and Wave do, since the equation is 2D.