MCPcopy Create free account
hub / github.com/FastLED/FastLED / detectDownbeat

Method detectDownbeat

src/fl/audio/detector/downbeat.cpp.hpp:220–311  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

218}
219
220bool Downbeat::detectDownbeat(u32 timestamp, float accent) {
221 // Downbeat detection strategy:
222 // 1. Check if we're at the expected measure boundary
223 // 2. Check if accent is strong enough
224 // 3. Check if pattern matches metric grouping
225
226 // If we haven't detected any downbeats yet, consider this one
227 if (mLastDownbeatTime == 0) {
228 // Use accent strength for initial confidence instead of fixed 0.5
229 // This provides a better estimate based on actual audio characteristics
230 float meanAccent = 1.0f;
231 if (!mBeatAccents.empty()) {
232 float sum = 0.0f;
233 for (size i = 0; i < mBeatAccents.size(); i++) {
234 sum += mBeatAccents[i];
235 }
236 meanAccent = sum / static_cast<float>(mBeatAccents.size());
237 }
238
239 // Calculate accent-based confidence
240 // If we have accent history, use it; otherwise use raw accent with moderate confidence
241 float accentConfidence = meanAccent > 0.0f
242 ? fl::clamp(accent / (meanAccent * mAccentThreshold), 0.0f, 1.0f)
243 : fl::clamp(accent * 0.5f, 0.3f, 0.7f); // Raw accent scaled to 30-70% range
244
245 mConfidence = accentConfidence;
246 return true;
247 }
248
249 // Calculate expected downbeat position
250 u32 timeSinceDownbeat = timestamp - mLastDownbeatTime;
251 float beatInterval = mBeatDetector->getBPM() > 0.0f
252 ? (60000.0f / mBeatDetector->getBPM())
253 : 500.0f;
254 float expectedMeasureDuration = beatInterval * static_cast<float>(mBeatsPerMeasure);
255
256 // Check if we're near expected measure boundary
257 float timingError = fl::abs(static_cast<float>(timeSinceDownbeat) - expectedMeasureDuration);
258 float maxTimingError = beatInterval * 0.4f; // Allow 40% timing error
259 bool nearMeasureBoundary = (timingError < maxTimingError);
260
261 // Check if accent is strong enough
262 float meanAccent = 1.0f;
263 if (!mBeatAccents.empty()) {
264 float sum = 0.0f;
265 for (size i = 0; i < mBeatAccents.size(); i++) {
266 sum += mBeatAccents[i];
267 }
268 meanAccent = sum / static_cast<float>(mBeatAccents.size());
269 }
270
271 bool strongAccent = (accent > meanAccent * mAccentThreshold);
272
273 // Check if we're at the beat counter boundary
274 bool atBeatCounterBoundary = (mBeatsSinceDownbeat >= mBeatsPerMeasure - 1);
275
276 // Calculate confidence
277 float timingConfidence = 1.0f - (timingError / (beatInterval * 2.0f));

Callers

nothing calls this directly

Calls 6

clampFunction · 0.85
maxFunction · 0.85
absFunction · 0.50
emptyMethod · 0.45
sizeMethod · 0.45
getBPMMethod · 0.45

Tested by

no test coverage detected