30 if (!std::isfinite(
static_cast<double>(sample_rate)) || !(sample_rate > SampleType{0}))
31 sample_rate = SampleType{44100};
32 fast_.prepare(sample_rate);
33 slow_.prepare(sample_rate);
34 apply_detector_times_();
39 if (std::isfinite(
static_cast<double>(db)))
44 if (std::isfinite(
static_cast<double>(db)))
49 set_time_(ms, fast_attack_ms_,
true,
true);
52 set_time_(ms, fast_release_ms_,
true,
false);
55 set_time_(ms, slow_attack_ms_,
false,
true);
58 set_time_(ms, slow_release_ms_,
false,
false);
61 SampleType
process(SampleType input)
noexcept {
62 if (!std::isfinite(
static_cast<double>(input))) {
67 const SampleType fast = fast_.process(input);
68 const SampleType slow = slow_.process(input);
69 const SampleType scale = std::max({fast, slow, SampleType{1.0e-12}});
70 contrast_ = std::clamp((fast - slow) / scale, SampleType{-1}, SampleType{1});
72 const SampleType attack_amount = std::max(contrast_, SampleType{0});
73 const SampleType sustain_amount = std::max(-contrast_, SampleType{0});
74 gain_db_ = attack_db_ * attack_amount + sustain_db_ * sustain_amount;
78 if (attack_db_ == SampleType{0} && sustain_db_ == SampleType{0})
80 const SampleType output = input * std::pow(SampleType{10}, gain_db_ / SampleType{20});
81 if (!std::isfinite(
static_cast<double>(output))) {
88 void process(
const SampleType* input, SampleType* output,
int num_samples)
noexcept {
89 if (input ==
nullptr || output ==
nullptr || num_samples <= 0)
91 for (
int i = 0;
i < num_samples; ++
i)
98 contrast_ = SampleType{0};
99 gain_db_ = SampleType{0};
109 return fast_attack_ms_;
112 return fast_release_ms_;
115 return slow_attack_ms_;
118 return slow_release_ms_;
131 void set_time_(SampleType ms, SampleType& stored,
bool fast,
bool attack) {
132 if (!std::isfinite(
static_cast<double>(ms)))
134 stored = std::max(ms, SampleType{0.01});
135 auto& follower = fast ? fast_ : slow_;
139 follower.set_release_ms(stored);
142 void apply_detector_times_() {
149 EnvelopeFollowerT<SampleType> fast_{};
150 EnvelopeFollowerT<SampleType> slow_{};
151 SampleType attack_db_ = SampleType{0};
152 SampleType sustain_db_ = SampleType{0};
153 SampleType fast_attack_ms_ = SampleType{0.5};
154 SampleType fast_release_ms_ = SampleType{20};
155 SampleType slow_attack_ms_ = SampleType{15};
156 SampleType slow_release_ms_ = SampleType{120};
157 SampleType contrast_ = SampleType{0};
158 SampleType gain_db_ = SampleType{0};
void set_attack_ms(float ms)
Definition ballistics_filter.hpp:46
void set_release_ms(float ms)
Definition ballistics_filter.hpp:53
Separates attack and sustain by comparing exact-timing peak envelopes.
Definition transient_designer.hpp:24
void set_sustain_db(SampleType db) noexcept
Definition transient_designer.hpp:43
void reset() noexcept
Definition transient_designer.hpp:95
static constexpr float kMaxShapeDb
Definition transient_designer.hpp:27
void set_fast_attack_ms(SampleType ms)
Definition transient_designer.hpp:48
void process(const SampleType *input, SampleType *output, int num_samples) noexcept
Definition transient_designer.hpp:88
void set_attack_db(SampleType db) noexcept
Definition transient_designer.hpp:38
SampleType slow_release_ms() const noexcept
Definition transient_designer.hpp:117
SampleType fast_attack_ms() const noexcept
Definition transient_designer.hpp:108
SampleType gain_db() const noexcept
Definition transient_designer.hpp:123
static constexpr float kMinShapeDb
Definition transient_designer.hpp:26
static constexpr int latency_samples() noexcept
Definition transient_designer.hpp:126
SampleType process(SampleType input) noexcept
Definition transient_designer.hpp:61
SampleType contrast() const noexcept
Definition transient_designer.hpp:120
void prepare(SampleType sample_rate)
Definition transient_designer.hpp:29
void set_slow_release_ms(SampleType ms)
Definition transient_designer.hpp:57
SampleType sustain_db() const noexcept
Definition transient_designer.hpp:105
SampleType slow_attack_ms() const noexcept
Definition transient_designer.hpp:114
void set_fast_release_ms(SampleType ms)
Definition transient_designer.hpp:51
SampleType fast_release_ms() const noexcept
Definition transient_designer.hpp:111
void set_slow_attack_ms(SampleType ms)
Definition transient_designer.hpp:54
SampleType attack_db() const noexcept
Definition transient_designer.hpp:102
Shared envelope and gain-reduction vocabulary for dynamics processors.
Definition additive_bank.hpp:218
TransientDesignerT< float > TransientDesigner
Definition transient_designer.hpp:161
@ attack
Definition envelope.hpp:58
@ i
Definition formant_filter_bank.hpp:20
TransientDesignerT< double > TransientDesigner64
Definition transient_designer.hpp:162