| 55 | Backbeat::~Backbeat() FL_NOEXCEPT = default; |
| 56 | |
| 57 | void Backbeat::update(shared_ptr<Context> context) { |
| 58 | // Update Beat if we own it |
| 59 | if (mOwnsBeatDetector && mBeatDetector) { |
| 60 | updateBeatDetector(context); |
| 61 | } |
| 62 | |
| 63 | // Update Downbeat if we own it |
| 64 | if (mOwnsDownbeatDetector && mDownbeatDetector) { |
| 65 | mDownbeatDetector->update(context); |
| 66 | } |
| 67 | |
| 68 | // Reset backbeat flag |
| 69 | mBackbeatDetected = false; |
| 70 | |
| 71 | // Check if a beat occurred |
| 72 | bool beatDetected = mBeatDetector && mBeatDetector->isBeat(); |
| 73 | |
| 74 | // Update beat position tracking |
| 75 | updateBeatPosition(); |
| 76 | |
| 77 | // Process beat if detected |
| 78 | if (beatDetected) { |
| 79 | // Get fft::FFT for multi-band analysis |
| 80 | mRetainedFFT = context->getFFT16(); |
| 81 | const fft::Bins& fft = *mRetainedFFT; |
| 82 | |
| 83 | // Calculate multi-band accent |
| 84 | MultibandAccent accent = calculateMultibandAccent(fft); |
| 85 | |
| 86 | // Detect backbeat accent strength |
| 87 | float accentStrength = detectBackbeatAccent(accent); |
| 88 | mCurrentStrength = accentStrength; |
| 89 | |
| 90 | // Detect backbeat |
| 91 | mBackbeatDetected = detectBackbeat(accentStrength, fft); |
| 92 | |
| 93 | if (mBackbeatDetected) { |
| 94 | mLastBackbeatNumber = mCurrentBeat; |
| 95 | |
| 96 | // Update backbeat profile |
| 97 | if (mAdaptive) { |
| 98 | updateBackbeatProfile(fft); |
| 99 | } |
| 100 | |
| 101 | // Store accent in backbeat history |
| 102 | if (mBackbeatAccents.size() >= MAX_ACCENT_HISTORY) { |
| 103 | mBackbeatAccents.pop_front(); |
| 104 | } |
| 105 | mBackbeatAccents.push_back(accentStrength); |
| 106 | } else { |
| 107 | // Store accent in non-backbeat history |
| 108 | if (mNonBackbeatAccents.size() >= MAX_ACCENT_HISTORY) { |
| 109 | mNonBackbeatAccents.pop_front(); |
| 110 | } |
| 111 | mNonBackbeatAccents.push_back(accentStrength); |
| 112 | } |
| 113 | |
| 114 | // Update adaptive thresholds |