22 .fade_out_frames = 64,
23 .recovery_frames = 64,
38 if (config.fade_out_frames < 2 || config.recovery_frames < 2)
return false;
52 recovery_start_gain_ = 0.0f;
53 fade_start_gain_ = 1.0f;
54 pending_emergency_ =
false;
60 if (!prepared_)
return;
65 recovery_start_gain_ = 0.0f;
66 fade_start_gain_ = 1.0f;
67 pending_emergency_ =
false;
70 bool prepared() const noexcept {
return prepared_; }
73 return prepared_ ? config_.fade_out_frames : 0;
81 ++stats_.predicted_events;
82 if (available_valid_frames < 2) {
83 ++stats_.insufficient_lead_events;
84 pending_emergency_ =
true;
85 if (available_valid_frames == 0)
return;
88 ramp_frames_ = std::min(config_.fade_out_frames, available_valid_frames);
90 mode_ = ramp_frames_ == 0
96 if (!prepared_)
return 0.0f;
101 const float gain = fade_start_gain_ *
102 equal_power_fade_out(ramp_position_, ramp_frames_);
104 if (++ramp_position_ >= ramp_frames_) {
111 if (!prepared_)
return;
113 ++stats_.emergency_events;
114 stats_.starved_frames += frames;
119 pending_emergency_ =
false;
124 ++stats_.recovery_events;
125 recovery_start_gain_ = 0.0f;
126 ramp_frames_ = config_.recovery_frames;
133 if (last_gain_ >= 1.0f) {
137 ++stats_.recovery_events;
138 recovery_start_gain_ = last_gain_;
139 ramp_frames_ = config_.recovery_frames;
147 static float ramp_fraction(std::uint32_t position,
148 std::uint32_t frames)
noexcept {
149 if (frames <= 1)
return 1.0f;
150 return static_cast<float>(position) /
static_cast<float>(frames - 1);
153 static float equal_power_fade_out(std::uint32_t position,
154 std::uint32_t frames)
noexcept {
155 if (position + 1 >= frames)
return 0.0f;
156 constexpr float kHalfPi = 1.57079632679489661923f;
157 return std::cos(kHalfPi * ramp_fraction(position, frames));
160 float next_recovery_gain() noexcept {
161 constexpr float kHalfPi = 1.57079632679489661923f;
162 const float start_angle = std::asin(
163 std::clamp(recovery_start_gain_, 0.0f, 1.0f));
164 const float fraction = ramp_fraction(ramp_position_, ramp_frames_);
165 const float gain = std::sin(
166 start_angle + (kHalfPi - start_angle) * fraction);
168 if (++ramp_position_ >= ramp_frames_) {
174 SampleStarvationEnvelopeConfig config_{};
175 SampleStarvationEnvelopeStats stats_{};
177 std::uint32_t ramp_frames_ = 0;
178 std::uint32_t ramp_position_ = 0;
179 bool prepared_ =
false;
180 float last_gain_ = 1.0f;
181 float recovery_start_gain_ = 0.0f;
182 float fade_start_gain_ = 1.0f;
183 bool pending_emergency_ =
false;
Definition sample_starvation_envelope.hpp:34
float next_valid_gain() noexcept
Definition sample_starvation_envelope.hpp:95
bool prepare(const SampleStarvationEnvelopeConfig &config) noexcept
Definition sample_starvation_envelope.hpp:36
bool prepared() const noexcept
Definition sample_starvation_envelope.hpp:70
SampleStarvationMode mode() const noexcept
Definition sample_starvation_envelope.hpp:71
SampleStarvationEnvelopeStats stats() const noexcept
Definition sample_starvation_envelope.hpp:144
void begin_predicted_fade(std::uint32_t available_valid_frames) noexcept
Definition sample_starvation_envelope.hpp:76
void cancel_predicted_fade() noexcept
Definition sample_starvation_envelope.hpp:131
void mark_starved(std::uint64_t frames) noexcept
Definition sample_starvation_envelope.hpp:110
void reset() noexcept
Definition sample_starvation_envelope.hpp:44
std::uint32_t fade_out_frames() const noexcept
Definition sample_starvation_envelope.hpp:72
void begin_recovery() noexcept
Definition sample_starvation_envelope.hpp:122
void restart_audio() noexcept
Restarts the audio gain at unity after an explicit timeline jump while preserving the prepared config...
Definition sample_starvation_envelope.hpp:59
Definition analyzer_provider.hpp:12
constexpr SampleStarvationEnvelopeConfig kDefaultSampleStarvationEnvelopeConfig
Definition sample_starvation_envelope.hpp:21
SampleStarvationMode
Definition sample_starvation_envelope.hpp:9
@ Silent
Definition sample_starvation_envelope.hpp:12
@ FadingOut
Definition sample_starvation_envelope.hpp:11
@ Recovering
Definition sample_starvation_envelope.hpp:13
@ Ready
Definition sample_starvation_envelope.hpp:10
Definition sample_starvation_envelope.hpp:16
std::uint32_t recovery_frames
Definition sample_starvation_envelope.hpp:18
std::uint32_t fade_out_frames
Definition sample_starvation_envelope.hpp:17
Definition sample_starvation_envelope.hpp:26
std::uint64_t insufficient_lead_events
Definition sample_starvation_envelope.hpp:28
std::uint64_t starved_frames
Definition sample_starvation_envelope.hpp:30
std::uint64_t recovery_events
Definition sample_starvation_envelope.hpp:31
std::uint64_t predicted_events
Definition sample_starvation_envelope.hpp:27
std::uint64_t emergency_events
Definition sample_starvation_envelope.hpp:29