FastLED 3.9.15
Loading...
Searching...
No Matches

◆ calculateMultibandAccent()

MultibandAccent fl::audio::detector::Backbeat::calculateMultibandAccent ( const fft::Bins & fft)
private

Definition at line 208 of file backbeat.cpp.hpp.

208 {
209 MultibandAccent accent;
210
211 // Define band ranges for 16-bin CQ log-spaced fft::FFT
212 // Bass: bins 0-3 (~175-400 Hz) - kick drum fundamentals
213 // Mid: bins 4-10 (~460-2100 Hz) - snare fundamental and harmonics
214 // High: bins 11-15 (~2450-4698 Hz) - hi-hats, cymbals
215
216 size numBins = fft.raw().size();
217 if (numBins == 0) {
218 accent = {0.0f, 0.0f, 0.0f, 0.0f};
219 return accent;
220 }
221
222 // Calculate current energy for each band
223 float bassEnergy = 0.0f;
224 float midEnergy = 0.0f;
225 float highEnergy = 0.0f;
226
227 // Adjust band ranges based on actual bin count
228 size bassEnd = fl::min(static_cast<size>(4), numBins);
229 size midStart = bassEnd;
230 size midEnd = fl::min(static_cast<size>(11), numBins);
231 size highStart = midEnd;
232 size highEnd = numBins;
233
234 // Sum energy in each band
235 for (size i = 0; i < bassEnd; i++) {
236 bassEnergy += fft.raw()[i];
237 }
238 for (size i = midStart; i < midEnd; i++) {
239 midEnergy += fft.raw()[i];
240 }
241 for (size i = highStart; i < highEnd; i++) {
242 highEnergy += fft.raw()[i];
243 }
244
245 // Normalize by bin count
246 bassEnergy /= static_cast<float>(bassEnd);
247 if (midEnd > midStart) {
248 midEnergy /= static_cast<float>(midEnd - midStart);
249 }
250 if (highEnd > highStart) {
251 highEnergy /= static_cast<float>(highEnd - highStart);
252 }
253
254 // Calculate accent strength for each band (current vs previous)
255 // Using logarithmic ratio with normalization
256 const float epsilon = 1e-6f;
257 const float maxRatio = 10.0f; // Maximum expected energy increase
258
259 float bassRatio = (mPreviousAccent.bass > epsilon)
260 ? (bassEnergy / mPreviousAccent.bass)
261 : 1.0f;
262 float midRatio = (mPreviousAccent.mid > epsilon)
263 ? (midEnergy / mPreviousAccent.mid)
264 : 1.0f;
265 float highRatio = (mPreviousAccent.high > epsilon)
266 ? (highEnergy / mPreviousAccent.high)
267 : 1.0f;
268
269 // Apply logarithmic scaling and normalize to 0-1 range
270 float logMaxRatio = fl::log10f(1.0f + maxRatio);
271 accent.bass = fl::clamp(fl::log10f(1.0f + bassRatio) / logMaxRatio, 0.0f, 1.0f);
272 accent.mid = fl::clamp(fl::log10f(1.0f + midRatio) / logMaxRatio, 0.0f, 1.0f);
273 accent.high = fl::clamp(fl::log10f(1.0f + highRatio) / logMaxRatio, 0.0f, 1.0f);
274
275 // Store raw energies for next comparison (not normalized accents)
276 accent.bass = bassEnergy;
277 accent.mid = midEnergy;
278 accent.high = highEnergy;
279
280 // Actually calculate accents properly
281 float bassAccent = fl::clamp(fl::log10f(1.0f + bassRatio) / logMaxRatio, 0.0f, 1.0f);
282 float midAccent = fl::clamp(fl::log10f(1.0f + midRatio) / logMaxRatio, 0.0f, 1.0f);
283 float highAccent = fl::clamp(fl::log10f(1.0f + highRatio) / logMaxRatio, 0.0f, 1.0f);
284
285 // Weighted combination emphasizing mid-range (snare)
286 // Bass: 0.3, Mid: 0.5, High: 0.2
287 accent.total = (bassAccent * 0.3f) + (midAccent * 0.5f) + (highAccent * 0.2f);
288
289 // Return struct with raw energies stored for next frame
290 return {bassEnergy, midEnergy, highEnergy, accent.total};
291}
AudioAnalyzeFFT1024 fft
MultibandAccent mPreviousAccent
Definition backbeat.h:148
FL_DISABLE_WARNING_PUSH U constexpr common_type_t< T, U > min(T a, U b) FL_NOEXCEPT
Definition math.h:71
float log10f(float value) FL_NOEXCEPT
Definition math.h:424
constexpr enable_if< is_fixed_point< T >::value, T >::type clamp(T x, T lo, T hi) FL_NOEXCEPT

References fl::audio::detector::MultibandAccent::bass, fl::clamp(), fl::audio::detector::MultibandAccent::high, fl::log10f(), fl::audio::detector::MultibandAccent::mid, fl::min(), mPreviousAccent, and fl::audio::detector::MultibandAccent::total.

Referenced by update().

+ Here is the call graph for this function:
+ Here is the caller graph for this function: