Make ADSREnvelope not a template

This commit is contained in:
Jean Pierre Cimalando 2021-02-01 10:30:17 +01:00
parent 9629fcad63
commit 9cb0a457a5
10 changed files with 62 additions and 104 deletions

View file

@ -36,7 +36,7 @@ public:
sfz::MidiState midiState;
sfz::Region region{0, midiState};
sfz::ADSREnvelope<float> envelope;
sfz::ADSREnvelope envelope;
std::vector<float> output;
};

View file

@ -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 \

View file

@ -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

View file

@ -11,33 +11,31 @@
namespace sfz {
template<class Type>
Type ADSREnvelope<Type>::secondsToSamples (Type timeInSeconds) const noexcept
using Float = ADSREnvelope::Float;
Float ADSREnvelope::secondsToSamples(Float timeInSeconds) const noexcept
{
return static_cast<int>(timeInSeconds * sampleRate);
};
template<class Type>
Type ADSREnvelope<Type>::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<class Type>
Type ADSREnvelope<Type>::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<Type>(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 <class Type>
void ADSREnvelope<Type>::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<Type>::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 <class Type>
Type ADSREnvelope<Type>::getNextValue() noexcept
Float ADSREnvelope::getNextValue() noexcept
{
if (shouldRelease && releaseDelay-- == 0)
currentState = State::Release;
@ -113,11 +110,10 @@ Type ADSREnvelope<Type>::getNextValue() noexcept
}
}
template <class Type>
void ADSREnvelope<Type>::getBlock(absl::Span<Type> output) noexcept
void ADSREnvelope::getBlock(absl::Span<Float> 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<Type>::getBlock(absl::Span<Type> output) noexcept
ASSERT(!hasNanInf(output));
}
template <class Type>
bool ADSREnvelope<Type>::isSmoothing() const noexcept
{
return (currentState != State::Done);
}
template <class Type>
bool ADSREnvelope<Type>::isReleased() const noexcept
{
return (currentState == State::Release) || shouldRelease;
}
template <class Type>
int ADSREnvelope<Type>::getRemainingDelay() const noexcept
{
return delay;
}
template <class Type>
void ADSREnvelope<Type>::startRelease(int releaseDelay) noexcept
void ADSREnvelope::startRelease(int releaseDelay) noexcept
{
shouldRelease = true;
this->releaseDelay = releaseDelay;
}
template <class Type>
void ADSREnvelope<Type>::setReleaseTime(Type timeInSeconds) noexcept
void ADSREnvelope::setReleaseTime(Float timeInSeconds) noexcept
{
releaseRate = secondsToExpRate(timeInSeconds);
}

View file

@ -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 Type>
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<Type> output) noexcept;
void getBlock(absl::Span<Float> 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 };

View file

@ -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<float>;
}

View file

@ -213,9 +213,9 @@ struct Voice::Impl
std::vector<std::unique_ptr<LFO>> lfos_;
std::vector<std::unique_ptr<FlexEnvelope>> flexEGs_;
ADSREnvelope<float> egAmplitude_;
std::unique_ptr<ADSREnvelope<float>> egPitch_;
std::unique_ptr<ADSREnvelope<float>> egFilter_;
ADSREnvelope egAmplitude_;
std::unique_ptr<ADSREnvelope> egPitch_;
std::unique_ptr<ADSREnvelope> 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<float>);
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<float>);
impl.egFilter_.reset(new ADSREnvelope);
else
impl.egFilter_.reset();
}
@ -1782,19 +1782,19 @@ Duration Voice::getLastPanningDuration() const noexcept
return impl.panningDuration_;
}
ADSREnvelope<float>* Voice::getAmplitudeEG()
ADSREnvelope* Voice::getAmplitudeEG()
{
Impl& impl = *impl_;
return &impl.egAmplitude_;
}
ADSREnvelope<float>* Voice::getPitchEG()
ADSREnvelope* Voice::getPitchEG()
{
Impl& impl = *impl_;
return impl.egPitch_.get();
}
ADSREnvelope<float>* Voice::getFilterEG()
ADSREnvelope* Voice::getFilterEG()
{
Impl& impl = *impl_;
return impl.egFilter_.get();

View file

@ -337,15 +337,15 @@ public:
/**
* @brief Get the SFZv1 amplitude EG, if existing
*/
ADSREnvelope<float>* getAmplitudeEG();
ADSREnvelope* getAmplitudeEG();
/**
* @brief Get the SFZv1 pitch EG, if existing
*/
ADSREnvelope<float>* getPitchEG();
ADSREnvelope* getPitchEG();
/**
* @brief Get the SFZv1 filter EG, if existing
*/
ADSREnvelope<float>* getFilterEG();
ADSREnvelope* getFilterEG();
/**
* @brief Get the trigger event

View file

@ -29,7 +29,7 @@ void ADSREnvelopeSource::init(const ModKey& sourceKey, NumericId<Voice> voiceId,
}
const Region* region = voice->getRegion();
ADSREnvelope<float>* eg = nullptr;
ADSREnvelope* eg = nullptr;
const EGDescription* desc = nullptr;
switch (sourceKey.id()) {
@ -66,7 +66,7 @@ void ADSREnvelopeSource::release(const ModKey& sourceKey, NumericId<Voice> voice
return;
}
ADSREnvelope<float>* eg = nullptr;
ADSREnvelope* eg = nullptr;
switch (sourceKey.id()) {
case ModId::AmpEG:
@ -97,7 +97,7 @@ void ADSREnvelopeSource::generate(const ModKey& sourceKey, NumericId<Voice> voic
return;
}
ADSREnvelope<float>* eg = nullptr;
ADSREnvelope* eg = nullptr;
switch (sourceKey.id()) {
case ModId::AmpEG:

View file

@ -16,7 +16,7 @@ using namespace Catch::literals;
TEST_CASE("[ADSREnvelope] Basic state")
{
sfz::ADSREnvelope<float> envelope;
sfz::ADSREnvelope envelope;
std::array<float, 5> output;
std::array<float, 5> 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<float> 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<float> 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<float> 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<float> 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<float> 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<float> 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<float> 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<float> 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<float> envelope;
sfz::ADSREnvelope envelope;
sfz::MidiState state;
sfz::Region region { state };
region.amplitudeEG.attack = 0.02f;