38template <
typename Transitioning,
typename Sample,
typename Block>
40 Sample&& sample, Block&& block) {
42 for (;
i < frames && transitioning(); ++
i)
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");
70 bool prepare(std::size_t section_capacity)
noexcept {
71 if (section_capacity == 0 || section_capacity > MaxSections)
73 for (
auto& section : sections_) {
77 capacity_ = section_capacity;
83 return capacity_ != 0;
88 std::size_t
size() const noexcept {
100 template <
typename CoefficientType, std::
size_t Extent>
104 return install<CoefficientType>(
108 template <
typename CoefficientType, std::
size_t Extent>
112 return install<CoefficientType>(
coefficients, transition);
115 SampleType
process(SampleType input)
noexcept {
116 for (std::size_t
i = 0;
i < size_; ++
i)
117 input = sections_[
i].
process(input);
137 SampleType* right_buffer, std::size_t num_samples)
noexcept {
140 left.size_, left_buffer, right_buffer,
144 left.process(left_buffer, num_samples);
145 right.process(right_buffer, num_samples);
149 for (std::size_t
i = 0;
i < MaxSections; ++
i)
154 return index < size_ ? sections_[index].coefficients() :
Coefficients{};
158 template <
typename CoefficientType>
162 static_assert(std::is_floating_point_v<CoefficientType>);
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))
180 const std::size_t old_size = size_;
188 for (std::size_t
i = old_size;
i < size_; ++
i)
190 for (std::size_t
i = size_;
i < old_size; ++
i)
196 return std::isfinite(
c.b0) && std::isfinite(
c.b1) && std::isfinite(
c.b2) &&
197 std::isfinite(
c.a1) && std::isfinite(
c.a2);
200 std::array<BiquadT<SampleType>, MaxSections> sections_{};
201 std::size_t capacity_ = 0;
202 std::size_t size_ = 0;
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