Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
svf_bank.hpp
Go to the documentation of this file.
1#pragma once
2
6
9#include <pulp/signal/svf.hpp>
10
11#include <algorithm>
12#include <cstddef>
13#include <iterator>
14
15namespace pulp::signal {
16
38template <typename SampleType = float, std::size_t Voices = 16> class SvfBankT {
39 static_assert(Voices > 0, "SvfBankT needs at least one voice");
40
41 public:
43 using Mode = typename Filter::Mode;
44 static constexpr std::size_t voice_count = Voices;
45
47 std::fill(std::begin(sample_rate_), std::end(sample_rate_), SampleType{44100.0f});
48 std::fill(std::begin(frequency_), std::end(frequency_), SampleType{1000.0f});
49 std::fill(std::begin(resonance_), std::end(resonance_), SampleType{0.707f});
50 }
51
54 void configure(std::size_t voice, Mode mode, SampleType sample_rate, SampleType frequency,
55 SampleType resonance) {
56 if (voice >= Voices)
57 return;
58 mode_[voice] = mode;
59 sample_rate_[voice] = sample_rate;
60 frequency_[voice] = frequency;
61 resonance_[voice] = resonance;
62 update(voice);
63 }
64
65 void set_sample_rate(std::size_t voice, SampleType sample_rate) {
66 if (voice >= Voices)
67 return;
68 sample_rate_[voice] = sample_rate;
69 update(voice);
70 }
71 void set_frequency(std::size_t voice, SampleType hz) {
72 if (voice >= Voices)
73 return;
74 frequency_[voice] = hz;
75 update(voice);
76 }
77 void set_resonance(std::size_t voice, SampleType q) {
78 if (voice >= Voices)
79 return;
80 resonance_[voice] = q;
81 update(voice);
82 }
83 void set_mode(std::size_t voice, Mode mode) {
84 if (voice >= Voices)
85 return;
86 mode_[voice] = mode;
87 }
88
90 typename Filter::Coefficients coefficients(std::size_t voice) const {
91 if (voice >= Voices)
92 return {};
93 return {g_[voice], k_[voice], a1_[voice], a2_[voice], a3_[voice]};
94 }
95
98 void process(const SampleType* in, SampleType* out) {
99 for (std::size_t v = 0; v < Voices; ++v) {
100 const SampleType input = in[v];
101 const SampleType v3 = input - ic2_[v];
102 const SampleType v1 = a1_[v] * ic1_[v] + a2_[v] * v3;
103 const SampleType v2 = ic2_[v] + a2_[v] * ic1_[v] + a3_[v] * v3;
104 ic1_[v] = detail::snap_to_zero_bits(SampleType{2.0f} * v1 - ic1_[v]);
105 ic2_[v] = detail::snap_to_zero_bits(SampleType{2.0f} * v2 - ic2_[v]);
106 const SampleType highpass = input - k_[v] * v1 - v2;
107 const SampleType notch = input - k_[v] * v1;
108 const Mode mode = mode_[v];
109 // Bit-operation selects (same values as conditionals) keep this
110 // loop free of control flow, so it vectorizes under GCC too.
111 const SampleType low_or_high =
112 detail::select_bits(mode == Mode::highpass, highpass, v2);
113 const SampleType band_or_notch = detail::select_bits(mode == Mode::notch, notch, v1);
114 const bool band_family = (mode == Mode::bandpass) | (mode == Mode::notch);
115 out[v] = detail::select_bits(band_family, band_or_notch, low_or_high);
116 }
117 }
118
121 void process_voices(SampleType* const* buffers, std::size_t num_samples) {
122 SampleType frame[Voices];
123 for (std::size_t n = 0; n < num_samples; ++n) {
124 for (std::size_t v = 0; v < Voices; ++v)
125 frame[v] = buffers[v][n];
126 process(frame, frame);
127 for (std::size_t v = 0; v < Voices; ++v)
128 buffers[v][n] = frame[v];
129 }
130 }
131
132 void reset(std::size_t voice) {
133 if (voice >= Voices)
134 return;
135 ic1_[voice] = SampleType{0};
136 ic2_[voice] = SampleType{0};
137 }
138
139 void reset() {
140 for (std::size_t v = 0; v < Voices; ++v)
141 reset(v);
142 }
143
144 private:
145 void update(std::size_t voice) {
146 const auto c = Filter::design(sample_rate_[voice], frequency_[voice], resonance_[voice]);
147 g_[voice] = c.g;
148 k_[voice] = c.k;
149 a1_[voice] = c.a1;
150 a2_[voice] = c.a2;
151 a3_[voice] = c.a3;
152 }
153
154 SampleType sample_rate_[Voices];
155 SampleType frequency_[Voices];
156 SampleType resonance_[Voices];
157 Mode mode_[Voices] = {};
158 SampleType g_[Voices] = {};
159 SampleType k_[Voices] = {};
160 SampleType a1_[Voices] = {};
161 SampleType a2_[Voices] = {};
162 SampleType a3_[Voices] = {};
163 SampleType ic1_[Voices] = {};
164 SampleType ic2_[Voices] = {};
165};
166
167template <std::size_t Voices = 16> using SvfBank = SvfBankT<float, Voices>;
168
169} // namespace pulp::signal
Voices independent SvfT voices advanced together.
Definition svf_bank.hpp:38
SvfBankT()
Definition svf_bank.hpp:46
void process(const SampleType *in, SampleType *out)
Advance every voice by one sample: out[v] = voice v's output for in[v].
Definition svf_bank.hpp:98
SvfT< SampleType > Filter
Definition svf_bank.hpp:42
void set_mode(std::size_t voice, Mode mode)
Definition svf_bank.hpp:83
typename Filter::Mode Mode
Definition svf_bank.hpp:43
void configure(std::size_t voice, Mode mode, SampleType sample_rate, SampleType frequency, SampleType resonance)
Install a coherent mode, rate, cutoff and resonance for one voice (SvfT::configure()).
Definition svf_bank.hpp:54
void set_frequency(std::size_t voice, SampleType hz)
Definition svf_bank.hpp:71
void reset()
Definition svf_bank.hpp:139
void process_voices(SampleType *const *buffers, std::size_t num_samples)
Advance every voice by num_samples samples in place, one buffer per voice (buffers[v] holds voice v's...
Definition svf_bank.hpp:121
Filter::Coefficients coefficients(std::size_t voice) const
The voice's coefficients (SvfT::design() for its current settings).
Definition svf_bank.hpp:90
void reset(std::size_t voice)
Definition svf_bank.hpp:132
void set_resonance(std::size_t voice, SampleType q)
Definition svf_bank.hpp:77
static constexpr std::size_t voice_count
Definition svf_bank.hpp:44
void set_sample_rate(std::size_t voice, SampleType sample_rate)
Definition svf_bank.hpp:65
Definition svf.hpp:16
static Coefficients design(SampleType sample_rate, SampleType frequency, SampleType resonance)
Definition svf.hpp:44
Scalar math helpers for real-time audio DSP.
@ Voices
Definition prepare_resources.hpp:26
T select_bits(bool condition, T if_true, T if_false) noexcept
condition ?
Definition fast_math.hpp:724
T snap_to_zero_bits(T x) noexcept
snap_to_zero() as bit operations (see select_bits()).
Definition fast_math.hpp:733
Definition additive_bank.hpp:218
@ c
Definition spectrum_trace.hpp:35
@ v2
Medium vibrato.
Definition scanner_vibrato.hpp:24
@ v3
Full vibrato.
Definition scanner_vibrato.hpp:25
@ v1
Shallow vibrato — scanner output only.
Definition scanner_vibrato.hpp:23
SvfBankT< float, Voices > SvfBank
Definition svf_bank.hpp:167
@ notch
Definition filter_morph.hpp:19
@ highpass
Definition filter_morph.hpp:19