diff --git a/src/sfizz/FlexEnvelope.cpp b/src/sfizz/FlexEnvelope.cpp index ae06c022..2ae0e04a 100644 --- a/src/sfizz/FlexEnvelope.cpp +++ b/src/sfizz/FlexEnvelope.cpp @@ -57,6 +57,7 @@ struct FlexEnvelope::Impl { void process(absl::Span out); bool advanceToStage(unsigned stageNumber); bool advanceToNextStage(); + void updateCurrentTimeAndLevel(); }; FlexEnvelope::FlexEnvelope(Resources &resources) @@ -97,18 +98,8 @@ void FlexEnvelope::start(unsigned triggerDelay) const FlexEGDescription& desc = *impl.desc_; impl.delayFramesLeft_ = triggerDelay; - - FlexEGPoint point; - if (!desc.points.empty()) - point = desc.points[0]; - - // - impl.stageSourceLevel_ = 0.0; - impl.stageTargetLevel_ = point.level; - impl.stageTime_ = point.time; - impl.stageSustained_ = desc.sustain == 0; - impl.stageCurve_ = &point.curve(); impl.currentFramesUntilRelease_ = absl::nullopt; + impl.advanceToStage(0); } void FlexEnvelope::setFreeRunning(bool freeRunning) @@ -172,6 +163,10 @@ void FlexEnvelope::Impl::process(absl::Span out) const FlexEGDescription& desc = *desc_; size_t numFrames = out.size(); const float samplePeriod = samplePeriod_; + + if (desc.dynamic) + updateCurrentTimeAndLevel(); + // Skip the initial delay, for frame-accurate trigger size_t skipFrames = std::min(numFrames, delayFramesLeft_); if (skipFrames > 0) { @@ -266,12 +261,11 @@ bool FlexEnvelope::Impl::advanceToStage(unsigned stageNumber) const FlexEGPoint& point = desc.points[stageNumber]; stageSourceLevel_ = currentLevel_; - stageTargetLevel_ = point.getLevel(midiState); - stageTime_ = point.getTime(midiState); + currentTime_ = 0.0f; + updateCurrentTimeAndLevel(); stageSustained_ = int(stageNumber) == desc.sustain; stageCurve_ = &point.curve(); - currentTime_ = 0; return true; }; @@ -280,4 +274,16 @@ bool FlexEnvelope::Impl::advanceToNextStage() return advanceToStage(currentStageNumber_ + 1); } +void FlexEnvelope::Impl::updateCurrentTimeAndLevel() +{ + const FlexEGDescription& desc = *desc_; + if (currentStageNumber_ >= desc.points.size()) + return; + + const FlexEGPoint& point = desc.points[currentStageNumber_]; + const MidiState& midiState = resources_->getMidiState(); + stageTargetLevel_ = point.getLevel(midiState); + stageTime_ = point.getTime(midiState); +} + } // namespace sfz diff --git a/src/sfizz/FlexEnvelope.h b/src/sfizz/FlexEnvelope.h index a72d280f..c33bf751 100644 --- a/src/sfizz/FlexEnvelope.h +++ b/src/sfizz/FlexEnvelope.h @@ -5,6 +5,7 @@ // If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz #pragma once +#include "MidiState.h" #include #include diff --git a/src/sfizz/Synth.cpp b/src/sfizz/Synth.cpp index 1e200b58..46b9f52d 100644 --- a/src/sfizz/Synth.cpp +++ b/src/sfizz/Synth.cpp @@ -70,7 +70,7 @@ Synth::Impl::Impl() MidiState& midiState = resources_.getMidiState(); genController_.reset(new ControllerSource(resources_, voiceManager_)); genLFO_.reset(new LFOSource(voiceManager_)); - genFlexEnvelope_.reset(new FlexEnvelopeSource(voiceManager_)); + genFlexEnvelope_.reset(new FlexEnvelopeSource(voiceManager_, midiState)); genADSREnvelope_.reset(new ADSREnvelopeSource(voiceManager_, midiState)); genChannelAftertouch_.reset(new ChannelAftertouchSource(voiceManager_, midiState)); genPolyAftertouch_.reset(new PolyAftertouchSource(voiceManager_, midiState)); diff --git a/src/sfizz/modulations/sources/FlexEnvelope.cpp b/src/sfizz/modulations/sources/FlexEnvelope.cpp index b3e85cfc..1a2698ad 100644 --- a/src/sfizz/modulations/sources/FlexEnvelope.cpp +++ b/src/sfizz/modulations/sources/FlexEnvelope.cpp @@ -14,9 +14,10 @@ namespace sfz { -FlexEnvelopeSource::FlexEnvelopeSource(VoiceManager& manager) - : voiceManager_(manager) +FlexEnvelopeSource::FlexEnvelopeSource(VoiceManager& manager, MidiState& midiState) + : voiceManager_(manager), midiState_(midiState) { + } void FlexEnvelopeSource::init(const ModKey& sourceKey, NumericId voiceId, unsigned delay) diff --git a/src/sfizz/modulations/sources/FlexEnvelope.h b/src/sfizz/modulations/sources/FlexEnvelope.h index 81b7a2f7..60cd5b14 100644 --- a/src/sfizz/modulations/sources/FlexEnvelope.h +++ b/src/sfizz/modulations/sources/FlexEnvelope.h @@ -7,13 +7,14 @@ #pragma once #include "../ModGenerator.h" #include "../../VoiceManager.h" +#include "../../MidiState.h" namespace sfz { class Synth; class FlexEnvelopeSource : public ModGenerator { public: - explicit FlexEnvelopeSource(VoiceManager& manager); + explicit FlexEnvelopeSource(VoiceManager& manager, MidiState& midiState); void init(const ModKey& sourceKey, NumericId voiceId, unsigned delay) override; void release(const ModKey& sourceKey, NumericId voiceId, unsigned delay) override; void cancelRelease(const ModKey& sourceKey, NumericId voiceId, unsigned delay) override; @@ -21,6 +22,7 @@ public: private: VoiceManager& voiceManager_; + MidiState& midiState_; }; } // namespace sfz