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_);
109 for (
int ch = 0; ch < numChannels_; ++ch)
111 delays_[ch].prepare(maxDelaySamples);
112 phasors_[ch].prepare(sampleRate_);
113 modPhasors_[ch].prepare(sampleRate_);
117 currentRate_ = rate_.load(std::memory_order_relaxed);
118 currentDepth_ = depthSemitones_.load(std::memory_order_relaxed);
119 currentModDepth_ = modDepth_.load(std::memory_order_relaxed);
128 const int numCh = std::min(buffer.getNumChannels(), numChannels_);
129 const int numSamples = buffer.getNumSamples();
130 if (numSamples == 0 || numCh == 0)
return;
133 const T targetRate = rate_.load(std::memory_order_relaxed);
134 const T targetDepth = depthSemitones_.load(std::memory_order_relaxed);
135 const T modRate = modRate_.load(std::memory_order_relaxed);
136 const T targetModDepth = modDepth_.load(std::memory_order_relaxed);
144 const T rateInc = (targetRate - currentRate_) /
static_cast<T
>(numSamples);
145 const T depthInc = (targetDepth - currentDepth_) /
static_cast<T
>(numSamples);
146 const T modDepthInc = (targetModDepth - currentModDepth_) /
static_cast<T
>(numSamples);
151 const bool fmActive = (targetModDepth > T(0)) || (currentModDepth_ > T(0));
153 constexpr T kLn2 =
static_cast<T
>(std::numbers::ln2_v<double>);
154 constexpr T kTwoPi =
static_cast<T
>(2.0 * std::numbers::pi);
155 const T deviationScaler = (kLn2 *
static_cast<T
>(sampleRate_)) / (kTwoPi * T(12));
157 for (
int ch = 0; ch < numCh; ++ch)
159 T* data = buffer.getChannel(ch);
160 auto& delay = delays_[ch];
161 auto& phasor = phasors_[ch];
162 auto& modPhasor = modPhasors_[ch];
164 modPhasor.setFrequency(modRate);
167 T smoothRate = currentRate_;
168 T smoothDepth = currentDepth_;
169 T smoothModDepth = currentModDepth_;
171 for (
int i = 0; i < numSamples; ++i)
173 smoothRate += rateInc;
174 smoothDepth += depthInc;
175 smoothModDepth += modDepthInc;
179 T effectiveRate = std::max(smoothRate, T(0.01));
185 T modPhase = modPhasor.advance();
186 fmMod =
fastSin(modPhase * kTwoPi) * smoothModDepth;
192 T instantRate = std::max(effectiveRate * (T(1) + fmMod), T(0.1));
195 phasor.setFrequency(instantRate);
196 T phase = phasor.advance();
204 T ratioSqrt = std::sqrt(instantRate / effectiveRate);
205 T adjustedDepth = smoothDepth / ratioSqrt;
209 T deviation = (adjustedDepth * deviationScaler) / instantRate;
210 T centre = deviation + kCentreOffset;
212 T lfo =
fastSin(phase * kTwoPi);
218 T delaySamples = std::clamp(centre + lfo * deviation, T(1.0),
219 static_cast<T
>(delay.getCapacity() - 4));
221 data[i] = delay.readInterpolated(delaySamples);
226 currentRate_ = targetRate;
227 currentDepth_ = targetDepth;
228 currentModDepth_ = targetModDepth;