diff --git a/src/sfizz/LFO.cpp b/src/sfizz/LFO.cpp index 33d31f70..06c823b5 100644 --- a/src/sfizz/LFO.cpp +++ b/src/sfizz/LFO.cpp @@ -49,7 +49,7 @@ void LFO::configure(const LFODescription* desc) impl_->desc_ = desc ? desc : &LFODescription::getDefault(); } -void LFO::start() +void LFO::start(unsigned triggerDelay) { Impl& impl = *impl_; const LFODescription& desc = *impl.desc_; @@ -59,7 +59,8 @@ void LFO::start() impl.sampleHoldMem_.fill(0.0f); const float delay = desc.delay; - impl.delayFramesLeft_ = (delay > 0) ? static_cast(std::ceil(sampleRate * delay)) : 0u; + size_t delayFrames = (delay > 0) ? static_cast(std::ceil(sampleRate * delay)) : 0u; + impl.delayFramesLeft_ = triggerDelay + delayFrames; impl.fadePosition_ = (desc.fade > 0) ? 0.0f : 1.0f; } diff --git a/src/sfizz/LFO.h b/src/sfizz/LFO.h index 3d75cad3..7a43fd13 100644 --- a/src/sfizz/LFO.h +++ b/src/sfizz/LFO.h @@ -67,7 +67,7 @@ public: Start processing a LFO as a region is triggered. Prepares the delay, phases, fade-in, etc.. */ - void start(); + void start(unsigned triggerDelay); /** Process a cycle of the oscillator. diff --git a/src/sfizz/Voice.cpp b/src/sfizz/Voice.cpp index 3321d761..56d7e6ce 100644 --- a/src/sfizz/Voice.cpp +++ b/src/sfizz/Voice.cpp @@ -150,7 +150,7 @@ void sfz::Voice::startVoice(Region* region, int delay, int number, float value, bendSmoother.reset(centsFactor(region->getBendInCents(resources.midiState.getPitchBend()))); egEnvelope.reset(region->amplitudeEG, *region, resources.midiState, delay, value, sampleRate); - resources.modMatrix.initVoice(id, region->getId()); + resources.modMatrix.initVoice(id, region->getId(), delay); } int sfz::Voice::getCurrentSampleQuality() const noexcept diff --git a/src/sfizz/modulations/ModGenerator.h b/src/sfizz/modulations/ModGenerator.h index 2229ec15..8c7a89e8 100644 --- a/src/sfizz/modulations/ModGenerator.h +++ b/src/sfizz/modulations/ModGenerator.h @@ -36,8 +36,9 @@ public: * * @param sourceKey identifier of the source to initialize * @param voiceId the particular voice to initialize, if per-voice + * @param delay the frame time when it happens */ - virtual void init(const ModKey& sourceKey, NumericId voiceId) = 0; + virtual void init(const ModKey& sourceKey, NumericId voiceId, unsigned delay) = 0; /** * @brief Generate a cycle of the modulator diff --git a/src/sfizz/modulations/ModMatrix.cpp b/src/sfizz/modulations/ModMatrix.cpp index 694a9cc0..913f3095 100644 --- a/src/sfizz/modulations/ModMatrix.cpp +++ b/src/sfizz/modulations/ModMatrix.cpp @@ -196,18 +196,18 @@ void ModMatrix::init() for (Impl::Source &source : impl.sources_) { const int flags = source.key.flags(); if (flags & kModIsPerCycle) - source.gen->init(source.key, {}); + source.gen->init(source.key, {}, 0); } } -void ModMatrix::initVoice(NumericId voiceId, NumericId regionId) +void ModMatrix::initVoice(NumericId voiceId, NumericId regionId, unsigned delay) { Impl& impl = *impl_; for (Impl::Source &source : impl.sources_) { const int flags = source.key.flags(); if ((flags & kModIsPerVoice) && source.key.region() == regionId) - source.gen->init(source.key, voiceId); + source.gen->init(source.key, voiceId, delay); } } diff --git a/src/sfizz/modulations/ModMatrix.h b/src/sfizz/modulations/ModMatrix.h index 0a451bec..21592360 100644 --- a/src/sfizz/modulations/ModMatrix.h +++ b/src/sfizz/modulations/ModMatrix.h @@ -106,7 +106,7 @@ public: * @brief Reinitialize modulation source for a given voice. * This must be called first after a voice enters active state. */ - void initVoice(NumericId voiceId, NumericId regionId); + void initVoice(NumericId voiceId, NumericId regionId, unsigned delay); /** * @brief Start modulation processing for the entire cycle. diff --git a/src/sfizz/modulations/sources/Controller.cpp b/src/sfizz/modulations/sources/Controller.cpp index 692b7556..1e611220 100644 --- a/src/sfizz/modulations/sources/Controller.cpp +++ b/src/sfizz/modulations/sources/Controller.cpp @@ -49,9 +49,10 @@ void ControllerSource::setSamplesPerBlock(unsigned count) (void)count; } -void ControllerSource::init(const ModKey& sourceKey, NumericId voiceId) +void ControllerSource::init(const ModKey& sourceKey, NumericId voiceId, unsigned delay) { (void)voiceId; + (void)delay; const ModKey::Parameters p = sourceKey.parameters(); if (p.smooth > 0) { diff --git a/src/sfizz/modulations/sources/Controller.h b/src/sfizz/modulations/sources/Controller.h index 1dfe26cd..d5320cf3 100644 --- a/src/sfizz/modulations/sources/Controller.h +++ b/src/sfizz/modulations/sources/Controller.h @@ -18,7 +18,7 @@ public: ~ControllerSource(); void setSampleRate(double sampleRate) override; void setSamplesPerBlock(unsigned count) override; - void init(const ModKey& sourceKey, NumericId voiceId) override; + void init(const ModKey& sourceKey, NumericId voiceId, unsigned delay) override; void generate(const ModKey& sourceKey, NumericId voiceId, absl::Span buffer) override; private: diff --git a/src/sfizz/modulations/sources/LFO.cpp b/src/sfizz/modulations/sources/LFO.cpp index 0f604898..2f06c34f 100644 --- a/src/sfizz/modulations/sources/LFO.cpp +++ b/src/sfizz/modulations/sources/LFO.cpp @@ -19,7 +19,7 @@ LFOSource::LFOSource(Synth &synth) { } -void LFOSource::init(const ModKey& sourceKey, NumericId voiceId) +void LFOSource::init(const ModKey& sourceKey, NumericId voiceId, unsigned delay) { Synth& synth = *synth_; unsigned lfoIndex = sourceKey.parameters().N; @@ -38,7 +38,7 @@ void LFOSource::init(const ModKey& sourceKey, NumericId voiceId) LFO* lfo = voice->getLFO(lfoIndex); lfo->configure(®ion->lfos[lfoIndex]); - lfo->start(); + lfo->start(delay); } void LFOSource::generate(const ModKey& sourceKey, NumericId voiceId, absl::Span buffer) diff --git a/src/sfizz/modulations/sources/LFO.h b/src/sfizz/modulations/sources/LFO.h index 83a1e30f..cf7e702f 100644 --- a/src/sfizz/modulations/sources/LFO.h +++ b/src/sfizz/modulations/sources/LFO.h @@ -13,7 +13,7 @@ class Synth; class LFOSource : public ModGenerator { public: explicit LFOSource(Synth &synth); - void init(const ModKey& sourceKey, NumericId voiceId) override; + void init(const ModKey& sourceKey, NumericId voiceId, unsigned delay) override; void generate(const ModKey& sourceKey, NumericId voiceId, absl::Span buffer) override; private: diff --git a/tests/LFOT.cpp b/tests/LFOT.cpp index 84c2795d..2271c2a8 100644 --- a/tests/LFOT.cpp +++ b/tests/LFOT.cpp @@ -31,7 +31,7 @@ static bool computeLFO(DataPoints& dp, const fs::path& sfzPath, double sampleRat std::vector outputMemory(numLfos * numFrames); for (size_t l = 0; l < numLfos; ++l) { - lfos[l].start(); + lfos[l].start(0); } std::vector> lfoOutputs(numLfos); diff --git a/tests/PlotLFO.cpp b/tests/PlotLFO.cpp index 06ccc553..8ce0aff5 100644 --- a/tests/PlotLFO.cpp +++ b/tests/PlotLFO.cpp @@ -119,7 +119,7 @@ int main(int argc, char* argv[]) std::vector outputMemory(numLfos * numFrames); for (size_t l = 0; l < numLfos; ++l) { - lfos[l].start(); + lfos[l].start(0); } std::vector> lfoOutputs(numLfos);