Sound Byte Libs 0.5.1-121-g3358a44
C++ firmware library for audio applications on 32-bit ARM Cortex-M processors
Loading...
Searching...
No Matches
fader.hpp
Go to the documentation of this file.
1// sbl/dsp/comp/fader.hpp — Gain control with taper curve (Audio Stack — Compositions)
2//
3// Atomic gain element for mixer faders, VCA control, or any context where a
4// normalized [0,1] signal controls amplitude. Applies a taper curve (linear,
5// audio, or exponential) and per-sample one-pole smoothing for click-free
6// gain changes.
7//
8// Taper curves shape the perceived loudness response:
9// Linear: gain = su (even distribution)
10// Audio: gain = su^2 (perceived-loudness, log-like)
11// Exponential: gain = su^3 (aggressive low-end concentration)
12//
13// Signal Unit API (FDP-064):
14// set_level_su(float) — [0,1] port. Clamped, taper-mapped, smoothed.
15// set_taper(Taper) — structural parameter, selects curve shape.
16//
17// Usage:
18// sbl::dsp::comp::Fader fader;
19// fader.set_level_su(0.7f); // normalized fader position
20// fader.set_taper(Taper::Audio); // default — perceived loudness
21// fader.process(buf, frames); // per-sample smoothed gain
22// fader.process(buf_l, buf_r, frames); // stereo variant
23
24#ifndef SBL_DSP_COMP_FADER_HPP_
25#define SBL_DSP_COMP_FADER_HPP_
26
27#include <cstdint>
28
31
32namespace sbl::dsp::comp {
33
34enum class Taper : uint8_t {
35 Linear, // gain = su
36 Audio, // gain = su^2 (perceived loudness, log-like)
37 Exponential, // gain = su^3 (aggressive low-end concentration)
38};
39
40class Fader {
41public:
42 static constexpr float kSettlingMs = 15.0f;
43
44 /// Port: set the fader level [0, 1].
45 /// Clamped, taper-mapped, and fed into internal smoother.
46 void set_level_su(float su) {
47 if (su < 0.0f) su = 0.0f;
48 if (su > 1.0f) su = 1.0f;
49 level_su_ = su;
50 target_gain_ = apply_taper(su);
51 }
52
53 /// Parameter: set the taper curve (structural config).
54 /// Recomputes target gain from current level.
55 void set_taper(Taper t) {
56 taper_ = t;
57 target_gain_ = apply_taper(level_su_);
58 }
59
60 /// Apply gain to a mono buffer in-place.
61 /// Per-sample smoothing toward target gain — click-free.
62 void process(float* buf, uint16_t n) {
63 ensure_smoother();
64 for (uint16_t i = 0; i < n; ++i) {
65 float g = smoother_.process(target_gain_);
66 buf[i] *= g;
67 }
68 }
69
70 /// Apply gain to stereo buffers in-place.
71 /// Same smoothed gain applied to both channels per sample.
72 void process(float* buf_l, float* buf_r, uint16_t n) {
73 ensure_smoother();
74 for (uint16_t i = 0; i < n; ++i) {
75 float g = smoother_.process(target_gain_);
76 buf_l[i] *= g;
77 buf_r[i] *= g;
78 }
79 }
80
81 /// Advance the smoother by n samples' worth without processing audio.
82 /// Call once per block with the block size for control-rate gain updates
83 /// (e.g., send levels) — settling time matches per-sample process()
84 /// regardless of call rate.
85 /// Returns the current smoothed gain.
86 float tick(uint16_t n) {
87 ensure_smoother();
88 return smoother_.process_steps(target_gain_, n);
89 }
90
91 /// Current smoothed gain value (after taper mapping + smoothing).
92 float gain() const { return smoother_.value(); }
93
94 /// Raw su level (before taper mapping).
95 float level() const { return level_su_; }
96
97 /// Reset smoother state and level to defaults.
98 void reset() {
99 level_su_ = 1.0f;
100 taper_ = Taper::Audio;
101 target_gain_ = apply_taper(level_su_);
102 smoother_.reset(target_gain_);
103 smoother_configured_ = false;
104 }
105
106private:
107 float apply_taper(float su) const {
108 switch (taper_) {
109 case Taper::Linear: return su;
110 case Taper::Audio: return su * su;
111 case Taper::Exponential: return su * su * su;
112 }
113 return su; // unreachable, but satisfies compiler
114 }
115
116 void ensure_smoother() {
117 if (!smoother_configured_) {
119 smoother_.reset(target_gain_);
120 smoother_configured_ = true;
121 }
122 }
123
124 Taper taper_ = Taper::Audio;
125 float level_su_ = 1.0f;
126 float target_gain_ = 1.0f; // apply_taper(1.0f) for Audio = 1.0
127 primitives::ParameterSmoother smoother_;
128 bool smoother_configured_ = false;
129};
130
131} // namespace sbl::dsp::comp
132
133#endif // SBL_DSP_COMP_FADER_HPP_
float tick(uint16_t n)
Definition fader.hpp:86
void set_taper(Taper t)
Definition fader.hpp:55
static constexpr float kSettlingMs
Definition fader.hpp:42
float gain() const
Current smoothed gain value (after taper mapping + smoothing).
Definition fader.hpp:92
void reset()
Reset smoother state and level to defaults.
Definition fader.hpp:98
float level() const
Raw su level (before taper mapping).
Definition fader.hpp:95
void set_level_su(float su)
Definition fader.hpp:46
void process(float *buf_l, float *buf_r, uint16_t n)
Definition fader.hpp:72
void process(float *buf, uint16_t n)
Definition fader.hpp:62
void set_time_ms(float ms, float rate_hz)
Compute coefficient from settling time in milliseconds.
float process_steps(float target, uint32_t n)
Advance n steps toward target in one call.
float process(float target)
Process one sample toward target.
float value() const
Current smoothed value.
Fixed-point constants and audio sample types.
Compositions: subcircuits of primitives.
float SAMPLE_RATE_F
Definition fixed.hpp:17
One-pole parameter smoother.