FastLED 3.10.6
Loading...
Searching...
No Matches

◆ draw()

void mood_ring::MoodPainter::draw ( const RoomSense & s,
fl::u32 nowMs,
fl::span< CRGB > out )

Render one frame into out.

Buffers resize on first use and whenever the length changes.

Definition at line 42 of file mood_painter.cpp.

42 {
43 if (out.empty())
44 return;
45 ensureBuffers(out.size());
46
47 const float dtSec =
48 (mLastMs == 0) ? 0.016f : static_cast<float>(nowMs - mLastMs) * 0.001f;
49 mLastMs = nowMs;
50
51 // Hue drift only while calm; a busy room gets its motion from the layers.
52 mHueDrift =
53 wrapTurns(mHueDrift + kHueDriftTurnsPerSecCalm * s.calm * dtSec);
54 const MoodPalette pal = paletteFor(s, mHueDrift);
55
56 // Every layer renders every frame, even at zero weight, so its
57 // envelopes, grains and phase correction keep running. Skipping a layer
58 // would freeze a half-finished flash and replay it when the layer
59 // returned. The pixel loops are cheap at ring scale.
60 RingCanvas breath(mBufBreath);
61 RingCanvas flow(mBufFlow);
62 RingCanvas groove(mBufGroove);
63 breath.clear();
64 flow.clear();
65 groove.clear();
66 mBreath.render(s, pal, dtSec, breath);
67 mFlow.render(s, pal, dtSec, flow);
68 mGroove.render(s, pal, dtSec, groove);
69
70 mixLayers(s);
71
72 if (tuning.trails) {
73 float keep = tuning.trailOverride;
74 if (keep < 0.0f) {
75 keep = kKeepCalm * s.calm + kKeepFlow * s.flow +
76 kKeepGroove * s.groove;
77 }
78 applyTrails(keep);
79 } else {
80 // Drop history so re-enabling does not smear a stale frame.
81 for (fl::size i = 0; i < mTrail.size(); ++i)
82 mTrail[i] = RGBf{};
83 }
84
85 if (tuning.pulses) {
86 // Pulses belong to groove. Weight them by it so a beat that fires
87 // while groove is fading in arrives at the right strength.
88 if (s.events.downbeat) {
89 emitPulse(1.0f * s.groove, true, nowMs);
90 } else if (s.events.kick || s.events.beat) {
91 emitPulse(0.7f * s.groove, false, nowMs);
92 }
93 drawPulses(pal, nowMs);
94 }
95
96 // The one and only quantisation.
97 for (fl::size i = 0; i < out.size(); ++i)
98 out[i] = toCRGB(mMix[i]);
99}
constexpr bool empty() const FL_NO_EXCEPT
Definition span.h:535
constexpr fl::size size() const FL_NO_EXCEPT
Definition span.h:483
fl::vector< RGBf > mBufGroove
fl::vector< RGBf > mTrail
persistence shadow
fl::vector< RGBf > mBufFlow
void drawPulses(const MoodPalette &pal, fl::u32 nowMs)
void mixLayers(const RoomSense &s)
void applyTrails(float keep)
void ensureBuffers(fl::size n)
float mHueDrift
slow hue travel, turns of the wheel
fl::vector< RGBf > mBufBreath
void emitPulse(float strength, bool downbeat, fl::u32 nowMs)
fl::vector< RGBf > mMix
this frame, summed
CRGB toCRGB(const RGBf &p)
MoodPalette paletteFor(const RoomSense &s, float hueDrift)
Derive the family for this frame. Cheap; call every frame.
float wrapTurns(float t)
Wrap into [0, 1).

References applyTrails(), mood_ring::RoomEvents::beat, mood_ring::RoomSense::calm, mood_ring::RingCanvas::clear(), mood_ring::RoomEvents::downbeat, drawPulses(), emitPulse(), fl::span< T, Extent >::empty(), ensureBuffers(), mood_ring::RoomSense::events, mood_ring::RoomSense::flow, mood_ring::RoomSense::groove, mood_ring::RoomEvents::kick, mBreath, mBufBreath, mBufFlow, mBufGroove, mFlow, mGroove, mHueDrift, mixLayers(), mLastMs, mMix, mTrail, mood_ring::paletteFor(), fl::span< T, Extent >::size(), mood_ring::toCRGB(), tuning, and mood_ring::wrapTurns().

+ Here is the call graph for this function: