28#include <pulp/signal/detail/simd_lanes.hpp>
40namespace lanes = signal::detail::lanes;
44template <
typename SampleType =
float>
47 void prepare(
int max_delay_samples, std::size_t stagger = 0) {
48 line_.prepare(max_delay_samples, stagger);
53 delay_ = std::clamp(samples, 2, line_.max_delay());
55 int delay()
const {
return delay_; }
60 SampleType
process(SampleType x, SampleType g) {
71 SampleType
process(SampleType x, SampleType g,
double fractional_delay) {
73 const SampleType delayed =
finite_or_zero(line_.read(fractional_delay));
84 SampleType* buf = line_.data();
85 const std::size_t w = line_.write_index();
86 const std::size_t r = (w -
static_cast<std::size_t
>(delay_)) & line_.mask();
87 run(x, buf + r, buf + w, n, g);
92 static void run(SampleType* __restrict x,
const SampleType* __restrict delayed,
93 SampleType* __restrict stored,
int n, SampleType g) {
94 for (
int k = 0; k < n; ++k) {
95 const SampleType v =
snap_to_zero(
static_cast<SampleType
>(x[k] + g * delayed[k]));
97 x[k] =
static_cast<SampleType
>(delayed[k] - g * v);
103 void process_block(SampleType* x,
int n, SampleType g,
const double* delays) {
105 for (
int k = 0; k < n; ++k) {
106 const SampleType delayed = line_.read_hermite_at(k, delays[k]);
107 stored[k] =
snap_to_zero(
static_cast<SampleType
>(x[k] + g * delayed));
108 x[k] =
static_cast<SampleType
>(delayed - g * stored[k]);
110 line_.push_block(stored, n);
120template <
typename SampleType =
float>
129 std::size_t stagger = 0) {
131 double base = max_base_ms;
132 for (
int s = 0; s < num_stages_; ++s) {
134 static_cast<int>(base * 0.001 * max_sample_rate) +
kHermiteGuard;
142 void configure(
double base_ms,
double sample_rate,
int offset_samples) {
143 double base = base_ms;
144 for (
int s = 0; s < num_stages_; ++s) {
146 static_cast<int>(base * 0.001 * sample_rate) + offset_samples;
147 stages_[s].set_delay(len);
148 base_delay_[
static_cast<std::size_t
>(s)] =
static_cast<double>(len);
151 min_delay_ = std::numeric_limits<int>::max();
152 for (
int s = 0; s < num_stages_; ++s)
153 min_delay_ = std::min(min_delay_, stages_[s].
delay());
157 for (
int s = 0; s < num_stages_; ++s) stages_[s].
reset();
170 for (
int s = 0; s < num_stages_; ++s)
171 sum += base_delay_[
static_cast<std::size_t
>(s)];
175 SampleType
process(SampleType x, SampleType g) {
176 for (
int s = 0; s < num_stages_; ++s) x = stages_[s].
process(x, g);
189 const int piece_max = std::max(1,
min_delay());
190 for (
int offset = 0; offset < n; offset += piece_max) {
191 const int piece = std::min(piece_max, n - offset);
192 if (num_stages_ == 4) {
193 fused4(x + offset, piece, g);
195 for (
int s = 0; s < num_stages_; ++s)
204 for (
int s = 0; s < num_stages_; ++s) {
205 const double d = base_delay_[
static_cast<std::size_t
>(s)];
206 for (
int k = 0; k < n; ++k)
207 delays[k] = d * (1.0 + depth * lfo[k]);
208 stages_[s].process_block(x, n, g, delays);
215 for (
int s = 0; s < num_stages_; ++s) {
216 const double d = base_delay_[
static_cast<std::size_t
>(s)];
217 x = stages_[s].process(x, g, d * (1.0 + depth * lfo));
226 void fused4(SampleType* x,
int n, SampleType g) {
239 bool spans4(
int n, SampleType** delayed, SampleType** stored) {
240 if (num_stages_ != 4 || n > min_delay_)
242 for (
int s = 0; s < 4; ++s) {
244 const std::size_t w = line.write_index();
245 const std::size_t r = (w -
static_cast<std::size_t
>(stages_[s].delay())) & line.mask();
246 delayed[s] = line.data() + r;
247 stored[s] = line.data() + w;
253 for (
int s = 0; s < 4; ++s)
254 stages_[s].line().advance(n);
262 static void run_spans4(SampleType* x,
int n, SampleType g, SampleType*
const* d,
263 SampleType*
const*
o) {
265 if constexpr (std::is_same_v<SampleType, float>) {
266 const lanes::F4 gv = lanes::splat(g);
267 for (; k + 4 <= n; k += 4) {
268 lanes::F4 v = lanes::load(x + k);
269 for (
int s = 0; s < 4; ++s) {
270 const lanes::F4 delayed = lanes::load(d[s] + k);
271 const lanes::F4
u = snap(v + gv * delayed);
272 lanes::store(
o[s] + k,
u);
273 v = delayed - gv *
u;
275 lanes::store(x + k, v);
280 for (
int s = 0; s < 4; ++s) {
281 const SampleType
u =
snap_to_zero(
static_cast<SampleType
>(v + g * d[s][k]));
283 v =
static_cast<SampleType
>(d[s][k] - g *
u);
291 static lanes::F4 snap(lanes::F4 v) {
293 lanes::splat(0.0f), v);
297 std::array<double, kMaxDiffusionStages> base_delay_{};
Definition diffusion.hpp:121
AllpassStage< SampleType > & stage(int s)
Definition diffusion.hpp:161
int min_delay() const
Definition diffusion.hpp:181
SampleType process(SampleType x, SampleType g)
Definition diffusion.hpp:175
int num_stages() const
Definition diffusion.hpp:160
void commit4(int n)
Definition diffusion.hpp:252
SampleType process_fluttered(SampleType x, SampleType g, double lfo, double depth)
Definition diffusion.hpp:214
static void run_spans4(SampleType *x, int n, SampleType g, SampleType *const *d, SampleType *const *o)
Definition diffusion.hpp:262
void process_block(SampleType *x, int n, SampleType g)
Definition diffusion.hpp:188
double total_delay() const
Definition diffusion.hpp:168
void reset()
Definition diffusion.hpp:156
bool spans4(int n, SampleType **delayed, SampleType **stored)
Definition diffusion.hpp:239
void process_block_fluttered(SampleType *x, int n, SampleType g, const double *lfo, double depth)
Definition diffusion.hpp:201
void prepare(double max_base_ms, double max_sample_rate, int num_stages, std::size_t stagger=0)
Definition diffusion.hpp:128
void configure(double base_ms, double sample_rate, int offset_samples)
Definition diffusion.hpp:142
Definition diffusion.hpp:45
static void run(SampleType *__restrict x, const SampleType *__restrict delayed, SampleType *__restrict stored, int n, SampleType g)
Definition diffusion.hpp:92
int delay() const
Definition diffusion.hpp:55
void reset()
Definition diffusion.hpp:50
void process_block(SampleType *x, int n, SampleType g, const double *delays)
Definition diffusion.hpp:103
void process_block(SampleType *x, int n, SampleType g)
Definition diffusion.hpp:83
SampleType process(SampleType x, SampleType g)
Definition diffusion.hpp:60
void set_delay(int samples)
Definition diffusion.hpp:52
FracDelayT< SampleType > & line()
Definition diffusion.hpp:56
SampleType process(SampleType x, SampleType g, double fractional_delay)
Definition diffusion.hpp:71
void prepare(int max_delay_samples, std::size_t stagger=0)
Definition diffusion.hpp:47
Definition frac_delay.hpp:36
T finite_or_zero(T value)
Definition sanitize.hpp:12
constexpr int kMaxDiffusionStages
Definition config.hpp:19
constexpr double kDiffusionStageShrink
Definition config.hpp:69
constexpr std::size_t kRingStaggerSamples
Definition config.hpp:199
constexpr int kHermiteGuard
Definition config.hpp:171
constexpr int kMaxBlockSamples
Definition config.hpp:190
constexpr T snap_threshold()
Threshold in absolute value below which a sample is treated as zero.
Definition denormal.hpp:36
@ delay
Definition envelope.hpp:57
T snap_to_zero(T x)
Returns 0 if |x| < snap_threshold, else x.
Definition denormal.hpp:45
@ u
Definition formant_filter_bank.hpp:20
@ o
Definition formant_filter_bank.hpp:20