16 const double samples = 0.001 * std::max(ms, 1
e-6) * sample_rate;
17 return std::exp(-1.0 / std::max(samples, 1
e-9));
28 const double samples = 0.001 * std::max(ms, 1
e-6) * sample_rate;
29 return std::pow(10.0, -3.0 / std::max(samples, 1
e-9));
51template <
typename SampleType =
float>
64 sample_rate_ = sr > 0.0 ? sr : sample_rate_;
71 attack_ms_ = std::max(ms, 0.0);
77 hold_ms_ = std::max(ms, 0.0);
83 decay_ms_ = std::max(ms, 0.0);
84 decay_is_t60_ =
false;
90 decay_ms_ = std::max(ms, 0.0);
96 double hold_ms()
const {
return hold_ms_; }
102 peak_ =
static_cast<double>(
peak);
105 hold_remaining_ = hold_samples_;
106 stage_ = attack_samples_ > 0.0 ? Stage::attack : Stage::hold;
107 if (stage_ == Stage::hold) level_ = 1.0;
108 active_ = peak_ != 0.0;
118 stage_ = Stage::idle;
126 if (!active_)
return SampleType{0};
130 attack_phase_ += attack_step_;
131 if (attack_phase_ >= 1.0) {
133 stage_ = Stage::hold;
135 level_ = attack_phase_;
140 if (hold_remaining_ > 0) {
143 stage_ = Stage::decay;
152 stage_ = Stage::idle;
161 return static_cast<SampleType
>(level_ * peak_);
168 SampleType
value()
const {
return static_cast<SampleType
>(level_ * peak_); }
174 attack_samples_ = 0.001 * attack_ms_ * sample_rate_;
175 attack_step_ = attack_samples_ > 0.0 ? 1.0 / attack_samples_ : 1.0;
176 hold_samples_ =
static_cast<long>(0.001 * hold_ms_ * sample_rate_);
181 double sample_rate_ = 44100.0;
182 double attack_ms_ = 0.5;
183 double hold_ms_ = 0.0;
184 double decay_ms_ = 200.0;
185 bool decay_is_t60_ =
false;
187 double attack_samples_ = 0.0;
188 double attack_step_ = 1.0;
189 long hold_samples_ = 0;
190 double decay_coef_ = 0.0;
192 Stage stage_ = Stage::idle;
195 double attack_phase_ = 0.0;
196 long hold_remaining_ = 0;
197 bool active_ =
false;
A one-shot percussion envelope: linear attack ramp, optional hold, then exponential decay.
Definition decay_envelope.hpp:52
double hold_ms() const
Definition decay_envelope.hpp:96
SampleType value() const
Current level without advancing, scaled by the trigger peak.
Definition decay_envelope.hpp:168
DecayEnvelopeT()
A default-constructed envelope has usable coefficients at 44.1 kHz, so triggering one before any sett...
Definition decay_envelope.hpp:61
void set_decay_t60_ms(double ms)
Decay expressed as a T60 (-60 dB after ms).
Definition decay_envelope.hpp:89
void set_decay_time_constant_ms(double ms)
Decay expressed as an RC time constant (1/e after ms).
Definition decay_envelope.hpp:82
void set_attack_ms(double ms)
Length of the anti-click ramp.
Definition decay_envelope.hpp:70
double attack_ms() const
Definition decay_envelope.hpp:95
bool is_active() const
Definition decay_envelope.hpp:122
double decay_ms() const
Definition decay_envelope.hpp:97
void set_hold_ms(double ms)
Time at full scale between the attack and the decay.
Definition decay_envelope.hpp:76
void set_sample_rate(double sr)
Definition decay_envelope.hpp:63
static constexpr double silence_floor
Definition decay_envelope.hpp:56
SampleType process()
Next envelope sample in [0, peak].
Definition decay_envelope.hpp:125
void trigger(SampleType peak=SampleType{1})
Starts the envelope from silence.
Definition decay_envelope.hpp:101
void reset()
Silences the envelope immediately without a release ramp.
Definition decay_envelope.hpp:114
Definition additive_bank.hpp:218
double t60_decay_coefficient(double ms, double sample_rate)
Per-sample multiplier for a decay that reaches -60 dB after ms.
Definition decay_envelope.hpp:27
@ peak
Sample peak. Literal, fastest-responding.
Definition feedforward_compressor.hpp:119
double exp_decay_coefficient(double ms, double sample_rate)
Per-sample multiplier for an exponential decay with time constant ms.
Definition decay_envelope.hpp:15
@ decay
Definition envelope.hpp:60
@ hold
Definition envelope.hpp:59
@ attack
Definition envelope.hpp:58
T snap_to_zero(T x)
Returns 0 if |x| < snap_threshold, else x.
Definition denormal.hpp:45
@ e
Definition formant_filter_bank.hpp:20
DecayEnvelopeT< float > DecayEnvelope
Definition decay_envelope.hpp:200
DecayEnvelopeT< double > DecayEnvelope64
Definition decay_envelope.hpp:201