Vital
Loading...
Searching...
No Matches
smooth_value.cpp
Go to the documentation of this file.
1
6#include "smooth_value.h"
7#include <cmath>
8#include "futils.h"
9
10namespace vital {
11
12 SmoothValue::SmoothValue(mono_float value) : Value(value), current_value_(value) { }
13
14 void SmoothValue::process(int num_samples) {
15 // If all values are equal (current_value, target value, and output), no need to continue processing.
16 if (utils::equal(current_value_, value_) && utils::equal(current_value_, output()->buffer[0]) &&
17 utils::equal(current_value_, output()->buffer[num_samples - 1])) {
18 enable(false);
19 return;
20 }
21
22 // Calculate the exponential decay factor based on the smoothing cutoff and sample rate.
24 poly_float current_value = current_value_;
25 poly_float target_value = value_;
26 poly_float* dest = output()->buffer;
27
28 // Apply exponential smoothing sample-by-sample.
29 for (int i = 0; i < num_samples; ++i) {
30 current_value = utils::interpolate(target_value, current_value, decay);
31 dest[i] = current_value;
32 }
33
34 // Check if conditions are met for linear interpolation for a final smooth step.
35 poly_mask equal_mask = poly_float::equal(current_value, current_value_) |
36 poly_float::equal(value_, current_value_);
37 if (equal_mask.anyMask())
38 linearInterpolate(num_samples, equal_mask);
39
40 current_value_ = utils::maskLoad(current_value, current_value_, equal_mask);
41 }
42
43 void SmoothValue::linearInterpolate(int num_samples, poly_mask linear_mask) {
44 // If linear interpolation is needed, we linearly ramp the value.
45 poly_float current_value = current_value_;
46 current_value_ = utils::maskLoad(current_value_, value_, linear_mask);
47 poly_float delta_value = (value_ - current_value) * (1.0f / num_samples);
48
49 poly_float* dest = output()->buffer;
50 for (int i = 0; i < num_samples; ++i) {
51 current_value += delta_value;
52 dest[i] = utils::maskLoad(dest[i], current_value, linear_mask);
53 }
54
55 // Fill remaining buffer with the final value if needed.
56 int max_samples = output()->buffer_size;
57 for (int i = num_samples; i < max_samples; ++i)
58 dest[i] = current_value_;
59 }
60
61 namespace cr {
62 SmoothValue::SmoothValue(mono_float value) : Value(value), current_value_(value) { }
63
64 void SmoothValue::process(int num_samples) {
65 // Compute decay based on control-rate updates.
66 mono_float decay = futils::exp(-2.0f * kPi * kSmoothCutoff * num_samples / getSampleRate());
67 current_value_ = utils::interpolate(value_, current_value_, decay);
68 output()->buffer[0] = current_value_;
69 }
70 } // namespace cr
71} // namespace vital
force_inline int getSampleRate() const
Retrieves the current (effective) sample rate.
Definition processor.h:326
force_inline Output * output(unsigned int index=0) const
Retrieves the Output pointer at a given index.
Definition processor.h:616
virtual void enable(bool enable)
Enables or disables this Processor.
Definition processor.h:318
void linearInterpolate(int num_samples, poly_mask linear_mask)
Performs a linear interpolation if conditions are met for a smoother transition.
Definition smooth_value.cpp:43
virtual void process(int num_samples) override
Processes a block of samples, updating the smoothed value output.
Definition smooth_value.cpp:14
static constexpr mono_float kSmoothCutoff
The cutoff frequency for smoothing, controlling how fast the value settles.
Definition smooth_value.h:26
SmoothValue(mono_float value=0.0f)
Constructs a new SmoothValue with an initial value.
Definition smooth_value.cpp:12
A Processor that maintains and outputs a constant poly_float value.
Definition value.h:24
poly_float value_
The constant output value.
Definition value.h:69
static constexpr mono_float kSmoothCutoff
The cutoff frequency for smoothing at control rate.
Definition smooth_value.h:94
virtual void process(int num_samples) override
Processes the control-rate smoothing for the given number of samples.
Definition smooth_value.cpp:64
SmoothValue(mono_float value=0.0f)
Constructs a new SmoothValue (control-rate) with an initial value.
Definition smooth_value.cpp:62
A control-rate variant of the Value processor.
Definition value.h:82
Contains faster but less accurate versions of utility math functions, such as exponential,...
force_inline mono_float exp(mono_float exponent)
Definition futils.h:132
force_inline bool equal(poly_float left, poly_float right)
Checks if two poly_floats are equal lane-by-lane. Returns true if all lanes match.
Definition poly_utils.h:341
force_inline poly_float maskLoad(poly_float zero_value, poly_float one_value, poly_mask reset_mask)
Selects between two values (zero_value or one_value) based on a mask in each lane.
Definition poly_utils.h:351
force_inline poly_float interpolate(poly_float from, poly_float to, mono_float t)
Performs a linear interpolation between two poly_floats using a scalar t in [0..1].
Definition poly_utils.h:182
Contains classes and functions used within the Vital synthesizer framework.
constexpr mono_float kPi
Pi constant.
Definition common.h:36
float mono_float
Definition common.h:33
Declares the SmoothValue classes, providing time-smoothed transitions for values.
poly_float * buffer
Pointer to the output buffer.
Definition processor.h:110
int buffer_size
Current buffer size in samples.
Definition processor.h:114
Represents a vector of floating-point values using SIMD instructions.
Definition poly_values.h:600
static force_inline mask_simd_type vector_call equal(simd_type one, simd_type two)
Compares two SIMD float registers for equality, element-wise.
Definition poly_values.h:954
Represents a vector of integer values using SIMD instructions.
Definition poly_values.h:56
static force_inline uint32_t vector_call anyMask(simd_type value)
Returns a bitmask that indicates which bytes/elements in the register are non-zero.
Definition poly_values.h:352