Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
fixed_ir_convolver.hpp
Go to the documentation of this file.
1#pragma once
2
5
9
10#include <algorithm>
11#include <cstddef>
12#include <cstdint>
13#include <type_traits>
14#include <vector>
15
16#if defined(__APPLE__)
17#include <TargetConditionals.h>
18#endif
19
20// The direct-engine table was measured on Apple Silicon Macs with the
21// Accelerate backend in single precision; it applies only there.
22#if defined(PULP_SIMD_DEFAULT_BACKEND_ACCELERATE) && defined(__aarch64__) && \
23 defined(TARGET_OS_OSX) && TARGET_OS_OSX
24#define PULP_FIXED_IR_MEASURED_TABLE 1
25#else
26#define PULP_FIXED_IR_MEASURED_TABLE 0
27#endif
28
29namespace pulp::signal {
30
32enum class ConvolutionBackend : std::uint8_t {
36};
37
61template <typename SampleType = float> class FixedIrConvolverT {
62 public:
66 void load_ir(const SampleType* ir, std::size_t ir_length, std::size_t block_size) {
67 load_ir(ir, ir_length, block_size, choose_backend(ir_length, block_size));
68 }
69
72 void load_ir(const SampleType* ir, std::size_t ir_length, std::size_t block_size,
73 ConvolutionBackend engine) {
74 direct_.set_coefficients({});
75 partitioned_ = PartitionedConvolverT<SampleType>{};
76 violations_ = 0;
77 if (ir == nullptr || ir_length == 0 || engine == ConvolutionBackend::none) {
78 backend_ = ConvolutionBackend::none;
79 block_size_ = 0;
80 return;
81 }
83 backend_ = engine;
84 if (backend_ == ConvolutionBackend::direct_fir)
85 direct_.set_coefficients(std::vector<SampleType>(ir, ir + ir_length));
86 else
87 partitioned_.load_ir(ir, ir_length, block_size);
88 }
89
92 static constexpr ConvolutionBackend choose_backend(std::size_t ir_length,
93 std::size_t block_size) noexcept {
96 }
97
114 static constexpr std::size_t direct_fir_limit(std::size_t block_size) noexcept {
115#if PULP_FIXED_IR_MEASURED_TABLE
116 if constexpr (!std::is_same_v<SampleType, float>) {
117 (void)block_size;
118 return 0;
119 } else {
121 case 1:
122 case 2:
123 case 4:
124 case 8:
125 return 4096;
126 case 16:
127 return 576;
128 case 32:
129 case 64:
130 return 128;
131 default:
132 return 64;
133 }
134 }
135#else
136 (void)block_size;
137 return 0;
138#endif
139 }
140
145 void process(const SampleType* input, SampleType* output, std::size_t num_samples) {
146 switch (backend_) {
148 if (input != output)
149 std::copy_n(input, num_samples, output);
150 return;
152 // The FFT engine fails closed and recovers on its own; only the
153 // count lives here, so both engines report it the same way.
154 if (num_samples != block_size_)
155 ++violations_;
156 partitioned_.process(input, output, num_samples);
157 return;
159 // A direct FIR has no partitioning, so any count up to the
160 // prepared maximum continues the stream.
161 if (num_samples > block_size_) {
162 std::fill_n(output, num_samples, SampleType{0});
163 ++violations_;
164 direct_.reset();
165 return;
166 }
167 direct_.process(input, output, static_cast<int>(num_samples));
168 return;
169 }
170 }
171
174 void reset() {
175 direct_.reset();
176 partitioned_.reset();
177 violations_ = 0;
178 }
179
180 [[nodiscard]] bool is_loaded() const noexcept {
181 return backend_ != ConvolutionBackend::none;
182 }
183
186 [[nodiscard]] std::size_t block_size() const noexcept {
187 return block_size_;
188 }
189 [[nodiscard]] std::size_t latency() const noexcept {
190 return 0;
191 }
192
196 [[nodiscard]] std::uint64_t block_size_violations() const noexcept {
197 return violations_;
198 }
199 [[nodiscard]] ConvolutionBackend backend() const noexcept {
200 return backend_;
201 }
202
203 private:
205 std::size_t block_size_ = 0;
206 std::uint64_t violations_ = 0;
209};
210
213
214} // namespace pulp::signal
FIR filter with arbitrary coefficients.
Definition fir_filter.hpp:39
Zero-latency convolution with one impulse response for the lifetime of a preparation,...
Definition fixed_ir_convolver.hpp:61
std::size_t block_size() const noexcept
Definition fixed_ir_convolver.hpp:186
void reset()
Clear the history so the next block starts from silence.
Definition fixed_ir_convolver.hpp:174
bool is_loaded() const noexcept
Definition fixed_ir_convolver.hpp:180
void process(const SampleType *input, SampleType *output, std::size_t num_samples)
Process one block.
Definition fixed_ir_convolver.hpp:145
static constexpr ConvolutionBackend choose_backend(std::size_t ir_length, std::size_t block_size) noexcept
The engine policy: a pure function of IR length and block size, so the choice is deterministic and ch...
Definition fixed_ir_convolver.hpp:92
std::size_t latency() const noexcept
Definition fixed_ir_convolver.hpp:189
void load_ir(const SampleType *ir, std::size_t ir_length, std::size_t block_size)
Load an IR on the engine choose_backend() selects.
Definition fixed_ir_convolver.hpp:66
static constexpr std::size_t direct_fir_limit(std::size_t block_size) noexcept
The longest IR run on the direct engine for a block size.
Definition fixed_ir_convolver.hpp:114
std::uint64_t block_size_violations() const noexcept
Calls to process() with a frame count the engine cannot take (any other than block_size() for the FFT...
Definition fixed_ir_convolver.hpp:196
ConvolutionBackend backend() const noexcept
Definition fixed_ir_convolver.hpp:199
void load_ir(const SampleType *ir, std::size_t ir_length, std::size_t block_size, ConvolutionBackend engine)
Load an IR on a named engine, for callers with their own measurements for the target.
Definition fixed_ir_convolver.hpp:72
Uniform partitioned convolution engine.
Definition convolver.hpp:46
Finite Impulse Response filter with configurable order and coefficients.
constexpr std::size_t convolver_block_size(std::size_t block_size) noexcept
The block size a convolver prepared for block_size accepts: the request rounded up to the next power ...
Definition convolver_messages.hpp:188
Definition additive_bank.hpp:218
FixedIrConvolverT< float > FixedIrConvolver
Definition fixed_ir_convolver.hpp:211
FixedIrConvolverT< double > FixedIrConvolver64
Definition fixed_ir_convolver.hpp:212
@ none
Definition dither.hpp:17
ConvolutionBackend
The engine a FixedIrConvolverT runs.
Definition fixed_ir_convolver.hpp:32
@ direct_fir
FirFilterT: a vectorized time-domain dot product.
Definition fixed_ir_convolver.hpp:34
@ none
No IR loaded; process() passes audio through.
Definition fixed_ir_convolver.hpp:33
@ partitioned_fft
PartitionedConvolverT: uniform overlap-save FFT.
Definition fixed_ir_convolver.hpp:35