| 163 | } |
| 164 | |
| 165 | float BuildupDetector::calculateEnergyTrend() const { |
| 166 | if (mEnergyHistorySize < 8 || !mEnergySG.full()) { |
| 167 | return 0.0f; // Not enough data |
| 168 | } |
| 169 | |
| 170 | // Use SG-smoothed current value vs oldest history entry for trend |
| 171 | float currentSmoothed = mEnergySG.value(); |
| 172 | // Get the oldest entry in the circular buffer |
| 173 | int oldestIdx = (mEnergyHistorySize < 32) ? 0 : mEnergyHistoryIndex; |
| 174 | float oldestValue = mEnergyHistory[oldestIdx]; |
| 175 | |
| 176 | if (oldestValue < 1e-6f) { |
| 177 | return 0.0f; |
| 178 | } |
| 179 | |
| 180 | float riseRate = (currentSmoothed - oldestValue) / oldestValue; |
| 181 | return fl::max(0.0f, fl::min(2.0f, riseRate)); // Clamp to [0, 2] |
| 182 | } |
| 183 | |
| 184 | float BuildupDetector::calculateTrebleTrend() const { |
| 185 | if (mTrebleHistorySize < 4 || !mTrebleSG.full()) { |