95 constexpr double kMinAllowedHz = 0.1;
96 constexpr double kMaxAllowedSemitones = 4.0;
97 const double maxDeviation =
98 (kMaxAllowedSemitones * std::numbers::ln2 * sampleRate_)
99 / (2.0 * std::numbers::pi * kMinAllowedHz * 12.0);
100 const double required =
101 2.0 * maxDeviation +
static_cast<double>(kCentreOffset) + 128.0;
102 const int maxDelaySamples =
103 static_cast<int>(std::min(required,
static_cast<double>(1 << 28)));
105 delays_.resize(numChannels_);
106 phasors_.resize(numChannels_);
107 modPhasors_.resize(numChannels_);
108 readPos_.assign(
static_cast<size_t>(numChannels_), T(-1));
110 for (
int ch = 0; ch < numChannels_; ++ch)
112 delays_[ch].prepare(maxDelaySamples);
113 phasors_[ch].prepare(sampleRate_);
114 modPhasors_[ch].prepare(sampleRate_);
118 currentRate_ = rate_.load(std::memory_order_relaxed);
119 currentDepth_ = depthSemitones_.load(std::memory_order_relaxed);
120 currentModDepth_ = modDepth_.load(std::memory_order_relaxed);
129 const int numCh = std::min(buffer.getNumChannels(), numChannels_);
130 const int numSamples = buffer.getNumSamples();
131 if (numSamples == 0 || numCh == 0)
return;
134 const T targetRate = rate_.load(std::memory_order_relaxed);
135 const T targetDepth = depthSemitones_.load(std::memory_order_relaxed);
136 const T modRate = modRate_.load(std::memory_order_relaxed);
137 const T targetModDepth = modDepth_.load(std::memory_order_relaxed);
145 const T rateInc = (targetRate - currentRate_) /
static_cast<T
>(numSamples);
146 const T depthInc = (targetDepth - currentDepth_) /
static_cast<T
>(numSamples);
147 const T modDepthInc = (targetModDepth - currentModDepth_) /
static_cast<T
>(numSamples);
152 const bool fmActive = (targetModDepth > T(0)) || (currentModDepth_ > T(0));
154 constexpr T kLn2 =
static_cast<T
>(std::numbers::ln2_v<double>);
155 constexpr T kTwoPi =
static_cast<T
>(2.0 * std::numbers::pi);
156 const T deviationScaler = (kLn2 *
static_cast<T
>(sampleRate_)) / (kTwoPi * T(12));
158 for (
int ch = 0; ch < numCh; ++ch)
160 T* data = buffer.getChannel(ch);
161 auto& delay = delays_[ch];
162 auto& phasor = phasors_[ch];
163 auto& modPhasor = modPhasors_[ch];
165 modPhasor.setFrequency(modRate);
168 T smoothRate = currentRate_;
169 T smoothDepth = currentDepth_;
170 T smoothModDepth = currentModDepth_;
172 for (
int i = 0; i < numSamples; ++i)
174 smoothRate += rateInc;
175 smoothDepth += depthInc;
176 smoothModDepth += modDepthInc;
189 const T baseRate = std::max(smoothRate, T(0.1));
190 const T deviation = (smoothDepth * deviationScaler) / baseRate;
191 const T centre = deviation + kCentreOffset;
199 speed +=
fastSin(modPhasor.advance() * kTwoPi) * smoothModDepth;
200 phasor.setFrequency(baseRate * std::max(speed, T(0)));
201 const T lfo =
fastSin(phasor.advance() * kTwoPi);
205 const T delaySamples = std::clamp(centre + lfo * deviation, T(1.0),
206 static_cast<T
>(delay.getCapacity() - 4));
216 T& pos = readPos_[
static_cast<size_t>(ch)];
217 pos = (pos < T(0)) ? delaySamples
218 : pos + std::clamp(delaySamples - pos, -kMaxReadSlope, kMaxReadSlope);
220 data[i] = delay.readInterpolated(pos);
225 currentRate_ = targetRate;
226 currentDepth_ = targetDepth;
227 currentModDepth_ = targetModDepth;