From 9cb0a457a5e53a9ff9651819e83bca30baba403b Mon Sep 17 00:00:00 2001 From: Jean Pierre Cimalando Date: Mon, 1 Feb 2021 10:30:17 +0100 Subject: [PATCH] Make ADSREnvelope not a template --- benchmarks/BM_ADSR.cpp | 2 +- common.mk | 1 - src/CMakeLists.txt | 2 +- src/sfizz/ADSREnvelope.cpp | 56 ++++++------------- src/sfizz/ADSREnvelope.h | 41 +++++++------- src/sfizz/FloatEnvelopes.cpp | 16 ------ src/sfizz/Voice.cpp | 16 +++--- src/sfizz/Voice.h | 6 +- .../modulations/sources/ADSREnvelope.cpp | 6 +- tests/ADSREnvelopeT.cpp | 20 +++---- 10 files changed, 62 insertions(+), 104 deletions(-) delete mode 100644 src/sfizz/FloatEnvelopes.cpp diff --git a/benchmarks/BM_ADSR.cpp b/benchmarks/BM_ADSR.cpp index c17a1a31..3dcfd6b1 100644 --- a/benchmarks/BM_ADSR.cpp +++ b/benchmarks/BM_ADSR.cpp @@ -36,7 +36,7 @@ public: sfz::MidiState midiState; sfz::Region region{0, midiState}; - sfz::ADSREnvelope envelope; + sfz::ADSREnvelope envelope; std::vector output; }; diff --git a/common.mk b/common.mk index fe7341b7..4efdbc57 100644 --- a/common.mk +++ b/common.mk @@ -86,7 +86,6 @@ SFIZZ_SOURCES = \ src/sfizz/FilterPool.cpp \ src/sfizz/FlexEGDescription.cpp \ src/sfizz/FlexEnvelope.cpp \ - src/sfizz/FloatEnvelopes.cpp \ src/sfizz/Interpolators.cpp \ src/sfizz/Logger.cpp \ src/sfizz/LFO.cpp \ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 26de3632..6786663e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -131,7 +131,7 @@ set(SFIZZ_SOURCES sfizz/MidiState.cpp sfizz/SfzHelpers.cpp sfizz/Oversampler.cpp - sfizz/FloatEnvelopes.cpp + sfizz/ADSREnvelope.cpp sfizz/Logger.cpp sfizz/SfzFilter.cpp sfizz/Curve.cpp diff --git a/src/sfizz/ADSREnvelope.cpp b/src/sfizz/ADSREnvelope.cpp index 803adbb6..b6fab78e 100644 --- a/src/sfizz/ADSREnvelope.cpp +++ b/src/sfizz/ADSREnvelope.cpp @@ -11,33 +11,31 @@ namespace sfz { -template -Type ADSREnvelope::secondsToSamples (Type timeInSeconds) const noexcept +using Float = ADSREnvelope::Float; + +Float ADSREnvelope::secondsToSamples(Float timeInSeconds) const noexcept { return static_cast(timeInSeconds * sampleRate); }; -template -Type ADSREnvelope::secondsToLinRate (Type timeInSeconds) const noexcept +Float ADSREnvelope::secondsToLinRate(Float timeInSeconds) const noexcept { if (timeInSeconds == 0) - return 1.0f; + return Float(1); return 1 / (sampleRate * timeInSeconds); }; -template -Type ADSREnvelope::secondsToExpRate (Type timeInSeconds) const noexcept +Float ADSREnvelope::secondsToExpRate(Float timeInSeconds) const noexcept { if (timeInSeconds == 0) - return 0.0f; + return Float(0.0); - timeInSeconds = std::max(25e-3, timeInSeconds); - return std::exp(-9.0 / (timeInSeconds * sampleRate)); + timeInSeconds = std::max(Float(25e-3), timeInSeconds); + return std::exp(Float(-9.0) / (timeInSeconds * sampleRate)); }; -template -void ADSREnvelope::reset(const EGDescription& desc, const Region& region, const MidiState& state, int delay, float velocity, float sampleRate) noexcept +void ADSREnvelope::reset(const EGDescription& desc, const Region& region, const MidiState& state, int delay, float velocity, float sampleRate) noexcept { this->sampleRate = sampleRate; @@ -54,15 +52,14 @@ void ADSREnvelope::reset(const EGDescription& desc, const Region& region, sustainThreshold = this->sustain + config::virtuallyZero; shouldRelease = false; freeRunning = ( - (this->sustain == 0.0f) + (this->sustain == Float(0.0)) || (region.loopMode == SfzLoopMode::one_shot && region.isOscillator()) ); currentValue = this->start; currentState = State::Delay; } -template -Type ADSREnvelope::getNextValue() noexcept +Float ADSREnvelope::getNextValue() noexcept { if (shouldRelease && releaseDelay-- == 0) currentState = State::Release; @@ -113,11 +110,10 @@ Type ADSREnvelope::getNextValue() noexcept } } -template -void ADSREnvelope::getBlock(absl::Span output) noexcept +void ADSREnvelope::getBlock(absl::Span output) noexcept { State currentState = this->currentState; - Type currentValue = this->currentValue; + Float currentValue = this->currentValue; bool shouldRelease = this->shouldRelease; int releaseDelay = this->releaseDelay; @@ -203,33 +199,13 @@ void ADSREnvelope::getBlock(absl::Span output) noexcept ASSERT(!hasNanInf(output)); } -template -bool ADSREnvelope::isSmoothing() const noexcept -{ - return (currentState != State::Done); -} - -template -bool ADSREnvelope::isReleased() const noexcept -{ - return (currentState == State::Release) || shouldRelease; -} - -template -int ADSREnvelope::getRemainingDelay() const noexcept -{ - return delay; -} - -template -void ADSREnvelope::startRelease(int releaseDelay) noexcept +void ADSREnvelope::startRelease(int releaseDelay) noexcept { shouldRelease = true; this->releaseDelay = releaseDelay; } -template -void ADSREnvelope::setReleaseTime(Type timeInSeconds) noexcept +void ADSREnvelope::setReleaseTime(Float timeInSeconds) noexcept { releaseRate = secondsToExpRate(timeInSeconds); } diff --git a/src/sfizz/ADSREnvelope.h b/src/sfizz/ADSREnvelope.h index eafd2f90..648267d4 100644 --- a/src/sfizz/ADSREnvelope.h +++ b/src/sfizz/ADSREnvelope.h @@ -13,12 +13,11 @@ namespace sfz { /** * @brief Describe an attack/delay/sustain/release envelope that can * produce its coefficient in a blockwise manner for SIMD-type operations. - * - * @tparam Type the underlying type */ -template class ADSREnvelope { public: + using Float = float; + ADSREnvelope() = default; /** * @brief Resets the ADSR envelope given a Region, the current midi state, and a delay and @@ -34,22 +33,22 @@ public: /** * @brief Get the next value for the envelope * - * @return Type + * @return Float */ - Type getNextValue() noexcept; + Float getNextValue() noexcept; /** * @brief Get a block of values for the envelope. This method tries hard to be efficient * and hopefully it is. * * @param output */ - void getBlock(absl::Span output) noexcept; + void getBlock(absl::Span output) noexcept; /** * @brief Set the release time for the envelope * * @param timeInSeconds */ - void setReleaseTime(Type timeInSeconds) noexcept; + void setReleaseTime(Float timeInSeconds) noexcept; /** * @brief Start the envelope release after a delay. * @@ -62,26 +61,26 @@ public: * @return true * @return false */ - bool isSmoothing() const noexcept; + bool isSmoothing() const noexcept { return currentState != State::Done; } /** * @brief Is the envelope released? * * @return true * @return false */ - bool isReleased() const noexcept; + bool isReleased() const noexcept { return currentState == State::Release || shouldRelease; } /** * @brief Get the remaining delay samples * * @return int */ - int getRemainingDelay() const noexcept; + int getRemainingDelay() const noexcept { return delay; } private: float sampleRate { config::defaultSampleRate }; - Type secondsToSamples (Type timeInSeconds) const noexcept; - Type secondsToLinRate (Type timeInSeconds) const noexcept; - Type secondsToExpRate (Type timeInSeconds) const noexcept; + Float secondsToSamples(Float timeInSeconds) const noexcept; + Float secondsToLinRate(Float timeInSeconds) const noexcept; + Float secondsToExpRate(Float timeInSeconds) const noexcept; enum class State { Delay, @@ -93,16 +92,16 @@ private: Done }; State currentState { State::Done }; - Type currentValue { 0.0 }; + Float currentValue { 0.0 }; int delay { 0 }; - Type attackStep { 0 }; - Type decayRate { 0 }; - Type releaseRate { 0 }; + Float attackStep { 0 }; + Float decayRate { 0 }; + Float releaseRate { 0 }; int hold { 0 }; - Type start { 0 }; - Type peak { 0 }; - Type sustain { 0 }; - Type sustainThreshold { config::virtuallyZero }; + Float start { 0 }; + Float peak { 0 }; + Float sustain { 0 }; + Float sustainThreshold { config::virtuallyZero }; int releaseDelay { 0 }; bool shouldRelease { false }; bool freeRunning { false }; diff --git a/src/sfizz/FloatEnvelopes.cpp b/src/sfizz/FloatEnvelopes.cpp deleted file mode 100644 index e4c5289c..00000000 --- a/src/sfizz/FloatEnvelopes.cpp +++ /dev/null @@ -1,16 +0,0 @@ -// SPDX-License-Identifier: BSD-2-Clause - -// This code is part of the sfizz library and is licensed under a BSD 2-clause -// license. You should have receive a LICENSE.md file along with the code. -// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz - -#include "ADSREnvelope.h" - -// Include the generic implementations -#include "ADSREnvelope.cpp" - -// And explicitely instantiate the float version -namespace sfz -{ - template class ADSREnvelope; -} diff --git a/src/sfizz/Voice.cpp b/src/sfizz/Voice.cpp index a93c925a..cdad7af7 100644 --- a/src/sfizz/Voice.cpp +++ b/src/sfizz/Voice.cpp @@ -213,9 +213,9 @@ struct Voice::Impl std::vector> lfos_; std::vector> flexEGs_; - ADSREnvelope egAmplitude_; - std::unique_ptr> egPitch_; - std::unique_ptr> egFilter_; + ADSREnvelope egAmplitude_; + std::unique_ptr egPitch_; + std::unique_ptr egFilter_; float bendStepFactor_ { centsFactor(1) }; WavetableOscillator waveOscillators_[config::oscillatorsPerVoice]; @@ -1553,7 +1553,7 @@ void Voice::setPitchEGEnabledPerVoice(bool havePitchEG) { Impl& impl = *impl_; if (havePitchEG) - impl.egPitch_.reset(new ADSREnvelope); + impl.egPitch_.reset(new ADSREnvelope); else impl.egPitch_.reset(); } @@ -1562,7 +1562,7 @@ void Voice::setFilterEGEnabledPerVoice(bool haveFilterEG) { Impl& impl = *impl_; if (haveFilterEG) - impl.egFilter_.reset(new ADSREnvelope); + impl.egFilter_.reset(new ADSREnvelope); else impl.egFilter_.reset(); } @@ -1782,19 +1782,19 @@ Duration Voice::getLastPanningDuration() const noexcept return impl.panningDuration_; } -ADSREnvelope* Voice::getAmplitudeEG() +ADSREnvelope* Voice::getAmplitudeEG() { Impl& impl = *impl_; return &impl.egAmplitude_; } -ADSREnvelope* Voice::getPitchEG() +ADSREnvelope* Voice::getPitchEG() { Impl& impl = *impl_; return impl.egPitch_.get(); } -ADSREnvelope* Voice::getFilterEG() +ADSREnvelope* Voice::getFilterEG() { Impl& impl = *impl_; return impl.egFilter_.get(); diff --git a/src/sfizz/Voice.h b/src/sfizz/Voice.h index 35428a6b..b6a07d38 100644 --- a/src/sfizz/Voice.h +++ b/src/sfizz/Voice.h @@ -337,15 +337,15 @@ public: /** * @brief Get the SFZv1 amplitude EG, if existing */ - ADSREnvelope* getAmplitudeEG(); + ADSREnvelope* getAmplitudeEG(); /** * @brief Get the SFZv1 pitch EG, if existing */ - ADSREnvelope* getPitchEG(); + ADSREnvelope* getPitchEG(); /** * @brief Get the SFZv1 filter EG, if existing */ - ADSREnvelope* getFilterEG(); + ADSREnvelope* getFilterEG(); /** * @brief Get the trigger event diff --git a/src/sfizz/modulations/sources/ADSREnvelope.cpp b/src/sfizz/modulations/sources/ADSREnvelope.cpp index 2f589282..fb4640e0 100644 --- a/src/sfizz/modulations/sources/ADSREnvelope.cpp +++ b/src/sfizz/modulations/sources/ADSREnvelope.cpp @@ -29,7 +29,7 @@ void ADSREnvelopeSource::init(const ModKey& sourceKey, NumericId voiceId, } const Region* region = voice->getRegion(); - ADSREnvelope* eg = nullptr; + ADSREnvelope* eg = nullptr; const EGDescription* desc = nullptr; switch (sourceKey.id()) { @@ -66,7 +66,7 @@ void ADSREnvelopeSource::release(const ModKey& sourceKey, NumericId voice return; } - ADSREnvelope* eg = nullptr; + ADSREnvelope* eg = nullptr; switch (sourceKey.id()) { case ModId::AmpEG: @@ -97,7 +97,7 @@ void ADSREnvelopeSource::generate(const ModKey& sourceKey, NumericId voic return; } - ADSREnvelope* eg = nullptr; + ADSREnvelope* eg = nullptr; switch (sourceKey.id()) { case ModId::AmpEG: diff --git a/tests/ADSREnvelopeT.cpp b/tests/ADSREnvelopeT.cpp index 424d8273..f0e12b79 100644 --- a/tests/ADSREnvelopeT.cpp +++ b/tests/ADSREnvelopeT.cpp @@ -16,7 +16,7 @@ using namespace Catch::literals; TEST_CASE("[ADSREnvelope] Basic state") { - sfz::ADSREnvelope envelope; + sfz::ADSREnvelope envelope; std::array output; std::array expected { 0.0, 0.0, 0.0, 0.0, 0.0 }; envelope.getBlock(absl::MakeSpan(output)); @@ -29,7 +29,7 @@ TEST_CASE("[ADSREnvelope] Basic state") TEST_CASE("[ADSREnvelope] Attack") { - sfz::ADSREnvelope envelope; + sfz::ADSREnvelope envelope; sfz::MidiState state; sfz::Region region { state }; region.amplitudeEG.attack = 0.02f; @@ -48,7 +48,7 @@ TEST_CASE("[ADSREnvelope] Attack") TEST_CASE("[ADSREnvelope] Attack again") { - sfz::ADSREnvelope envelope; + sfz::ADSREnvelope envelope; sfz::MidiState state; sfz::Region region { state }; region.amplitudeEG.attack = 0.03f; @@ -67,7 +67,7 @@ TEST_CASE("[ADSREnvelope] Attack again") TEST_CASE("[ADSREnvelope] Release") { - sfz::ADSREnvelope envelope; + sfz::ADSREnvelope envelope; sfz::MidiState state; sfz::Region region { state }; region.amplitudeEG.attack = 0.02f; @@ -89,7 +89,7 @@ TEST_CASE("[ADSREnvelope] Release") TEST_CASE("[ADSREnvelope] Delay") { - sfz::ADSREnvelope envelope; + sfz::ADSREnvelope envelope; sfz::MidiState state; sfz::Region region { state }; region.amplitudeEG.attack = 0.02f; @@ -111,7 +111,7 @@ TEST_CASE("[ADSREnvelope] Delay") TEST_CASE("[ADSREnvelope] Lower sustain") { - sfz::ADSREnvelope envelope; + sfz::ADSREnvelope envelope; sfz::MidiState state; sfz::Region region { state }; region.amplitudeEG.attack = 0.02f; @@ -132,7 +132,7 @@ TEST_CASE("[ADSREnvelope] Lower sustain") TEST_CASE("[ADSREnvelope] Decay") { - sfz::ADSREnvelope envelope; + sfz::ADSREnvelope envelope; sfz::MidiState state; sfz::Region region { state }; region.amplitudeEG.attack = 0.02f; @@ -154,7 +154,7 @@ TEST_CASE("[ADSREnvelope] Decay") TEST_CASE("[ADSREnvelope] Hold") { - sfz::ADSREnvelope envelope; + sfz::ADSREnvelope envelope; sfz::MidiState state; sfz::Region region { state }; region.amplitudeEG.attack = 0.02f; @@ -177,7 +177,7 @@ TEST_CASE("[ADSREnvelope] Hold") TEST_CASE("[ADSREnvelope] Hold with release") { - sfz::ADSREnvelope envelope; + sfz::ADSREnvelope envelope; sfz::MidiState state; sfz::Region region { state }; region.amplitudeEG.attack = 0.02f; @@ -202,7 +202,7 @@ TEST_CASE("[ADSREnvelope] Hold with release") TEST_CASE("[ADSREnvelope] Hold with release 2") { - sfz::ADSREnvelope envelope; + sfz::ADSREnvelope envelope; sfz::MidiState state; sfz::Region region { state }; region.amplitudeEG.attack = 0.02f;