FastLED 3.9.15
Loading...
Searching...
No Matches
fx_engine.cpp.hpp
Go to the documentation of this file.
1#include "fl/fx/fx_engine.h"
3#include "fl/fx/video.h"
5#include "fl/task/scheduler.h"
6#include "fl/stl/noexcept.h"
7
8namespace fl {
9
10FxEngine::FxEngine(u16 numLeds, bool interpolate)
11 : mTimeFunction(0), mCompositor(numLeds), mCurrId(0),
12 mInterpolate(interpolate) {
14}
15
17
19 mAudioBack.push_back(frame);
20}
21
25
26int FxEngine::addFx(FxPtr effect) {
27 float fps = 0;
28 if (mInterpolate && effect->hasFixedFrameRate(&fps)) {
29 // Wrap the effect in a VideoFxWrapper so that we can get
30 // interpolation.
31 VideoFxWrapperPtr vid_fx = fl::make_shared<VideoFxWrapper>(effect);
32 vid_fx->setFade(0, 0); // No fade for interpolated effects
33 effect = vid_fx;
34 }
35 bool auto_set = mEffects.empty();
36 bool ok = mEffects.insert(mCounter, effect);
37 if (!ok) {
38 return -1;
39 }
40 if (auto_set) {
42 mCompositor.startTransition(0, 0, effect);
43 }
44 return mCounter++;
45}
46
47bool FxEngine::nextFx(u16 duration) {
48 bool ok = mEffects.next(mCurrId, &mCurrId, true);
49 if (!ok) {
50 return false;
51 }
52 setNextFx(mCurrId, duration);
53 return true;
54}
55
56bool FxEngine::setNextFx(int index, u16 duration) {
57 if (!mEffects.has(index)) {
58 return false;
59 }
60 mCurrId = index;
61 mDuration = duration;
62 mDurationSet = true;
63 return true;
64}
65
66FxPtr FxEngine::removeFx(int index) {
67 if (!mEffects.has(index)) {
68 return FxPtr();
69 }
70
71 FxPtr removedFx;
72 bool ok = mEffects.get(index, &removedFx);
73 if (!ok) {
74 return FxPtr();
75 }
76
77 if (mCurrId == index) {
78 // If we're removing the current effect, switch to the next one
79 mEffects.next(mCurrId, &mCurrId, true);
80 mDurationSet = true;
81 mDuration = 0; // Instant transition
82 }
83
84 return removedFx;
85}
86
87FxPtr FxEngine::getFx(int id) {
88 if (mEffects.has(id)) {
89 FxPtr fx;
90 mEffects.get(id, &fx);
91 return fx;
92 }
93 return FxPtr();
94}
95
96bool FxEngine::draw(fl::u32 now, fl::span<CRGB> finalBuffer) {
97 mTimeFunction.update(now);
98 fl::u32 warpedTime = mTimeFunction.time();
99
100 // Swap audio double-buffers: back → front, then clear back for next frame.
102 mAudioBack.clear();
103
104 // Bump the task scheduler so the audio auto-pump task runs NOW,
105 // feeding any pending I2S samples into the Processor before we read levels.
106 // Without this, draw() would read stale levels from the previous frame.
107 if (mAudioProcessor) {
109 }
110
111 // If an audio processor is wired, poll it for one frame per draw cycle.
112 if (mAudioProcessor) {
113 AudioFrame af;
114 af.bass = mAudioProcessor->getBassLevel();
115 af.mid = mAudioProcessor->getMidLevel();
116 af.treble = mAudioProcessor->getTrebleLevel();
117 af.volume = mAudioProcessor->getEnergy();
118 af.beat = mAudioProcessor->isVibeBassSpike();
119 af.timestamp = now;
120 mAudioFront.push_back(af);
121 }
122
123 // Build AudioBatch on the stack — shared across both compositor layers.
124 // Passes Processor pointer for lazy access to vibe/equalizer/percussion.
126 AudioBatch audioBatch(audioSpan, mAudioProcessor.get());
127 const AudioBatch *audioPtr =
128 (mAudioFront.empty() && !mAudioProcessor) ? nullptr : &audioBatch;
129
130 if (mEffects.empty()) {
131 return false;
132 }
133 if (mDurationSet) {
134 FxPtr fx;
135 bool ok = mEffects.get(mCurrId, &fx);
136 if (!ok) {
137 // something went wrong.
138 return false;
139 }
140 mCompositor.startTransition(now, mDuration, fx);
141 mDurationSet = false;
142 }
143 if (!mEffects.empty()) {
144 float speed = mTimeFunction.scale();
145 mCompositor.draw(now, warpedTime, finalBuffer, speed, audioPtr);
146 }
147 return true;
148}
149
150} // namespace fl
uint16_t speed
Definition Noise.ino:66
void setAudio(fl::shared_ptr< fl::audio::Processor > proc)
Connects an audio processor for automatic audio delivery.
fl::vector< AudioFrame > mAudioBack
Definition fx_engine.h:148
bool nextFx(u16 transition_ms=500)
Transitions to the next effect in the sequence.
int addFx(FxPtr effect)
Adds a new effect to the engine.
FxEngine(u16 numLeds, bool interpolate=true)
Constructs an FxEngine with the specified number of LEDs.
bool mDurationSet
Flag indicating if a new transition has been set.
Definition fx_engine.h:140
FxCompositor mCompositor
Handles effect transitions and rendering.
Definition fx_engine.h:137
int mCurrId
Id of the current effect.
Definition fx_engine.h:138
fl::vector< AudioFrame > mAudioFront
Definition fx_engine.h:147
fl::shared_ptr< fl::audio::Processor > mAudioProcessor
Definition fx_engine.h:151
~FxEngine() FL_NOEXCEPT
Destructor for FxEngine.
u16 mDuration
Duration of the current transition.
Definition fx_engine.h:139
bool setNextFx(int index, u16 duration)
Sets the next effect to transition to.
IntFxMap mEffects
Collection of effects.
Definition fx_engine.h:136
bool draw(fl::u32 now, fl::span< CRGB > outputBuffer)
Renders the current effect or transition to the output buffer.
void pushAudioFrame(const AudioFrame &frame)
Pushes an audio frame into the back buffer.
FxPtr removeFx(int index)
Requests removal of an effect from the engine, which might not happen immediately (for example the Fx...
FxPtr getFx(int index)
Retrieves an effect from the engine without removing it.
bool mInterpolate
Definition fx_engine.h:142
TimeWarp mTimeFunction
Definition fx_engine.h:134
static Scheduler & instance()
#define FASTLED_FX_ENGINE_MAX_FX
constexpr remove_reference< T >::type && move(T &&t) FL_NOEXCEPT
Definition s16x16x4.h:28
shared_ptr< T > make_shared(Args &&... args) FL_NOEXCEPT
Definition shared_ptr.h:414
Base definition for an LED controller.
Definition crgb.hpp:179
fl::u32 timestamp
When this audio sample was captured (ms)
Definition audio_frame.h:16
float volume
Overall volume (0.0-1.0, normalized RMS)
Definition audio_frame.h:14
float mid
Mid energy (0.0-1.0, normalized)
Definition audio_frame.h:12
float bass
Bass energy (0.0-1.0, normalized)
Definition audio_frame.h:11
bool beat
True if a beat was detected this sample.
Definition audio_frame.h:15
float treble
Treble energy (0.0-1.0, normalized)
Definition audio_frame.h:13
Lightweight snapshot of pre-computed audio analysis for one audio sample.
Definition audio_frame.h:10
#define FL_NOEXCEPT
Task scheduler — manages timer and frame-based tasks.