FastLED 3.9.15
Loading...
Searching...
No Matches
dynamics_analyzer.cpp.hpp
Go to the documentation of this file.
3#include "fl/math/math.h"
4#include "fl/stl/noexcept.h"
5
6namespace fl {
7namespace audio {
8namespace detector {
9
11 : mHistorySize(86) // ~2 seconds at 43fps
12 , mHistoryIndex(0)
13 , mCurrentRMS(0.0f)
14 , mAverageRMS(0.0f)
15 , mPeakRMS(0.0f)
16 , mMinRMS(1.0f)
17 , mTrend(0.0f)
18 , mCompressionRatio(1.0f)
19 , mPeakDecay(0.99f)
20 , mSmoothingFactor(0.9f)
21 , mTrendThreshold(0.15f)
22 , mIsCrescendo(false)
23 , mIsDiminuendo(false)
24 , mPrevIsCrescendo(false)
25 , mPrevIsDiminuendo(false)
27{
29}
30
32
34 mCurrentRMS = context->getRMS();
35 u32 timestamp = context->getTimestamp();
36
37 // Update peak with decay
39
40 // Add to history
41 if (mRMSHistory.size() < mHistorySize) {
42 mRMSHistory.push_back(mCurrentRMS);
44 } else {
47 }
48
49 // Calculate average RMS from history
50 float sum = 0.0f;
51 for (fl::size i = 0; i < mRMSHistory.size(); i++) {
52 sum += mRMSHistory[i];
53 }
54 mAverageRMS = (mRMSHistory.size() > 0) ? sum / mRMSHistory.size() : 0.0f;
55
56 // Track minimum RMS (with slow rise to handle changing environments)
57 if (mCurrentRMS < mMinRMS) {
59 } else {
60 mMinRMS += (mCurrentRMS - mMinRMS) * 0.001f; // Very slow rise
61 }
62
63 // Calculate dynamic trend
64 float newTrend = calculateTrend();
65
66 // Smooth the trend
67 mTrend = mSmoothingFactor * mTrend + (1.0f - mSmoothingFactor) * newTrend;
68
69 // Determine crescendo/diminuendo state
72
75
76 // Update compression ratio
78
79 mLastUpdateTime = timestamp;
80}
81
96
98 mRMSHistory.clear();
99 mHistoryIndex = 0;
100 mCurrentRMS = 0.0f;
101 mAverageRMS = 0.0f;
102 mPeakRMS = 0.0f;
103 mMinRMS = 1.0f;
104 mTrend = 0.0f;
105 mCompressionRatio = 1.0f;
106 mIsCrescendo = false;
107 mIsDiminuendo = false;
108 mPrevIsCrescendo = false;
109 mPrevIsDiminuendo = false;
110 mLastUpdateTime = 0;
111}
112
114 if (mRMSHistory.size() < 10) {
115 return 0.0f; // Not enough data
116 }
117
118 // Use linear regression to determine trend
119 // Compare recent average to older average
120 fl::size halfSize = mRMSHistory.size() / 2;
121
122 float recentSum = 0.0f;
123 float olderSum = 0.0f;
124
125 // Recent half
126 for (fl::size i = 0; i < halfSize; i++) {
127 fl::size idx = (mHistoryIndex + i) % mRMSHistory.size();
128 olderSum += mRMSHistory[idx];
129 }
130
131 // Older half
132 for (fl::size i = halfSize; i < mRMSHistory.size(); i++) {
133 fl::size idx = (mHistoryIndex + i) % mRMSHistory.size();
134 recentSum += mRMSHistory[idx];
135 }
136
137 float recentAvg = recentSum / halfSize;
138 float olderAvg = olderSum / halfSize;
139
140 // Avoid division by zero
141 if (olderAvg < 1e-6f) {
142 return 0.0f;
143 }
144
145 // Calculate normalized trend (-1 to +1)
146 float rawTrend = (recentAvg - olderAvg) / olderAvg;
147
148 // Clamp to reasonable range
149 return fl::max(-1.0f, fl::min(1.0f, rawTrend * 5.0f));
150}
151
153 if (rms > mPeakRMS) {
154 mPeakRMS = rms;
155 } else {
156 // Apply decay
158 }
159}
160
162 // Calculate dynamic range compression ratio
163 // Compression ratio = (peak - min) / peak
164 // High compression (near 1.0) = small dynamic range
165 // Low compression (near 0.0) = large dynamic range
166
167 if (mPeakRMS < 1e-6f) {
168 mCompressionRatio = 1.0f;
169 return;
170 }
171
172 float dynamicRange = mPeakRMS - mMinRMS;
174
175 // Clamp to 0-1
177}
178
180 mHistorySize = size;
181 mRMSHistory.clear();
182 mRMSHistory.reserve(size);
183 mHistoryIndex = 0;
184}
185
187 mTrendThreshold = threshold;
188}
189
191 // Clamp to 0-1
192 mSmoothingFactor = fl::max(0.0f, fl::min(1.0f, alpha));
193}
194
195} // namespace detector
196} // namespace audio
197} // namespace fl
float rms(fl::span< const int16_t > data)
Definition simple.h:104
const float dynamicRange
void update(shared_ptr< Context > context) override
~DynamicsAnalyzer() FL_NOEXCEPT override
function_list< void(float compression)> onCompressionRatio
function_list< void(float trend)> onDynamicTrend
FL_DISABLE_WARNING_PUSH U constexpr common_type_t< T, U > min(T a, U b) FL_NOEXCEPT
Definition math.h:71
constexpr common_type_t< T, U > max(T a, U b) FL_NOEXCEPT
Definition math.h:75
Base definition for an LED controller.
Definition crgb.hpp:179
#define FL_NOEXCEPT