FastLED 3.9.15
Loading...
Searching...
No Matches
multiband_beat_detector.cpp.hpp
Go to the documentation of this file.
2#include "fl/math/math.h"
3#include "fl/stl/noexcept.h"
4
5namespace fl {
6namespace audio {
7namespace detector {
8
10
14
16
18 mConfig = config;
19 reset();
20}
21
23 // Verify input size
24 if (frequencyBins.size() < 16) {
25 // Invalid input - reset beat flags
26 mBassBeat = false;
27 mMidBeat = false;
28 mTrebleBeat = false;
29 return;
30 }
31
32 // Calculate current energies
33 float bassEnergy = calculateBassEnergy(frequencyBins);
34 float midEnergy = calculateMidEnergy(frequencyBins);
35 float trebleEnergy = calculateTrebleEnergy(frequencyBins);
36
37 // Decrement cooldown counters
39 if (mMidCooldown > 0) mMidCooldown--;
41
42 // Detect beats in each band
44 mConfig.bassThreshold, mBassCooldown);
46 mConfig.midThreshold, mMidCooldown);
48 mConfig.trebleThreshold, mTrebleCooldown);
49
50 // Cross-band correlation: if multiple bands trigger, boost confidence
51 if (mConfig.enableCrossBandCorrelation) {
52 u32 bandCount = 0;
53 if (mBassBeat) bandCount++;
54 if (mMidBeat) bandCount++;
55 if (mTrebleBeat) bandCount++;
56
57 // Multi-band beat detected
58 if (bandCount >= 2) {
59 mStats.multiBandBeats++;
60 }
61 }
62
63 // Update statistics
64 if (mBassBeat) mStats.bassBeats++;
65 if (mMidBeat) mStats.midBeats++;
66 if (mTrebleBeat) mStats.trebleBeats++;
67
68 // Store current energies for next frame
69 mPreviousBassEnergy = bassEnergy;
70 mPreviousMidEnergy = midEnergy;
71 mPreviousTrebleEnergy = trebleEnergy;
72
73 // Update current energies in stats
74 mBassEnergy = bassEnergy;
75 mMidEnergy = midEnergy;
76 mTrebleEnergy = trebleEnergy;
77
78 mStats.bassEnergy = bassEnergy;
79 mStats.midEnergy = midEnergy;
80 mStats.trebleEnergy = trebleEnergy;
81
83}
84
86 return mBassBeat;
87}
88
90 return mMidBeat;
91}
92
94 return mTrebleBeat;
95}
96
98 return mBassEnergy;
99}
100
102 return mMidEnergy;
103}
104
106 return mTrebleEnergy;
107}
108
110 u32 bandCount = 0;
111 if (mBassBeat) bandCount++;
112 if (mMidBeat) bandCount++;
113 if (mTrebleBeat) bandCount++;
114 return bandCount >= 2;
115}
116
118 mBassBeat = false;
119 mMidBeat = false;
120 mTrebleBeat = false;
121
122 mBassEnergy = 0.0f;
123 mMidEnergy = 0.0f;
124 mTrebleEnergy = 0.0f;
125
126 mPreviousBassEnergy = 0.0f;
127 mPreviousMidEnergy = 0.0f;
129
130 mBassCooldown = 0;
131 mMidCooldown = 0;
132 mTrebleCooldown = 0;
133
134 mCurrentFrame = 0;
135
136 mStats.bassBeats = 0;
137 mStats.midBeats = 0;
138 mStats.trebleBeats = 0;
139 mStats.multiBandBeats = 0;
140 mStats.bassEnergy = 0.0f;
141 mStats.midEnergy = 0.0f;
142 mStats.trebleEnergy = 0.0f;
143}
144
145bool MultiBandBeat::detectBandBeat(float currentEnergy, float previousEnergy,
146 float threshold, u32& cooldownCounter) {
147 // Check if cooldown is active
148 if (cooldownCounter > 0) {
149 return false;
150 }
151
152 // Need previous energy to calculate relative increase
153 // Skip beat detection on first frame (no baseline)
154 if (previousEnergy <= 0.0001f) {
155 return false;
156 }
157
158 // Calculate energy increase
159 float energyIncrease = currentEnergy - previousEnergy;
160
161 // Must be a significant increase
162 if (energyIncrease <= 0.0f) {
163 return false;
164 }
165
166 // Calculate relative increase (percentage)
167 float relativeIncrease = energyIncrease / previousEnergy;
168
169 // Detect beat if relative increase exceeds threshold
170 if (relativeIncrease > threshold) {
171 // Activate cooldown
172 cooldownCounter = mConfig.beatCooldownFrames;
173 return true;
174 }
175
176 return false;
177}
178
180 // Average bins 0-1 (20-80 Hz)
181 float sum = 0.0f;
182 for (size i = BASS_BIN_START; i < BASS_BIN_END; ++i) {
183 sum += frequencyBins[i];
184 }
185 return sum / static_cast<float>(BASS_BIN_END - BASS_BIN_START);
186}
187
189 // Average bins 6-7 (320-640 Hz)
190 float sum = 0.0f;
191 for (size i = MID_BIN_START; i < MID_BIN_END; ++i) {
192 sum += frequencyBins[i];
193 }
194 return sum / static_cast<float>(MID_BIN_END - MID_BIN_START);
195}
196
198 // Average bins 14-15 (5120-16000 Hz)
199 float sum = 0.0f;
200 for (size i = TREBLE_BIN_START; i < TREBLE_BIN_END; ++i) {
201 sum += frequencyBins[i];
202 }
203 return sum / static_cast<float>(TREBLE_BIN_END - TREBLE_BIN_START);
204}
205
206} // namespace detector
207} // namespace audio
208} // namespace fl
bool detectBandBeat(float currentEnergy, float previousEnergy, float threshold, u32 &cooldownCounter)
Detect beat in a specific frequency band.
void reset()
Reset internal state (clear history, reset cooldowns)
float getMidEnergy() const
Get current mid energy (0.0-1.0)
bool isBassBeat() const
Check if a bass beat was detected in the last frame.
float calculateMidEnergy(span< const float > frequencyBins) const
Calculate energy for mid band (bins 6-7)
float getTrebleEnergy() const
Get current treble energy (0.0-1.0)
bool isMultiBandBeat() const
Check if multiple bands triggered simultaneously (strong beat)
bool mBassBeat
Beat detection flags for current frame.
bool isMidBeat() const
Check if a mid beat was detected in the last frame.
float getBassEnergy() const
Get current bass energy (0.0-1.0)
u32 mBassCooldown
Beat cooldown counters (prevent double-triggering)
float calculateBassEnergy(span< const float > frequencyBins) const
Calculate energy for bass band (bins 0-1)
float mPreviousBassEnergy
Previous band energies (for energy increase calculation)
bool isTrebleBeat() const
Check if a treble beat was detected in the last frame.
void configure(const MultiBandBeatDetectorConfig &config)
Configure the multi-band beat detector.
static constexpr size BASS_BIN_START
Frequency bin indices for each band.
float calculateTrebleEnergy(span< const float > frequencyBins) const
Calculate energy for treble band (bins 14-15)
void detectBeats(span< const float > frequencyBins)
Detect beats in all frequency bands.
constexpr fl::size size() const FL_NOEXCEPT
Definition span.h:458
Configuration for multi-band beat detection.
Base definition for an LED controller.
Definition crgb.hpp:179
#define FL_NOEXCEPT