Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
sos_cascade.hpp
Go to the documentation of this file.
1#pragma once
2
5
7
8#include <array>
9#include <cmath>
10#include <cstddef>
11#include <span>
12#include <type_traits>
13
14namespace pulp::signal {
15
23
30
31namespace detail {
32
38template <typename Transitioning, typename Sample, typename Block>
39inline void transition_then_block(std::size_t frames, Transitioning&& transitioning,
40 Sample&& sample, Block&& block) {
41 std::size_t i = 0;
42 for (; i < frames && transitioning(); ++i)
43 sample(i);
44 if (i < frames)
45 block(i, frames - i);
46}
47
48} // namespace detail
49
60template <typename SampleType = float, std::size_t MaxSections = 16> class SosCascadeT {
61 static_assert(std::is_floating_point_v<SampleType>,
62 "SosCascadeT requires a floating-point sample type");
63 static_assert(MaxSections > 0, "SosCascadeT requires non-zero storage");
64
65 public:
67
70 bool prepare(std::size_t section_capacity) noexcept {
71 if (section_capacity == 0 || section_capacity > MaxSections)
72 return false;
73 for (auto& section : sections_) {
74 section.set_coefficients(Coefficients{});
75 section.reset();
76 }
77 capacity_ = section_capacity;
78 size_ = 0;
79 return true;
80 }
81
82 bool prepared() const noexcept {
83 return capacity_ != 0;
84 }
85 std::size_t capacity() const noexcept {
86 return capacity_;
87 }
88 std::size_t size() const noexcept {
89 return size_;
90 }
91 static constexpr std::size_t storage_capacity() noexcept {
92 return MaxSections;
93 }
94
100 template <typename CoefficientType, std::size_t Extent>
104 return install<CoefficientType>(
105 std::span<const BiquadCoefficientsT<CoefficientType>>(coefficients), transition);
106 }
107
108 template <typename CoefficientType, std::size_t Extent>
112 return install<CoefficientType>(coefficients, transition);
113 }
114
115 SampleType process(SampleType input) noexcept {
116 for (std::size_t i = 0; i < size_; ++i)
117 input = sections_[i].process(input);
118 return input;
119 }
120
126 void process(SampleType* buffer, std::size_t num_samples) noexcept {
127 BiquadT<SampleType>::process_chain(sections_.data(), size_, buffer, num_samples);
128 }
129
136 static void process_stereo(SosCascadeT& left, SosCascadeT& right, SampleType* left_buffer,
137 SampleType* right_buffer, std::size_t num_samples) noexcept {
138 if (left.size_ == right.size_) {
139 BiquadT<SampleType>::process_chain_stereo(left.sections_.data(), right.sections_.data(),
140 left.size_, left_buffer, right_buffer,
141 num_samples);
142 return;
143 }
144 left.process(left_buffer, num_samples);
145 right.process(right_buffer, num_samples);
146 }
147
148 void reset() noexcept {
149 for (std::size_t i = 0; i < MaxSections; ++i)
150 sections_[i].reset();
151 }
152
153 Coefficients coefficients(std::size_t index) const noexcept {
154 return index < size_ ? sections_[index].coefficients() : Coefficients{};
155 }
156
157 private:
158 template <typename CoefficientType>
160 install(std::span<const BiquadCoefficientsT<CoefficientType>> coefficients,
161 SosCascadeTransition transition) noexcept {
162 static_assert(std::is_floating_point_v<CoefficientType>);
163 if (!prepared())
165 if (coefficients.size() > capacity_)
167
168 for (std::size_t i = 0; i < coefficients.size(); ++i) {
169 const auto& source = coefficients[i];
170 const Coefficients candidate{
171 static_cast<SampleType>(source.b0), static_cast<SampleType>(source.b1),
172 static_cast<SampleType>(source.b2), static_cast<SampleType>(source.a1),
173 static_cast<SampleType>(source.a2)};
174 if (!finite(candidate))
176 if (!biquad_is_stable(candidate))
178 }
179
180 const std::size_t old_size = size_;
181 for (std::size_t i = 0; i < coefficients.size(); ++i)
182 sections_[i].set_coefficients(coefficients[i]);
183 size_ = coefficients.size();
184
185 if (transition == SosCascadeTransition::reset_state) {
186 reset();
187 } else {
188 for (std::size_t i = old_size; i < size_; ++i)
189 sections_[i].reset();
190 for (std::size_t i = size_; i < old_size; ++i)
191 sections_[i].reset();
192 }
194 }
195 static bool finite(const Coefficients& c) noexcept {
196 return std::isfinite(c.b0) && std::isfinite(c.b1) && std::isfinite(c.b2) &&
197 std::isfinite(c.a1) && std::isfinite(c.a2);
198 }
199
200 std::array<BiquadT<SampleType>, MaxSections> sections_{};
201 std::size_t capacity_ = 0;
202 std::size_t size_ = 0;
203};
204
207
208} // namespace pulp::signal
static void process_chain_stereo(BiquadT *left, BiquadT *right, std::size_t count, SampleType *left_buffer, SampleType *right_buffer, std::size_t num_samples) noexcept
process_chain() for two channels at once, each through its own chain of count sections,...
Definition biquad.hpp:334
static void process_chain(BiquadT *sections, std::size_t count, SampleType *buffer, std::size_t num_samples) noexcept
Run a chain of sections (a cascade: each section's output feeds the next) over a buffer in place.
Definition biquad.hpp:320
Executes a bounded cascade of normalized second-order sections (SOS).
Definition sos_cascade.hpp:60
std::size_t size() const noexcept
Definition sos_cascade.hpp:88
static void process_stereo(SosCascadeT &left, SosCascadeT &right, SampleType *left_buffer, SampleType *right_buffer, std::size_t num_samples) noexcept
Process two channels in place, each through its own cascade, with the two channels in vector lanes (B...
Definition sos_cascade.hpp:136
static constexpr std::size_t storage_capacity() noexcept
Definition sos_cascade.hpp:91
std::size_t capacity() const noexcept
Definition sos_cascade.hpp:85
void reset() noexcept
Definition sos_cascade.hpp:148
SampleType process(SampleType input) noexcept
Definition sos_cascade.hpp:115
Coefficients coefficients(std::size_t index) const noexcept
Definition sos_cascade.hpp:153
bool prepare(std::size_t section_capacity) noexcept
Select the usable prefix of fixed storage and clear the active cascade.
Definition sos_cascade.hpp:70
BiquadCoefficientsT< SampleType > Coefficients
Definition sos_cascade.hpp:66
SosCascadeInstallStatus set_coefficients(std::span< BiquadCoefficientsT< CoefficientType >, Extent > coefficients, SosCascadeTransition transition=SosCascadeTransition::reset_state) noexcept
Install one complete SOS cascade.
Definition sos_cascade.hpp:102
void process(SampleType *buffer, std::size_t num_samples) noexcept
Process a buffer in place through BiquadT::process_chain().
Definition sos_cascade.hpp:126
bool prepared() const noexcept
Definition sos_cascade.hpp:82
SosCascadeInstallStatus set_coefficients(std::span< const BiquadCoefficientsT< CoefficientType >, Extent > coefficients, SosCascadeTransition transition=SosCascadeTransition::reset_state) noexcept
Definition sos_cascade.hpp:110
void transition_then_block(std::size_t frames, Transitioning &&transitioning, Sample &&sample, Block &&block)
The block path the cascade EQs share: a design transition (crossfade or coefficient ramp) runs sample...
Definition sos_cascade.hpp:39
Definition additive_bank.hpp:218
@ buffer
A borrowed static buffer with a traversable playhead.
Definition granular.hpp:110
@ right
Definition multi_channel_meter.hpp:67
@ left
Definition multi_channel_meter.hpp:66
SosCascadeTransition
Coefficient changes take effect immediately.
Definition sos_cascade.hpp:26
@ preserve_state
Definition sos_cascade.hpp:28
@ reset_state
Definition sos_cascade.hpp:27
@ c
Definition spectrum_trace.hpp:35
@ not_prepared
Definition comb_filter.hpp:33
SosCascadeInstallStatus
Definition sos_cascade.hpp:16
@ non_finite
Definition sos_cascade.hpp:20
@ over_capacity
Definition sos_cascade.hpp:19
@ installed
Definition sos_cascade.hpp:17
@ unstable
Definition sos_cascade.hpp:21
@ not_prepared
Definition sos_cascade.hpp:18
SosCascadeT< float > SosCascade
Definition sos_cascade.hpp:205
SosCascadeT< double > SosCascade64
Definition sos_cascade.hpp:206
bool biquad_is_stable(const BiquadCoefficientsT< SampleType > &c) noexcept
Return whether a normalized real biquad's poles are strictly inside the unit circle.
Definition biquad.hpp:34
@ over_capacity
Definition graphic_eq.hpp:28
@ i
Definition formant_filter_bank.hpp:20
@ non_finite
Definition formant_filter_bank.hpp:26
@ unstable
Definition formant_filter_bank.hpp:29
Definition biquad.hpp:24