Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
modulation_curve.hpp
Go to the documentation of this file.
1#pragma once
2
15
18
19#include <algorithm>
20#include <cmath>
21#include <cstdint>
22#include <type_traits>
23
24namespace pulp::signal {
25
33
41
43 if (!std::isfinite(curve.strength))
44 curve.strength = 0.0f;
45 curve.strength = std::clamp(curve.strength, 0.0f, 1.0f);
46 return curve;
47}
48
52namespace detail {
53
54template <typename SampleType>
55inline SampleType precise_stage_curve(SampleType progress, SampleType curve) noexcept {
56 if constexpr (std::is_same_v<SampleType, float>) {
57 return stage_curve(progress, curve);
58 } else {
59 const SampleType k = static_cast<SampleType>(kCurveSpan) * curve;
60 if (std::abs(k) < SampleType{1.0e-8})
61 return progress;
62 return -std::expm1(-k * progress) / -std::expm1(-k);
63 }
64}
65
66} // namespace detail
67
68template <typename SampleType>
69inline SampleType modulation_curve_progress(SampleType progress, ModulationCurve curve,
70 bool rising) noexcept {
71 static_assert(std::is_floating_point_v<SampleType>);
72 const SampleType p = std::isfinite(progress)
73 ? std::clamp(progress, SampleType{0}, SampleType{1})
74 : SampleType{0};
75 curve = sanitize_modulation_curve(curve);
76
77 switch (curve.shape) {
79 return p;
81 return p * p * (SampleType{3} - SampleType{2} * p);
83 return p >= 1.0f ? 1.0f : 0.0f;
85 // A rising exponential is slow-then-fast; a falling exponential
86 // moves quickly toward its floor and then tails.
88 p, static_cast<SampleType>(rising ? -curve.strength : curve.strength));
91 p, static_cast<SampleType>(rising ? curve.strength : -curve.strength));
92 }
93 return p;
94}
95
96template <typename SampleType, typename ProgressType>
97inline SampleType interpolate_modulation_curve(SampleType start, SampleType end,
98 ProgressType progress,
99 ModulationCurve curve = {}) noexcept {
100 static_assert(std::is_floating_point_v<SampleType>);
101 static_assert(std::is_floating_point_v<ProgressType>);
102 const double a = static_cast<double>(start);
103 const double b = static_cast<double>(end);
104 if (!std::isfinite(a))
105 return std::isfinite(b) ? end : SampleType{0};
106 if (!std::isfinite(b))
107 return start;
108
109 const SampleType shaped =
110 modulation_curve_progress(static_cast<SampleType>(progress), curve, b >= a);
111 const SampleType result = std::lerp(start, end, shaped);
112 return snap_to_zero(result);
113}
114
115} // namespace pulp::signal
The small modular utilities every patch reaches for between a modulation source and its destination: ...
SampleType precise_stage_curve(SampleType progress, SampleType curve) noexcept
Definition modulation_curve.hpp:55
Definition additive_bank.hpp:218
float smoothstep(float p)
Cubic smoothstep, 3t^2 - 2t^3.
Definition mod_tools.hpp:75
@ exponential
Definition mod_tools.hpp:106
SampleType interpolate_modulation_curve(SampleType start, SampleType end, ProgressType progress, ModulationCurve curve={}) noexcept
Definition modulation_curve.hpp:97
@ rising
Definition rise_fall_generator.hpp:19
@ hold
Definition envelope.hpp:59
ModulationCurve sanitize_modulation_curve(ModulationCurve curve) noexcept
Definition modulation_curve.hpp:42
ModulationCurveShape
Definition modulation_curve.hpp:26
@ smoothstep
Definition modulation_curve.hpp:30
@ logarithmic
Definition modulation_curve.hpp:29
@ linear
Definition modulation_curve.hpp:27
@ exponential
Definition modulation_curve.hpp:28
@ hold
Definition modulation_curve.hpp:31
T snap_to_zero(T x)
Returns 0 if |x| < snap_threshold, else x.
Definition denormal.hpp:45
float stage_curve(float p, float curve)
The shared stage-shaping law:
Definition mod_tools.hpp:44
@ a
Definition formant_filter_bank.hpp:20
@ linear
2-point. Cheapest; audible imaging when pitching up.
Definition granular.hpp:133
@ progress
Definition finite_stretch_builder.hpp:30
SampleType modulation_curve_progress(SampleType progress, ModulationCurve curve, bool rising) noexcept
Definition modulation_curve.hpp:69
constexpr float kCurveSpan
Curve span for the shared stage-shaping law.
Definition mod_tools.hpp:31
Curve strength is dimensionless and legal in [0, 1].
Definition modulation_curve.hpp:37
ModulationCurveShape shape
Definition modulation_curve.hpp:38
float strength
Definition modulation_curve.hpp:39