FastLED 3.9.15
Loading...
Searching...
No Matches
silence.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
26
28
30 mCurrentRMS = context->getRMS();
31 u32 timestamp = context->getTimestamp();
32 mLastUpdateTime = timestamp;
33
34 // Build history
35 if (mRMSHistory.size() < static_cast<fl::size>(mHistorySize)) {
36 mRMSHistory.push_back(mCurrentRMS);
37 } else {
38 mRMSHistory[mHistoryIndex] = mCurrentRMS;
39 mHistoryIndex = (mHistoryIndex + 1) % mHistorySize;
40 }
41
42 // Get smoothed RMS
43 float smoothedRMS = getSmoothedRMS();
44
45 // Check silence condition with hysteresis
46 bool nowSilent = checkSilenceCondition(smoothedRMS);
47
48 // State transition logic
49 if (nowSilent && !mPreviousSilent) {
50 // Entering silence
51 mSilenceStartTime = timestamp;
52 mPreviousSilent = true;
53 } else if (!nowSilent && mPreviousSilent) {
54 // Exiting silence
55 mSilenceEndTime = timestamp;
56 u32 duration = mSilenceEndTime - mSilenceStartTime;
57
58 // Only fire callbacks if minimum duration was met
59 if (mIsSilent && duration >= mMinSilenceDuration) {
61 mPendingDuration = duration;
62 }
63
64 mIsSilent = false;
65 mPreviousSilent = false;
67 } else if (nowSilent && mPreviousSilent) {
68 // Continuing silence
69 u32 duration = timestamp - mSilenceStartTime;
70
71 // Check if we've reached minimum duration and should fire start event
72 if (!mIsSilent && duration >= mMinSilenceDuration) {
73 mIsSilent = true;
75 }
76
77 // Check if we've exceeded maximum duration
78 if (mIsSilent && mMaxSilenceDuration > 0 && duration >= mMaxSilenceDuration) {
80 mPendingDuration = duration;
81 }
82 }
83}
84
104
106 mIsSilent = false;
107 mPreviousSilent = false;
108 mCurrentRMS = 0.0f;
110 mSilenceEndTime = 0;
111 mLastUpdateTime = 0;
112 mRMSHistory.clear();
113 mHistoryIndex = 0;
114}
115
117 if (mRMSHistory.empty()) {
118 return 0.0f;
119 }
120
121 float sum = 0.0f;
122 for (fl::size i = 0; i < mRMSHistory.size(); i++) {
123 sum += mRMSHistory[i];
124 }
125 return sum / static_cast<float>(mRMSHistory.size());
126}
127
128bool Silence::checkSilenceCondition(float smoothedRMS) {
129 // Use hysteresis to prevent rapid toggling
130 // When currently silent, use a higher threshold to exit
131 // When not silent, use a lower threshold to enter
132 if (mPreviousSilent) {
133 // Currently in potential silence - need louder signal to exit
134 float exitThreshold = mSilenceThreshold * (1.0f + mHysteresis);
135 return smoothedRMS <= exitThreshold;
136 } else {
137 // Currently not silent - need quiet signal to enter
138 float enterThreshold = mSilenceThreshold * (1.0f - mHysteresis);
139 return smoothedRMS <= enterThreshold;
140 }
141}
142
144 if (!mIsSilent || mSilenceStartTime == 0) {
145 return 0;
146 }
148}
149
150} // namespace detector
151} // namespace audio
152} // namespace fl
PendingSilenceEvent mPendingEvent
Definition silence.h:60
bool checkSilenceCondition(float smoothedRMS)
static constexpr u32 DEFAULT_MIN_SILENCE_MS
Definition silence.h:63
static constexpr u32 DEFAULT_MAX_SILENCE_MS
Definition silence.h:64
function_list< void(u32 durationMs)> onSilenceDuration
Definition silence.h:27
function_list< void()> onSilenceStart
Definition silence.h:25
function_list< void()> onSilenceEnd
Definition silence.h:26
function_list< void(u8 silent)> onSilence
Definition silence.h:24
vector< float > mRMSHistory
Definition silence.h:55
void update(shared_ptr< Context > context) override
static constexpr float DEFAULT_SILENCE_THRESHOLD
Definition silence.h:65
~Silence() FL_NOEXCEPT override
static constexpr float DEFAULT_HYSTERESIS
Definition silence.h:66
static constexpr int DEFAULT_HISTORY_SIZE
Definition silence.h:67
Base definition for an LED controller.
Definition crgb.hpp:179
#define FL_NOEXCEPT