6#include <pulp/signal/detail/leslie_common.hpp>
32template <
typename SampleType =
float>
69 static constexpr double kV1 = 0.33;
70 static constexpr double kV2 = 0.66;
71 static constexpr double kV3 = 1.00;
91 sample_rate_ = sample_rate > 0.0 ? sample_rate : sample_rate_;
93 scanner_.prepare(sample_rate_);
95 blocker_.set_pole(
static_cast<SampleType
>(
96 1.0 - kDcCornerHz * leslie_detail::kTwoPi / sample_rate_));
108 line_.discard_history();
121 if (!std::isfinite(hz))
return;
122 scan_hz_ = std::clamp(hz, 0.0, 100.0);
127 if (!std::isfinite(ms))
return;
133 if (!std::isfinite(frac))
return;
134 v1_ = std::clamp(frac, 0.0, 1.0);
138 if (!std::isfinite(frac))
return;
139 v2_ = std::clamp(frac, 0.0, 1.0);
143 if (!std::isfinite(frac))
return;
144 v3_ = std::clamp(frac, 0.0, 1.0);
149 if (!std::isfinite(mix01))
return;
150 chorus_mix_ = std::clamp(mix01, 0.0, 1.0);
171 return depth_frac_ * line_ms_ * 0.001 * 2.0 * scan_hz_;
179 if (!std::isfinite(
static_cast<double>(input))) {
181 return SampleType{0};
183 if (mode_ == Mode::off)
return input;
185 const double dry =
static_cast<double>(input);
186 const double x =
static_cast<double>(blocker_.process(input));
193 const double s =
static_cast<double>(scanner_.next_unipolar());
209 const double delay_samples = depth_frac_ * s * line_ms_ * 0.001 * sample_rate_;
211 line_.push(
static_cast<SampleType
>(x));
212 const int index =
static_cast<int>(std::floor(delay_samples));
213 const double frac = delay_samples -
static_cast<double>(index);
215 static_cast<double>(line_.read(index - 1)),
216 static_cast<double>(line_.read(index)),
217 static_cast<double>(line_.read(index + 1)),
218 static_cast<double>(line_.read(index + 2)));
225 return static_cast<SampleType
>(
snap_to_zero(dry_mix_ * dry + (1.0 - dry_mix_) * wet));
233 return static_cast<int>(std::ceil(
kMaxLineDelayMs * 0.001 * sample_rate)) +
234 leslie_detail::kInterpolatorMargin;
240 static constexpr double kDcCornerHz = 5.0;
262 dry_mix_ = chorus_mix_;
266 dry_mix_ = chorus_mix_;
270 dry_mix_ = chorus_mix_;
276 double sample_rate_ = 48000.0;
277 Mode mode_ = Mode::off;
284 double depth_frac_ = 0.0;
285 double dry_mix_ = 1.0;
287 DelayLineT<SampleType> line_{};
288 EffectLfoT<double> scanner_{};
289 DcBlocker<SampleType> blocker_{};
The motor-scanned tapped delay line.
Definition scanner_vibrato.hpp:33
static int worst_case_delay_samples(double sample_rate)
Definition scanner_vibrato.hpp:232
static constexpr double kV1
Definition scanner_vibrato.hpp:69
void set_v1_frac(double frac)
Definition scanner_vibrato.hpp:132
void set_v2_frac(double frac)
Definition scanner_vibrato.hpp:137
void set_mode(Mode mode)
Definition scanner_vibrato.hpp:113
static constexpr double kChorusMix
Definition scanner_vibrato.hpp:75
static constexpr double kLineDelayMs
Definition scanner_vibrato.hpp:55
void set_chorus_mix(double mix01)
Definition scanner_vibrato.hpp:148
void set_v3_frac(double frac)
Definition scanner_vibrato.hpp:142
void process_block(const SampleType *in, SampleType *out, int n)
Definition scanner_vibrato.hpp:228
void reset()
Definition scanner_vibrato.hpp:101
static constexpr double kMaxLineDelayMs
Definition scanner_vibrato.hpp:78
double depth_fraction() const
The fraction of the line the scanner currently traverses.
Definition scanner_vibrato.hpp:157
static constexpr double kV3
Definition scanner_vibrato.hpp:71
SampleType process(SampleType input)
Definition scanner_vibrato.hpp:178
void discard_history() noexcept
Definition scanner_vibrato.hpp:107
double peak_pitch_shift_ratio() const
The peak fractional pitch shift this setting produces, |Δf/f|.
Definition scanner_vibrato.hpp:170
static constexpr int latency_samples()
Zero, for the same reason as the Leslie: the line box's delay is the modelled electrical path,...
Definition scanner_vibrato.hpp:176
double dry_mix() const
How much dry is blended back.
Definition scanner_vibrato.hpp:161
Mode mode() const
Definition scanner_vibrato.hpp:118
static constexpr double kWorstCaseGain
Definition scanner_vibrato.hpp:86
static constexpr double kScanHz
Definition scanner_vibrato.hpp:44
static constexpr double kScanHz50
Definition scanner_vibrato.hpp:51
void prepare(double sample_rate)
Definition scanner_vibrato.hpp:90
static constexpr int kScannerTaps
Definition scanner_vibrato.hpp:64
static constexpr double kV2
Definition scanner_vibrato.hpp:70
ScannerVibratoT()
Definition scanner_vibrato.hpp:88
ScannerMode Mode
Definition scanner_vibrato.hpp:35
void set_scan_hz(double hz)
Definition scanner_vibrato.hpp:120
void set_line_ms(double ms)
Definition scanner_vibrato.hpp:126
void set_rate_hz(double hz)
Definition lfo.hpp:162
High-quality sample interpolation for delay lines and resampling.
The house low-frequency oscillator: seven waveforms plus a continuous shape morph,...
Definition additive_bank.hpp:218
@ off
Definition nonlinear_shaping.hpp:24
ScannerMode
The console's six-position vibrato/chorus switch, plus off.
Definition scanner_vibrato.hpp:21
@ c3
Full chorus. The lush one.
Definition scanner_vibrato.hpp:28
@ 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
@ c2
Medium chorus.
Definition scanner_vibrato.hpp:27
@ c1
Shallow chorus — scanner plus dry.
Definition scanner_vibrato.hpp:26
ScannerVibratoT< double > ScannerVibrato64
Definition scanner_vibrato.hpp:293
T snap_to_zero(T x)
Returns 0 if |x| < snap_threshold, else x.
Definition denormal.hpp:45
@ i
Definition formant_filter_bank.hpp:20
@ triangle
Definition lfo_sampling.hpp:55
ScannerVibratoT< float > ScannerVibrato
Definition scanner_vibrato.hpp:292
static SampleType lagrange(SampleType frac, SampleType ym1, SampleType y0, SampleType y1, SampleType y2)
4-point Lagrange interpolation.
Definition interpolator.hpp:60