Merge pull request #759 from jpcima/normalize-bis

Fix the value bounds in ADSR
This commit is contained in:
JP Cimalando 2021-04-01 02:09:14 +02:00 committed by GitHub
commit 798f501a65
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 38 additions and 35 deletions

View file

@ -13,14 +13,17 @@ namespace sfz {
using Float = ADSREnvelope::Float; using Float = ADSREnvelope::Float;
Float ADSREnvelope::secondsToSamples(Float timeInSeconds) const noexcept int ADSREnvelope::secondsToSamples(Float timeInSeconds) const noexcept
{ {
if (timeInSeconds <= 0)
return Float(0);
return static_cast<int>(timeInSeconds * sampleRate); return static_cast<int>(timeInSeconds * sampleRate);
}; };
Float ADSREnvelope::secondsToLinRate(Float timeInSeconds) const noexcept Float ADSREnvelope::secondsToLinRate(Float timeInSeconds) const noexcept
{ {
if (timeInSeconds == 0) if (timeInSeconds <= 0)
return Float(1); return Float(1);
return 1 / (sampleRate * timeInSeconds); return 1 / (sampleRate * timeInSeconds);
@ -28,7 +31,7 @@ Float ADSREnvelope::secondsToLinRate(Float timeInSeconds) const noexcept
Float ADSREnvelope::secondsToExpRate(Float timeInSeconds) const noexcept Float ADSREnvelope::secondsToExpRate(Float timeInSeconds) const noexcept
{ {
if (timeInSeconds == 0) if (timeInSeconds <= 0)
return Float(0.0); return Float(0.0);
timeInSeconds = std::max(Float(25e-3), timeInSeconds); timeInSeconds = std::max(Float(25e-3), timeInSeconds);
@ -44,8 +47,8 @@ void ADSREnvelope::reset(const EGDescription& desc, const Region& region, const
this->decayRate = secondsToExpRate(desc.getDecay(state, velocity)); this->decayRate = secondsToExpRate(desc.getDecay(state, velocity));
this->releaseRate = secondsToExpRate(desc.getRelease(state, velocity)); this->releaseRate = secondsToExpRate(desc.getRelease(state, velocity));
this->hold = secondsToSamples(desc.getHold(state, velocity)); this->hold = secondsToSamples(desc.getHold(state, velocity));
this->sustain = desc.getSustain(state, velocity); this->sustain = clamp(desc.getSustain(state, velocity), 0.0f, 1.0f);
this->start = desc.getStart(state, velocity); this->start = clamp(desc.getStart(state, velocity), 0.0f, 1.0f);
releaseDelay = 0; releaseDelay = 0;
sustainThreshold = this->sustain + config::virtuallyZero; sustainThreshold = this->sustain + config::virtuallyZero;

View file

@ -72,7 +72,7 @@ public:
private: private:
float sampleRate { config::defaultSampleRate }; float sampleRate { config::defaultSampleRate };
Float secondsToSamples(Float timeInSeconds) const noexcept; int secondsToSamples(Float timeInSeconds) const noexcept;
Float secondsToLinRate(Float timeInSeconds) const noexcept; Float secondsToLinRate(Float timeInSeconds) const noexcept;
Float secondsToExpRate(Float timeInSeconds) const noexcept; Float secondsToExpRate(Float timeInSeconds) const noexcept;

View file

@ -104,7 +104,7 @@ struct EGDescription {
for (auto& mod: ccAttack) { for (auto& mod: ccAttack) {
returnedValue += state.getCCValue(mod.cc) * mod.data; returnedValue += state.getCCValue(mod.cc) * mod.data;
} }
return Default::egTime.bounds.clamp(returnedValue); return returnedValue;
} }
/** /**
* @brief Get the decay with possibly a CC modifier and a velocity modifier * @brief Get the decay with possibly a CC modifier and a velocity modifier
@ -120,7 +120,7 @@ struct EGDescription {
for (auto& mod: ccDecay) { for (auto& mod: ccDecay) {
returnedValue += state.getCCValue(mod.cc) * mod.data; returnedValue += state.getCCValue(mod.cc) * mod.data;
} }
return Default::egTime.bounds.clamp(returnedValue); return returnedValue;
} }
/** /**
* @brief Get the delay with possibly a CC modifier and a velocity modifier * @brief Get the delay with possibly a CC modifier and a velocity modifier
@ -136,7 +136,7 @@ struct EGDescription {
for (auto& mod: ccDelay) { for (auto& mod: ccDelay) {
returnedValue += state.getCCValue(mod.cc) * mod.data; returnedValue += state.getCCValue(mod.cc) * mod.data;
} }
return Default::egTime.bounds.clamp(returnedValue); return returnedValue;
} }
/** /**
* @brief Get the holding duration with possibly a CC modifier and a velocity modifier * @brief Get the holding duration with possibly a CC modifier and a velocity modifier
@ -152,7 +152,7 @@ struct EGDescription {
for (auto& mod: ccHold) { for (auto& mod: ccHold) {
returnedValue += state.getCCValue(mod.cc) * mod.data; returnedValue += state.getCCValue(mod.cc) * mod.data;
} }
return Default::egTime.bounds.clamp(returnedValue); return returnedValue;
} }
/** /**
* @brief Get the release duration with possibly a CC modifier and a velocity modifier * @brief Get the release duration with possibly a CC modifier and a velocity modifier
@ -168,7 +168,7 @@ struct EGDescription {
for (auto& mod: ccRelease) { for (auto& mod: ccRelease) {
returnedValue += state.getCCValue(mod.cc) * mod.data; returnedValue += state.getCCValue(mod.cc) * mod.data;
} }
return Default::egTime.bounds.clamp(returnedValue); return returnedValue;
} }
/** /**
* @brief Get the starting level with possibly a CC modifier and a velocity modifier * @brief Get the starting level with possibly a CC modifier and a velocity modifier
@ -184,7 +184,7 @@ struct EGDescription {
for (auto& mod: ccStart) { for (auto& mod: ccStart) {
returnedValue += state.getCCValue(mod.cc) * mod.data; returnedValue += state.getCCValue(mod.cc) * mod.data;
} }
return Default::egPercent.bounds.clamp(returnedValue); return returnedValue;
} }
/** /**
* @brief Get the sustain level with possibly a CC modifier and a velocity modifier * @brief Get the sustain level with possibly a CC modifier and a velocity modifier
@ -200,7 +200,7 @@ struct EGDescription {
for (auto& mod: ccSustain) { for (auto& mod: ccSustain) {
returnedValue += state.getCCValue(mod.cc) * mod.data; returnedValue += state.getCCValue(mod.cc) * mod.data;
} }
return Default::egPercent.bounds.clamp(returnedValue); return returnedValue;
} }
LEAK_DETECTOR(EGDescription); LEAK_DETECTOR(EGDescription);
}; };

View file

@ -19,12 +19,12 @@ TEST_CASE("[EGDescription] Attack range")
eg.vel2attack = -1.27f; eg.vel2attack = -1.27f;
eg.ccAttack[63] = 1.27f; eg.ccAttack[63] = 1.27f;
REQUIRE(eg.getAttack(state, 0_norm) == 1.0f); REQUIRE(eg.getAttack(state, 0_norm) == 1.0f);
REQUIRE(eg.getAttack(state, 127_norm) == 0.0f); //REQUIRE(eg.getAttack(state, 127_norm) == 0.0f);
state.ccEvent(0, 63, 127_norm); state.ccEvent(0, 63, 127_norm);
REQUIRE(eg.getAttack(state, 127_norm) == 1.0f); REQUIRE(eg.getAttack(state, 127_norm) == 1.0f);
REQUIRE(eg.getAttack(state, 0_norm) == 2.27f); REQUIRE(eg.getAttack(state, 0_norm) == 2.27f);
eg.ccAttack[63] = 127.0f; //eg.ccAttack[63] = 127.0f;
REQUIRE(eg.getAttack(state, 0_norm) == 100.0f); //REQUIRE(eg.getAttack(state, 0_norm) == 100.0f);
eg.ccAttack[63] = 1.27f; eg.ccAttack[63] = 1.27f;
eg.ccAttack[65] = 1.0f; eg.ccAttack[65] = 1.0f;
REQUIRE(eg.getAttack(state, 0_norm) == 2.27f); REQUIRE(eg.getAttack(state, 0_norm) == 2.27f);
@ -42,12 +42,12 @@ TEST_CASE("[EGDescription] Delay range")
eg.vel2delay = -1.27f; eg.vel2delay = -1.27f;
eg.ccDelay[63] = 1.27f; eg.ccDelay[63] = 1.27f;
REQUIRE(eg.getDelay(state, 0_norm) == 1.0f); REQUIRE(eg.getDelay(state, 0_norm) == 1.0f);
REQUIRE(eg.getDelay(state, 127_norm) == 0.0f); //REQUIRE(eg.getDelay(state, 127_norm) == 0.0f);
state.ccEvent(0, 63, 127_norm); state.ccEvent(0, 63, 127_norm);
REQUIRE(eg.getDelay(state, 127_norm) == 1.0f); REQUIRE(eg.getDelay(state, 127_norm) == 1.0f);
REQUIRE(eg.getDelay(state, 0_norm) == 2.27f); REQUIRE(eg.getDelay(state, 0_norm) == 2.27f);
eg.ccDelay[63] = 127.0f; //eg.ccDelay[63] = 127.0f;
REQUIRE(eg.getDelay(state, 0_norm) == 100.0f); //REQUIRE(eg.getDelay(state, 0_norm) == 100.0f);
eg.ccDelay[63] = 1.27f; eg.ccDelay[63] = 1.27f;
eg.ccDelay[65] = 1.0f; eg.ccDelay[65] = 1.0f;
REQUIRE(eg.getDelay(state, 0_norm) == 2.27f); REQUIRE(eg.getDelay(state, 0_norm) == 2.27f);
@ -65,12 +65,12 @@ TEST_CASE("[EGDescription] Decay range")
eg.vel2decay = -1.27f; eg.vel2decay = -1.27f;
eg.ccDecay[63] = 1.27f; eg.ccDecay[63] = 1.27f;
REQUIRE(eg.getDecay(state, 0_norm) == 1.0f); REQUIRE(eg.getDecay(state, 0_norm) == 1.0f);
REQUIRE(eg.getDecay(state, 127_norm) == 0.0f); //REQUIRE(eg.getDecay(state, 127_norm) == 0.0f);
state.ccEvent(0, 63, 127_norm); state.ccEvent(0, 63, 127_norm);
REQUIRE(eg.getDecay(state, 127_norm) == 1.0f); REQUIRE(eg.getDecay(state, 127_norm) == 1.0f);
REQUIRE(eg.getDecay(state, 0_norm) == 2.27f); REQUIRE(eg.getDecay(state, 0_norm) == 2.27f);
eg.ccDecay[63] = 127.0f; //eg.ccDecay[63] = 127.0f;
REQUIRE(eg.getDecay(state, 0_norm) == 100.0f); //REQUIRE(eg.getDecay(state, 0_norm) == 100.0f);
eg.ccDecay[63] = 1.27f; eg.ccDecay[63] = 1.27f;
eg.ccDecay[65] = 1.0f; eg.ccDecay[65] = 1.0f;
REQUIRE(eg.getDecay(state, 0_norm) == 2.27f); REQUIRE(eg.getDecay(state, 0_norm) == 2.27f);
@ -88,12 +88,12 @@ TEST_CASE("[EGDescription] Release range")
eg.vel2release = -1.27f; eg.vel2release = -1.27f;
eg.ccRelease[63] = 1.27f; eg.ccRelease[63] = 1.27f;
REQUIRE(eg.getRelease(state, 0_norm) == 1.0f); REQUIRE(eg.getRelease(state, 0_norm) == 1.0f);
REQUIRE(eg.getRelease(state, 127_norm) == 0.0f); //REQUIRE(eg.getRelease(state, 127_norm) == 0.0f);
state.ccEvent(0, 63, 127_norm); state.ccEvent(0, 63, 127_norm);
REQUIRE(eg.getRelease(state, 127_norm) == 1.0f); REQUIRE(eg.getRelease(state, 127_norm) == 1.0f);
REQUIRE(eg.getRelease(state, 0_norm) == 2.27f); REQUIRE(eg.getRelease(state, 0_norm) == 2.27f);
eg.ccRelease[63] = 127.0f; //eg.ccRelease[63] = 127.0f;
REQUIRE(eg.getRelease(state, 0_norm) == 100.0f); //REQUIRE(eg.getRelease(state, 0_norm) == 100.0f);
eg.ccRelease[63] = 1.27f; eg.ccRelease[63] = 1.27f;
eg.ccRelease[65] = 1.0f; eg.ccRelease[65] = 1.0f;
REQUIRE(eg.getRelease(state, 0_norm) == 2.27f); REQUIRE(eg.getRelease(state, 0_norm) == 2.27f);
@ -111,12 +111,12 @@ TEST_CASE("[EGDescription] Hold range")
eg.vel2hold = -1.27f; eg.vel2hold = -1.27f;
eg.ccHold[63] = 1.27f; eg.ccHold[63] = 1.27f;
REQUIRE(eg.getHold(state, 0_norm) == 1.0f); REQUIRE(eg.getHold(state, 0_norm) == 1.0f);
REQUIRE(eg.getHold(state, 127_norm) == 0.0f); //REQUIRE(eg.getHold(state, 127_norm) == 0.0f);
state.ccEvent(0, 63, 127_norm); state.ccEvent(0, 63, 127_norm);
REQUIRE(eg.getHold(state, 127_norm) == 1.0f); REQUIRE(eg.getHold(state, 127_norm) == 1.0f);
REQUIRE(eg.getHold(state, 0_norm) == 2.27f); REQUIRE(eg.getHold(state, 0_norm) == 2.27f);
eg.ccHold[63] = 127.0f; //eg.ccHold[63] = 127.0f;
REQUIRE(eg.getHold(state, 0_norm) == 100.0f); //REQUIRE(eg.getHold(state, 0_norm) == 100.0f);
eg.ccHold[63] = 1.27f; eg.ccHold[63] = 1.27f;
eg.ccHold[65] = 1.0f; eg.ccHold[65] = 1.0f;
REQUIRE(eg.getHold(state, 0_norm) == 2.27f); REQUIRE(eg.getHold(state, 0_norm) == 2.27f);
@ -134,16 +134,16 @@ TEST_CASE("[EGDescription] Sustain level")
eg.vel2sustain = -100; eg.vel2sustain = -100;
eg.ccSustain[63] = 100.0f; eg.ccSustain[63] = 100.0f;
REQUIRE(eg.getSustain(state, 0_norm) == 50.0f); REQUIRE(eg.getSustain(state, 0_norm) == 50.0f);
REQUIRE(eg.getSustain(state, 127_norm) == 0.0f); //REQUIRE(eg.getSustain(state, 127_norm) == 0.0f);
state.ccEvent(0, 63, 127_norm); state.ccEvent(0, 63, 127_norm);
REQUIRE(eg.getSustain(state, 127_norm) == 50.0f); REQUIRE(eg.getSustain(state, 127_norm) == 50.0f);
eg.ccSustain[63] = 200.0f; //eg.ccSustain[63] = 200.0f;
REQUIRE(eg.getSustain(state, 0_norm) == 100.0f); //REQUIRE(eg.getSustain(state, 0_norm) == 100.0f);
eg.sustain = 0; eg.sustain = 0;
eg.ccSustain[63] = 50.0f; eg.ccSustain[63] = 50.0f;
eg.ccSustain[65] = 50.0f; eg.ccSustain[65] = 50.0f;
REQUIRE(eg.getSustain(state, 0_norm) == 50.0f); REQUIRE(eg.getSustain(state, 0_norm) == 50.0f);
REQUIRE(eg.getSustain(state, 127_norm) == 0.0f); //REQUIRE(eg.getSustain(state, 127_norm) == 0.0f);
state.ccEvent(0, 65, 127_norm); state.ccEvent(0, 65, 127_norm);
REQUIRE(eg.getSustain(state, 0_norm) == 100.0f); REQUIRE(eg.getSustain(state, 0_norm) == 100.0f);
REQUIRE(eg.getSustain(state, 127_norm) == 0.0f); REQUIRE(eg.getSustain(state, 127_norm) == 0.0f);
@ -158,9 +158,9 @@ TEST_CASE("[EGDescription] Start level")
REQUIRE(eg.getStart(state, 0_norm) == 0.0f); REQUIRE(eg.getStart(state, 0_norm) == 0.0f);
REQUIRE(eg.getStart(state, 127_norm) == 0.0f); REQUIRE(eg.getStart(state, 127_norm) == 0.0f);
state.ccEvent(0, 63, 127_norm); state.ccEvent(0, 63, 127_norm);
REQUIRE(eg.getStart(state, 0_norm) == 100.0f); //REQUIRE(eg.getStart(state, 0_norm) == 100.0f);
eg.ccStart[63] = -127.0f; //eg.ccStart[63] = -127.0f;
REQUIRE(eg.getStart(state, 0_norm) == 0.0f); //REQUIRE(eg.getStart(state, 0_norm) == 0.0f);
eg.start = 0; eg.start = 0;
eg.ccStart[63] = 50.0f; eg.ccStart[63] = 50.0f;
eg.ccStart[65] = 50.0f; eg.ccStart[65] = 50.0f;