Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
smoothed_value.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <cmath>
4#include <algorithm>
5#include <limits>
6
7namespace pulp::signal {
8
23template<typename T = float>
25public:
26 SmoothedValue() = default;
27 explicit SmoothedValue(T initial) : current_(initial), target_(initial) {}
28
33 // Set the smoothing time in seconds and sample rate
34 void set_ramp_time(T seconds, T sample_rate) {
35 // Public control inputs can be malformed. Keep the conversion to int
36 // defined and fail closed to the historical one-sample behavior.
37 constexpr int kMaxRampSamples = (std::numeric_limits<int>::max)();
38 if (!std::isfinite(seconds) || !std::isfinite(sample_rate) || seconds <= T(0) ||
39 sample_rate <= T(0)) {
40 ramp_samples_ = 1;
41 return;
42 }
43 // Compare in a wider type before converting to int. In particular,
44 // float(INT_MAX) rounds to 2^31, which otherwise leaves an out-of-range
45 // value eligible for the conversion below.
46 const long double sample_count_wide =
47 static_cast<long double>(seconds) * static_cast<long double>(sample_rate);
48 if (!std::isfinite(sample_count_wide) ||
49 sample_count_wide > static_cast<long double>(kMaxRampSamples)) {
50 ramp_samples_ = kMaxRampSamples;
51 return;
52 }
53 ramp_samples_ = static_cast<int>(seconds * sample_rate);
54 if (ramp_samples_ < 1) ramp_samples_ = 1;
55 }
56
57 // Set the target value (begins ramping)
58 void set_target(T value) {
59 target_ = value;
60 if (ramp_samples_ <= 1) {
61 current_ = value;
62 steps_remaining_ = 0;
63 increment_ = T(0);
64 } else {
65 increment_ = (target_ - current_) / static_cast<T>(ramp_samples_);
66 steps_remaining_ = ramp_samples_;
67 }
68 }
69
70 // Jump immediately to value (no smoothing)
71 void set_immediate(T value) {
72 current_ = value;
73 target_ = value;
74 steps_remaining_ = 0;
75 increment_ = T(0);
76 }
77
78 // Get the next smoothed sample
79 T next() {
80 if (steps_remaining_ > 0) {
81 current_ += increment_;
82 --steps_remaining_;
83 if (steps_remaining_ == 0) current_ = target_;
84 }
85 return current_;
86 }
87
88 // Skip N samples of smoothing
89 void skip(int n) {
90 if (n <= 0) return;
91 if (steps_remaining_ <= 0) return;
92 if (n >= steps_remaining_) {
93 current_ = target_;
94 steps_remaining_ = 0;
95 } else {
96 current_ += increment_ * static_cast<T>(n);
97 steps_remaining_ -= n;
98 }
99 }
100
101 // Is smoothing still active?
102 bool is_smoothing() const { return steps_remaining_ > 0; }
103
104 // Current value (without advancing)
105 T current() const { return current_; }
106 T target() const { return target_; }
107
108private:
109 T current_ = T(0);
110 T target_ = T(0);
111 T increment_ = T(0);
112 int ramp_samples_ = 1;
113 int steps_remaining_ = 0;
114};
115
117
118} // namespace pulp::signal
Linear smoothing for control-rate parameters.
Definition smoothed_value.hpp:24
void set_target(T value)
Definition smoothed_value.hpp:58
T next()
Definition smoothed_value.hpp:79
void skip(int n)
Definition smoothed_value.hpp:89
void set_immediate(T value)
Definition smoothed_value.hpp:71
SmoothedValue(T initial)
Definition smoothed_value.hpp:27
T target() const
Definition smoothed_value.hpp:106
void set_ramp_time(T seconds, T sample_rate)
RT contract: this helper stores only scalar state and allocates no memory.
Definition smoothed_value.hpp:34
bool is_smoothing() const
Definition smoothed_value.hpp:102
T current() const
Definition smoothed_value.hpp:105
Definition additive_bank.hpp:218
SmoothedValue< double > SmoothedValue64
Definition smoothed_value.hpp:116