FastLED 3.9.15
Loading...
Searching...
No Matches
simple.h
Go to the documentation of this file.
1
10
11/*
12This demo is best viewed using the FastLED compiler.
13
14Windows/MacOS binaries: https://github.com/FastLED/FastLED/releases
15
16Python
17
18Install: pip install fastled
19Run: fastled <this sketch directory>
20This will compile and preview the sketch in the browser, and enable
21all the UI elements you see below.
22*/
23
24#include <Arduino.h>
25#include <FastLED.h>
26
27#include "fl/audio.h"
28#include "fl/downscale.h"
29#include "fl/draw_visitor.h"
30#include "fl/fft.h"
31#include "fl/math.h"
32#include "fl/math_macros.h"
33#include "fl/raster.h"
34#include "fl/time_alpha.h"
35#include "fl/ui.h"
36#include "fl/xypath.h"
37#include "fl/unused.h"
38#include "fx/time.h"
39#include "fl/function.h"
40
41// Sketch.
42#include "fx_audio.h"
43
44#include "fl/memfill.h"
45using namespace fl;
46
47#define HEIGHT 128
48#define WIDTH 128
49#define NUM_LEDS ((WIDTH) * (HEIGHT))
50#define IS_SERPINTINE false
51#define TIME_ANIMATION 1000 // ms
52#define PIN_DATA 3
53
54UITitle title("Simple control of an xy path");
55UIDescription description("This is more of a test for new features.");
56UICheckbox enableVolumeVis("Enable volume visualization", false);
57UICheckbox enableRMS("Enable RMS visualization", false);
58UICheckbox enableFFT("Enable FFT visualization", true);
59UICheckbox freeze("Freeze frame", false);
60UIButton advanceFrame("Advance frame");
61UISlider decayTimeSeconds("Fade time Seconds", .1, 0, 4, .02);
62UISlider attackTimeSeconds("Attack time Seconds", .1, 0, 4, .02);
63UISlider outputTimeSec("outputTimeSec", .17, 0, 2, .01);
64
65UIAudio audio("Audio");
66UISlider fadeToBlack("Fade to black by", 5, 0, 20, 1);
67
68// Group related UI elements using UIGroup template multi-argument constructor
72
74 decayTimeSeconds.value(), outputTimeSec.value(),
75 44100);
76
79
80CRGB leds[NUM_LEDS / 4]; // Downscaled buffer
82 IS_SERPINTINE); // Framebuffer is regular rectangle LED matrix.
83
84FFTBins fftOut(WIDTH); // 2x width due to super sampling.
85
86// CRGB framebuffer[NUM_LEDS];
87// CRGB framebuffer[WIDTH_2X * HEIGHT_2X]; // 2x super sampling.
88// XYMap frameBufferXY(WIDTH, HEIGHT, IS_SERPINTINE); // LED output, serpentine
89// as is common for LED matrices. XYMap xyMap_2X(WIDTH_2X, HEIGHT_2X, false); //
90// Framebuffer is regular rectangle LED matrix.
91
92int x = 0;
93int y = 0;
94bool triggered = false;
95
97
99 double sumSq = 0.0;
100 const int N = data.size();
101 for (int i = 0; i < N; ++i) {
102 int32_t x32 = int32_t(data[i]);
103 sumSq += x32 * x32;
104 }
105 float rms = sqrt(float(sumSq) / N);
106 return rms;
107}
108
109void setup() {
110 Serial.begin(115200);
111 // auto screenmap = frameBufferXY.toScreenMap();
112 // screenmap.setDiameter(.2);
113 // FastLED.addLeds<NEOPIXEL, 2>(framebuffer,
114 // NUM_LEDS).setScreenMap(screenmap);
115 auto screenmap = ledsXY.toScreenMap();
116 screenmap.setDiameter(.2);
117
118 decayTimeSeconds.onChanged([](float value) {
119 audioFadeTracker.setDecayTime(value);
120 FASTLED_WARN("Fade time seconds: " << value);
121 });
122 attackTimeSeconds.onChanged([](float value) {
123 audioFadeTracker.setAttackTime(value);
124 FASTLED_WARN("Attack time seconds: " << value);
125 });
126 outputTimeSec.onChanged([](float value) {
127 audioFadeTracker.setOutputTime(value);
128 FASTLED_WARN("Output time seconds: " << value);
129 });
130 FastLED.addLeds<NEOPIXEL, PIN_DATA>(leds, ledsXY.getTotal())
131 .setScreenMap(screenmap);
132}
133
134void shiftUp() {
135 // fade each led by 1%
136 if (fadeToBlack.as_int()) {
137
138 for (int i = 0; i < NUM_LEDS; ++i) {
139 auto &c = framebuffer[i];
140 c.fadeToBlackBy(fadeToBlack.as_int());
141 }
142 }
143
144 for (int y = HEIGHT - 1; y > 0; --y) {
145 CRGB* row1 = &framebuffer[frameBufferXY(0, y)];
146 CRGB* row2 = &framebuffer[frameBufferXY(0, y - 1)];
147 memcpy(row1, row2, WIDTH * sizeof(CRGB));
148 }
149 CRGB* row = &framebuffer[frameBufferXY(0, 0)];
150 fl::memfill(row, 0, sizeof(CRGB) * WIDTH);
151}
152
153
154bool doFrame() {
155 if (!freeze) {
156 return true;
157 }
158 if (advanceFrame.isPressed()) {
159 return true;
160 }
161 return false;
162}
163
164void loop() {
165 if (triggered) {
166 FASTLED_WARN("Triggered");
167 }
168
169 // x = pointX.as_int();
170 y = HEIGHT / 2;
171
172 bool do_frame = doFrame();
173
174 while (AudioSample sample = audio.next()) {
175 if (!do_frame) {
176 continue;
177 }
178 float fade = audioFadeTracker(sample.pcm().data(), sample.pcm().size());
179 shiftUp();
180 // FASTLED_WARN("Audio sample size: " << sample.pcm().size());
181 soundLevelMeter.processBlock(sample.pcm());
182 // FASTLED_WARN("")
183 auto dbfs = soundLevelMeter.getDBFS();
184 FASTLED_UNUSED(dbfs);
185 // FASTLED_WARN("getDBFS: " << dbfs);
186 int32_t max = 0;
187 for (size_t i = 0; i < sample.pcm().size(); ++i) {
188 int32_t x = ABS(sample.pcm()[i]);
189 if (x > max) {
190 max = x;
191 }
192 }
193 float anim =
194 fl::map_range<float, float>(max, 0.0f, 32768.0f, 0.0f, 1.0f);
195 anim = fl::clamp(anim, 0.0f, 1.0f);
196
197 x = fl::map_range<float, float>(anim, 0.0f, 1.0f, 0.0f, WIDTH - 1);
198 // FASTLED_WARN("x: " << x);
199
200 // fft.run(sample.pcm(), &fftOut);
201 sample.fft(&fftOut);
202
203 // FASTLED_ASSERT(fftOut.bins_raw.size() == WIDTH_2X,
204 // "FFT bins size mismatch");
205
206 if (enableFFT) {
207 auto max_x = fftOut.bins_raw.size() - 1;
208 FASTLED_UNUSED(max_x);
209 for (size_t i = 0; i < fftOut.bins_raw.size(); ++i) {
210 auto x = i;
211 auto v = fftOut.bins_db[i];
212 // Map audio intensity to a position in the heat palette (0-255)
213 v = fl::map_range<float, float>(v, 45, 70, 0, 1.f);
214 v = fl::clamp(v, 0.0f, 1.0f);
215 uint8_t heatIndex =
216 fl::map_range<float, uint8_t>(v, 0, 1, 0, 255);
217
218 // FASTLED_WARN(v);
219
220 // Use FastLED's built-in HeatColors palette
221 auto c = ColorFromPalette(HeatColors_p, heatIndex);
222 c.fadeToBlackBy(255 - heatIndex);
223 framebuffer[frameBufferXY(x, 0)] = c;
224 // FASTLED_WARN("y: " << i << " b: " << b);
225 }
226 }
227
228 if (enableVolumeVis) {
229 framebuffer[frameBufferXY(x, HEIGHT / 2)] = CRGB(0, 255, 0);
230 }
231
232 if (enableRMS) {
233 float rms = sample.rms();
234 FASTLED_WARN("RMS: " << rms);
235 rms = fl::map_range<float, float>(rms, 0.0f, 32768.0f, 0.0f, 1.0f);
236 rms = fl::clamp(rms, 0.0f, 1.0f) * WIDTH;
237 framebuffer[frameBufferXY(rms, HEIGHT * 3 / 4)] = CRGB(0, 0, 255);
238 }
239 if (true) {
240 uint16_t fade_width = fade * (WIDTH - 1);
241 uint16_t h = HEIGHT / 4;
242 // yellow
243 int index = frameBufferXY(fade_width, h);
244 auto c = CRGB(255, 255, 0);
245 framebuffer[index] = c;
246 }
247 }
248
249 // now downscale the framebuffer to the led matrix
251
252 FastLED.show();
253}
CRGB leds[NUM_LEDS]
#define NUM_LEDS
int y
Definition simple.h:93
UIGroup visualizationControls("Visualization", enableVolumeVis, enableRMS, enableFFT)
UISlider decayTimeSeconds("Fade time Seconds",.1, 0, 4,.02)
UITitle title("Simple control of an xy path")
UICheckbox enableRMS("Enable RMS visualization", false)
void shiftUp()
Definition simple.h:134
UISlider outputTimeSec("outputTimeSec",.17, 0, 2,.01)
bool triggered
Definition simple.h:94
float rms(Slice< const int16_t > data)
Definition simple.h:98
UIButton advanceFrame("Advance frame")
UICheckbox freeze("Freeze frame", false)
UICheckbox enableFFT("Enable FFT visualization", true)
UIAudio audio("Audio")
void setup()
Definition simple.h:109
UISlider fadeToBlack("Fade to black by", 5, 0, 20, 1)
#define PIN_DATA
Definition simple.h:52
int x
Definition simple.h:92
CRGB framebuffer[NUM_LEDS]
Definition simple.h:77
XYMap ledsXY(WIDTH/2, HEIGHT/2, IS_SERPINTINE)
SoundLevelMeter soundLevelMeter(.0, 0.0)
UISlider attackTimeSeconds("Attack time Seconds",.1, 0, 4,.02)
FFTBins fftOut(WIDTH)
UIGroup generalControls("General Controls", freeze, advanceFrame, fadeToBlack)
#define IS_SERPINTINE
Definition simple.h:50
MaxFadeTracker audioFadeTracker(attackTimeSeconds.value(), decayTimeSeconds.value(), outputTimeSec.value(), 44100)
UIDescription description("This is more of a test for new features.")
UICheckbox enableVolumeVis("Enable volume visualization", false)
bool doFrame()
Definition simple.h:154
UIGroup audioProcessingControls("Audio Processing", decayTimeSeconds, attackTimeSeconds, outputTimeSec)
void loop()
Definition simple.h:164
XYMap frameBufferXY(WIDTH, HEIGHT, IS_SERPINTINE)
FL_DISABLE_WARNING_PUSH FL_DISABLE_WARNING_GLOBAL_CONSTRUCTORS CFastLED FastLED
Global LED strip management instance.
Definition FastLED.cpp:74
central include file for FastLED, defines the CFastLED class/object
#define WIDTH
Definition advanced.h:36
UIAudio audio("Audio Input")
#define HEIGHT
Definition advanced.h:37
Tracks a smoothed peak with attack, decay, and output-inertia time-constants.
Definition fx_audio.h:6
LED controller for WS2812 LEDs with GRB color order.
Definition FastLED.h:158
fl::size size() const
Definition slice.h:142
const TProgmemRGBPalette16 HeatColors_p
Approximate "black body radiation" palette, akin to the FastLED HeatColor() function.
#define ABS(x)
Definition math_macros.h:45
void downscale(const CRGB *src, const XYMap &srcXY, CRGB *dst, const XYMap &dstXY)
CRGB ColorFromPalette(const CRGBPalette16 &pal, fl::u8 index, fl::u8 brightness, TBlendType blendType)
void * memfill(void *ptr, int value, fl::size num)
Definition memfill.h:11
FASTLED_FORCE_INLINE T clamp(T value, T min, T max)
Definition clamp.h:10
IMPORTANT!
Definition crgb.h:20
Representation of an RGB pixel (Red, Green, Blue)
Definition crgb.h:86
#define FASTLED_UNUSED(x)
Definition unused.h:4
#define FASTLED_WARN
Definition warn.h:7