Use float velocities in envelopes
This commit is contained in:
parent
de0d86fa09
commit
787fb963f3
6 changed files with 97 additions and 94 deletions
|
|
@ -12,7 +12,7 @@
|
|||
namespace sfz {
|
||||
|
||||
template <class Type>
|
||||
void ADSREnvelope<Type>::reset(const Region& region, const MidiState& state, int delay, uint8_t velocity, float sampleRate) noexcept
|
||||
void ADSREnvelope<Type>::reset(const Region& region, const MidiState& state, int delay, float velocity, float sampleRate) noexcept
|
||||
{
|
||||
auto secondsToSamples = [sampleRate](Type timeInSeconds) {
|
||||
return static_cast<int>(timeInSeconds * sampleRate);
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ public:
|
|||
* @param delay
|
||||
* @param velocity
|
||||
*/
|
||||
void reset(const Region& region, const MidiState& state, int delay, uint8_t velocity, float sampleRate) noexcept;
|
||||
void reset(const Region& region, const MidiState& state, int delay, float velocity, float sampleRate) noexcept;
|
||||
/**
|
||||
* @brief Get the next value for the envelope
|
||||
*
|
||||
|
|
|
|||
|
|
@ -32,9 +32,7 @@
|
|||
#include "MidiState.h"
|
||||
#include <absl/types/optional.h>
|
||||
|
||||
|
||||
namespace sfz
|
||||
{
|
||||
namespace sfz {
|
||||
/**
|
||||
* @brief A description for an SFZ envelope generator, with its envelope parameters
|
||||
* and possible CC modulation. This is a structure to be integrated directly in a
|
||||
|
|
@ -60,36 +58,35 @@ inline float ccSwitchedValue(const MidiState& state, const absl::optional<CCValu
|
|||
return value;
|
||||
}
|
||||
|
||||
struct EGDescription
|
||||
{
|
||||
struct EGDescription {
|
||||
EGDescription() = default;
|
||||
EGDescription(const EGDescription&) = default;
|
||||
EGDescription(EGDescription&&) = default;
|
||||
~EGDescription() = default;
|
||||
|
||||
float attack { Default::attack };
|
||||
float decay { Default::decay };
|
||||
float delay { Default::delayEG };
|
||||
float hold { Default::hold };
|
||||
float release { Default::release };
|
||||
float start { Default::start };
|
||||
float sustain { Default::sustain };
|
||||
int depth { Default::depth };
|
||||
float vel2attack { Default::attack };
|
||||
float vel2decay { Default::decay };
|
||||
float vel2delay { Default::delayEG };
|
||||
float vel2hold { Default::hold };
|
||||
float vel2release { Default::vel2release };
|
||||
float vel2sustain { Default::vel2sustain };
|
||||
int vel2depth { Default::depth };
|
||||
float attack { Default::attack };
|
||||
float decay { Default::decay };
|
||||
float delay { Default::delayEG };
|
||||
float hold { Default::hold };
|
||||
float release { Default::release };
|
||||
float start { Default::start };
|
||||
float sustain { Default::sustain };
|
||||
int depth { Default::depth };
|
||||
float vel2attack { Default::attack };
|
||||
float vel2decay { Default::decay };
|
||||
float vel2delay { Default::delayEG };
|
||||
float vel2hold { Default::hold };
|
||||
float vel2release { Default::vel2release };
|
||||
float vel2sustain { Default::vel2sustain };
|
||||
int vel2depth { Default::depth };
|
||||
|
||||
absl::optional<CCValuePair<float>> ccAttack;
|
||||
absl::optional<CCValuePair<float>> ccDecay;
|
||||
absl::optional<CCValuePair<float>> ccDelay;
|
||||
absl::optional<CCValuePair<float>> ccHold;
|
||||
absl::optional<CCValuePair<float>> ccRelease;
|
||||
absl::optional<CCValuePair<float>> ccStart;
|
||||
absl::optional<CCValuePair<float>> ccSustain;
|
||||
absl::optional<CCValuePair<float>> ccAttack;
|
||||
absl::optional<CCValuePair<float>> ccDecay;
|
||||
absl::optional<CCValuePair<float>> ccDelay;
|
||||
absl::optional<CCValuePair<float>> ccHold;
|
||||
absl::optional<CCValuePair<float>> ccRelease;
|
||||
absl::optional<CCValuePair<float>> ccStart;
|
||||
absl::optional<CCValuePair<float>> ccSustain;
|
||||
|
||||
/**
|
||||
* @brief Get the attack with possibly a CC modifier and a velocity modifier
|
||||
|
|
@ -98,9 +95,10 @@ struct EGDescription
|
|||
* @param velocity
|
||||
* @return float
|
||||
*/
|
||||
float getAttack(const MidiState &state, uint8_t velocity) const noexcept
|
||||
float getAttack(const MidiState& state, float velocity) const noexcept
|
||||
{
|
||||
return Default::egTimeRange.clamp(ccSwitchedValue(state, ccAttack, attack) + normalizeVelocity(velocity)*vel2attack);
|
||||
ASSERT(velocity >= 0.0f && velocity <= 1.0f);
|
||||
return Default::egTimeRange.clamp(ccSwitchedValue(state, ccAttack, attack) + velocity * vel2attack);
|
||||
}
|
||||
/**
|
||||
* @brief Get the decay with possibly a CC modifier and a velocity modifier
|
||||
|
|
@ -109,9 +107,10 @@ struct EGDescription
|
|||
* @param velocity
|
||||
* @return float
|
||||
*/
|
||||
float getDecay(const MidiState &state, uint8_t velocity) const noexcept
|
||||
float getDecay(const MidiState& state, float velocity) const noexcept
|
||||
{
|
||||
return Default::egTimeRange.clamp(ccSwitchedValue(state, ccDecay, decay) + normalizeVelocity(velocity)*vel2decay);
|
||||
ASSERT(velocity >= 0.0f && velocity <= 1.0f);
|
||||
return Default::egTimeRange.clamp(ccSwitchedValue(state, ccDecay, decay) + velocity * vel2decay);
|
||||
}
|
||||
/**
|
||||
* @brief Get the delay with possibly a CC modifier and a velocity modifier
|
||||
|
|
@ -120,9 +119,10 @@ struct EGDescription
|
|||
* @param velocity
|
||||
* @return float
|
||||
*/
|
||||
float getDelay(const MidiState &state, uint8_t velocity) const noexcept
|
||||
float getDelay(const MidiState& state, float velocity) const noexcept
|
||||
{
|
||||
return Default::egTimeRange.clamp(ccSwitchedValue(state, ccDelay, delay) + normalizeVelocity(velocity)*vel2delay);
|
||||
ASSERT(velocity >= 0.0f && velocity <= 1.0f);
|
||||
return Default::egTimeRange.clamp(ccSwitchedValue(state, ccDelay, delay) + velocity * vel2delay);
|
||||
}
|
||||
/**
|
||||
* @brief Get the holding duration with possibly a CC modifier and a velocity modifier
|
||||
|
|
@ -131,9 +131,10 @@ struct EGDescription
|
|||
* @param velocity
|
||||
* @return float
|
||||
*/
|
||||
float getHold(const MidiState &state, uint8_t velocity) const noexcept
|
||||
float getHold(const MidiState& state, float velocity) const noexcept
|
||||
{
|
||||
return Default::egTimeRange.clamp(ccSwitchedValue(state, ccHold, hold) + normalizeVelocity(velocity)*vel2hold);
|
||||
ASSERT(velocity >= 0.0f && velocity <= 1.0f);
|
||||
return Default::egTimeRange.clamp(ccSwitchedValue(state, ccHold, hold) + velocity * vel2hold);
|
||||
}
|
||||
/**
|
||||
* @brief Get the release duration with possibly a CC modifier and a velocity modifier
|
||||
|
|
@ -142,9 +143,10 @@ struct EGDescription
|
|||
* @param velocity
|
||||
* @return float
|
||||
*/
|
||||
float getRelease(const MidiState &state, uint8_t velocity) const noexcept
|
||||
float getRelease(const MidiState& state, float velocity) const noexcept
|
||||
{
|
||||
return Default::egTimeRange.clamp(ccSwitchedValue(state, ccRelease, release) + normalizeVelocity(velocity)*vel2release);
|
||||
ASSERT(velocity >= 0.0f && velocity <= 1.0f);
|
||||
return Default::egTimeRange.clamp(ccSwitchedValue(state, ccRelease, release) + velocity * vel2release);
|
||||
}
|
||||
/**
|
||||
* @brief Get the starting level with possibly a CC modifier and a velocity modifier
|
||||
|
|
@ -153,7 +155,7 @@ struct EGDescription
|
|||
* @param velocity
|
||||
* @return float
|
||||
*/
|
||||
float getStart(const MidiState &state, uint8_t velocity) const noexcept
|
||||
float getStart(const MidiState& state, float velocity) const noexcept
|
||||
{
|
||||
UNUSED(velocity);
|
||||
return Default::egPercentRange.clamp(ccSwitchedValue(state, ccStart, start));
|
||||
|
|
@ -165,9 +167,10 @@ struct EGDescription
|
|||
* @param velocity
|
||||
* @return float
|
||||
*/
|
||||
float getSustain(const MidiState &state, uint8_t velocity) const noexcept
|
||||
float getSustain(const MidiState& state, float velocity) const noexcept
|
||||
{
|
||||
return Default::egPercentRange.clamp(ccSwitchedValue(state, ccSustain, sustain) + normalizeVelocity(velocity)*vel2sustain);
|
||||
ASSERT(velocity >= 0.0f && velocity <= 1.0f);
|
||||
return Default::egPercentRange.clamp(ccSwitchedValue(state, ccSustain, sustain) + velocity * vel2sustain);
|
||||
}
|
||||
LEAK_DETECTOR(EGDescription);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -140,7 +140,7 @@ void sfz::Voice::startVoice(Region* region, int delay, int number, float value,
|
|||
initialDelay = delay + static_cast<int>(region->getDelay() * sampleRate);
|
||||
baseFrequency = midiNoteFrequency(number);
|
||||
bendStepFactor = centsFactor(region->bendStep);
|
||||
egEnvelope.reset(*region, resources.midiState, delay, denormalize7Bits<uint8_t>(value), sampleRate);
|
||||
egEnvelope.reset(*region, resources.midiState, delay, value, sampleRate);
|
||||
}
|
||||
|
||||
bool sfz::Voice::isFree() const noexcept
|
||||
|
|
|
|||
|
|
@ -49,14 +49,14 @@ TEST_CASE("[ADSREnvelope] Attack")
|
|||
sfz::Region region { state };
|
||||
region.amplitudeEG.attack = 0.02f;
|
||||
|
||||
envelope.reset(region, state, 0, 0, 100.0f);
|
||||
envelope.reset(region, state, 0, 0.0f, 100.0f);
|
||||
std::array<float, 5> output;
|
||||
std::array<float, 5> expected { 0.5f, 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
for (auto& out : output)
|
||||
out = envelope.getNextValue();
|
||||
REQUIRE(approxEqual<float>(output, expected));
|
||||
|
||||
envelope.reset(region, state, 0, 0, 100.0f);
|
||||
envelope.reset(region, state, 0, 0.0f, 100.0f);
|
||||
absl::c_fill(output, -1.0f);
|
||||
envelope.getBlock(absl::MakeSpan(output));
|
||||
REQUIRE(approxEqual<float>(output, expected));
|
||||
|
|
@ -69,14 +69,14 @@ TEST_CASE("[ADSREnvelope] Attack again")
|
|||
sfz::Region region { state };
|
||||
region.amplitudeEG.attack = 0.03f;
|
||||
|
||||
envelope.reset(region, state, 0, 0, 100.0f);
|
||||
envelope.reset(region, state, 0, 0.0f, 100.0f);
|
||||
std::array<float, 5> output;
|
||||
std::array<float, 5> expected { 0.33333f, 0.66667f, 1.0f, 1.0f, 1.0f };
|
||||
for (auto& out : output)
|
||||
out = envelope.getNextValue();
|
||||
REQUIRE(approxEqual<float>(output, expected));
|
||||
|
||||
envelope.reset(region, state, 0, 0, 100.0f);
|
||||
envelope.reset(region, state, 0, 0.0f, 100.0f);
|
||||
absl::c_fill(output, -1.0f);
|
||||
envelope.getBlock(absl::MakeSpan(output));
|
||||
REQUIRE(approxEqual<float>(output, expected));
|
||||
|
|
@ -90,7 +90,7 @@ TEST_CASE("[ADSREnvelope] Release")
|
|||
region.amplitudeEG.attack = 0.02f;
|
||||
region.amplitudeEG.release = 0.04f;
|
||||
|
||||
envelope.reset(region, state, 0, 0, 100.0f);
|
||||
envelope.reset(region, state, 0, 0.0f, 100.0f);
|
||||
envelope.startRelease(2);
|
||||
std::array<float, 8> output;
|
||||
std::array<float, 8> expected { 0.5f, 1.0f, 0.08409f, 0.00707f, 0.000594604f, 0.00005f, 0.0f, 0.0f };
|
||||
|
|
@ -98,7 +98,7 @@ TEST_CASE("[ADSREnvelope] Release")
|
|||
out = envelope.getNextValue();
|
||||
REQUIRE(approxEqual<float>(output, expected));
|
||||
|
||||
envelope.reset(region, state, 0, 0, 100.0f);
|
||||
envelope.reset(region, state, 0, 0.0f, 100.0f);
|
||||
envelope.startRelease(2);
|
||||
absl::c_fill(output, -1.0f);
|
||||
envelope.getBlock(absl::MakeSpan(output));
|
||||
|
|
@ -114,14 +114,14 @@ TEST_CASE("[ADSREnvelope] Delay")
|
|||
region.amplitudeEG.release = 0.04f;
|
||||
region.amplitudeEG.delay = 0.02f;
|
||||
std::array<float, 10> output;
|
||||
envelope.reset(region, state, 0, 0, 100.0f);
|
||||
envelope.reset(region, state, 0, 0.0f, 100.0f);
|
||||
envelope.startRelease(4);
|
||||
std::array<float, 10> expected { 0.0f, 0.0f, 0.5f, 1.0f, 0.08409f, 0.00707f, 0.000594604f, 0.00005f, 0.0f, 0.0f };
|
||||
for (auto& out : output)
|
||||
out = envelope.getNextValue();
|
||||
REQUIRE(approxEqual<float>(output, expected));
|
||||
|
||||
envelope.reset(region, state, 0, 0, 100.0f);
|
||||
envelope.reset(region, state, 0, 0.0f, 100.0f);
|
||||
envelope.startRelease(4);
|
||||
absl::c_fill(output, -1.0f);
|
||||
envelope.getBlock(absl::MakeSpan(output));
|
||||
|
|
@ -138,13 +138,13 @@ TEST_CASE("[ADSREnvelope] Lower sustain")
|
|||
region.amplitudeEG.delay = 0.02f;
|
||||
region.amplitudeEG.sustain = 50.0f;
|
||||
std::array<float, 10> output;
|
||||
envelope.reset(region, state, 0, 0, 100.0f);
|
||||
envelope.reset(region, state, 0, 0.0f, 100.0f);
|
||||
std::array<float, 10> expected { 0.0f, 0.0f, 0.5f, 1.0f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f };
|
||||
for (auto& out : output)
|
||||
out = envelope.getNextValue();
|
||||
REQUIRE(approxEqual<float>(output, expected));
|
||||
|
||||
envelope.reset(region, state, 0, 0, 100.0f);
|
||||
envelope.reset(region, state, 0, 0.0f, 100.0f);
|
||||
absl::c_fill(output, -1.0f);
|
||||
envelope.getBlock(absl::MakeSpan(output));
|
||||
REQUIRE(approxEqual<float>(output, expected));
|
||||
|
|
@ -161,13 +161,13 @@ TEST_CASE("[ADSREnvelope] Decay")
|
|||
region.amplitudeEG.sustain = 50.0f;
|
||||
region.amplitudeEG.decay = 0.02f;
|
||||
std::array<float, 10> output;
|
||||
envelope.reset(region, state, 0, 0, 100.0f);
|
||||
envelope.reset(region, state, 0, 0.0f, 100.0f);
|
||||
std::array<float, 10> expected { 0.0f, 0.0f, 0.5f, 1.0f, 0.707107f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5 };
|
||||
for (auto& out : output)
|
||||
out = envelope.getNextValue();
|
||||
REQUIRE(approxEqual<float>(output, expected));
|
||||
|
||||
envelope.reset(region, state, 0, 0, 100.0f);
|
||||
envelope.reset(region, state, 0, 0.0f, 100.0f);
|
||||
absl::c_fill(output, -1.0f);
|
||||
envelope.getBlock(absl::MakeSpan(output));
|
||||
REQUIRE(approxEqual<float>(output, expected));
|
||||
|
|
@ -185,13 +185,13 @@ TEST_CASE("[ADSREnvelope] Hold")
|
|||
region.amplitudeEG.decay = 0.02f;
|
||||
region.amplitudeEG.hold = 0.02f;
|
||||
std::array<float, 12> output;
|
||||
envelope.reset(region, state, 0, 0, 100.0f);
|
||||
envelope.reset(region, state, 0, 0.0f, 100.0f);
|
||||
std::array<float, 12> expected { 0.0f, 0.0f, 0.5f, 1.0f, 1.0f, 1.0f, 0.707107f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f };
|
||||
for (auto& out : output)
|
||||
out = envelope.getNextValue();
|
||||
REQUIRE(approxEqual<float>(output, expected));
|
||||
|
||||
envelope.reset(region, state, 0, 0, 100.0f);
|
||||
envelope.reset(region, state, 0, 0.0f, 100.0f);
|
||||
absl::c_fill(output, -1.0f);
|
||||
envelope.getBlock(absl::MakeSpan(output));
|
||||
REQUIRE(approxEqual<float>(output, expected));
|
||||
|
|
@ -208,7 +208,7 @@ TEST_CASE("[ADSREnvelope] Hold with release")
|
|||
region.amplitudeEG.sustain = 50.0f;
|
||||
region.amplitudeEG.decay = 0.02f;
|
||||
region.amplitudeEG.hold = 0.02f;
|
||||
envelope.reset(region, state, 0, 0, 100.0f);
|
||||
envelope.reset(region, state, 0, 0.0f, 100.0f);
|
||||
envelope.startRelease(8);
|
||||
std::array<float, 14> output;
|
||||
std::array<float, 14> expected { 0.0f, 0.0f, 0.5f, 1.0f, 1.0f, 1.0f, 0.707107f, 0.5f, 0.05f, 0.005f, 0.0005f, 0.00005f, 0.0f, 0.0f };
|
||||
|
|
@ -216,7 +216,7 @@ TEST_CASE("[ADSREnvelope] Hold with release")
|
|||
out = envelope.getNextValue();
|
||||
|
||||
REQUIRE(approxEqual<float>(output, expected));
|
||||
envelope.reset(region, state, 0, 0, 100.0f);
|
||||
envelope.reset(region, state, 0, 0.0f, 100.0f);
|
||||
envelope.startRelease(8);
|
||||
absl::c_fill(output, -1.0f);
|
||||
envelope.getBlock(absl::MakeSpan(output));
|
||||
|
|
@ -234,14 +234,14 @@ TEST_CASE("[ADSREnvelope] Hold with release 2")
|
|||
region.amplitudeEG.sustain = 50.0f;
|
||||
region.amplitudeEG.decay = 0.02f;
|
||||
region.amplitudeEG.hold = 0.02f;
|
||||
envelope.reset(region, state, 0, 0, 100.0f);
|
||||
envelope.reset(region, state, 0, 0.0f, 100.0f);
|
||||
envelope.startRelease(4);
|
||||
std::array<float, 14> output;
|
||||
std::array<float, 14> expected { 0.0f, 0.0f, 0.5f, 1.0f, 0.08409f, 0.00707f, 0.000594604f, 0.00005f, 0.0f, 0.0f, 0.0f, 0.0 };
|
||||
for (auto& out : output)
|
||||
out = envelope.getNextValue();
|
||||
REQUIRE(approxEqual<float>(output, expected));
|
||||
envelope.reset(region, state, 0, 0, 100.0f);
|
||||
envelope.reset(region, state, 0, 0.0f, 100.0f);
|
||||
envelope.startRelease(4);
|
||||
absl::c_fill(output, -1.0f);
|
||||
envelope.getBlock(absl::MakeSpan(output));
|
||||
|
|
|
|||
|
|
@ -18,13 +18,13 @@ TEST_CASE("[EGDescription] Attack range")
|
|||
eg.attack = 1;
|
||||
eg.vel2attack = -1.27f;
|
||||
eg.ccAttack = { 63, 1.27f };
|
||||
REQUIRE( eg.getAttack(state, 0) == 1.0f );
|
||||
REQUIRE( eg.getAttack(state, 127) == 0.0f );
|
||||
REQUIRE( eg.getAttack(state, 0_norm) == 1.0f );
|
||||
REQUIRE( eg.getAttack(state, 127_norm) == 0.0f );
|
||||
state.ccEvent(0, 63, 127_norm);
|
||||
REQUIRE( eg.getAttack(state, 127) == 1.0f );
|
||||
REQUIRE( eg.getAttack(state, 0) == 2.27f );
|
||||
REQUIRE( eg.getAttack(state, 127_norm) == 1.0f );
|
||||
REQUIRE( eg.getAttack(state, 0_norm) == 2.27f );
|
||||
eg.ccAttack = { 63, 127.0f };
|
||||
REQUIRE( eg.getAttack(state, 0) == 100.0f );
|
||||
REQUIRE( eg.getAttack(state, 0_norm) == 100.0f );
|
||||
}
|
||||
|
||||
TEST_CASE("[EGDescription] Delay range")
|
||||
|
|
@ -34,13 +34,13 @@ TEST_CASE("[EGDescription] Delay range")
|
|||
eg.delay = 1;
|
||||
eg.vel2delay = -1.27f;
|
||||
eg.ccDelay = { 63, 1.27f };
|
||||
REQUIRE( eg.getDelay(state, 0) == 1.0f );
|
||||
REQUIRE( eg.getDelay(state, 127) == 0.0f );
|
||||
REQUIRE( eg.getDelay(state, 0_norm) == 1.0f );
|
||||
REQUIRE( eg.getDelay(state, 127_norm) == 0.0f );
|
||||
state.ccEvent(0, 63, 127_norm);
|
||||
REQUIRE( eg.getDelay(state, 127) == 1.0f );
|
||||
REQUIRE( eg.getDelay(state, 0) == 2.27f );
|
||||
REQUIRE( eg.getDelay(state, 127_norm) == 1.0f );
|
||||
REQUIRE( eg.getDelay(state, 0_norm) == 2.27f );
|
||||
eg.ccDelay = { 63, 127.0f };
|
||||
REQUIRE( eg.getDelay(state, 0) == 100.0f );
|
||||
REQUIRE( eg.getDelay(state, 0_norm) == 100.0f );
|
||||
}
|
||||
|
||||
TEST_CASE("[EGDescription] Decay range")
|
||||
|
|
@ -50,13 +50,13 @@ TEST_CASE("[EGDescription] Decay range")
|
|||
eg.decay = 1.0f;
|
||||
eg.vel2decay = -1.27f;
|
||||
eg.ccDecay = { 63, 1.27f };
|
||||
REQUIRE( eg.getDecay(state, 0) == 1.0f );
|
||||
REQUIRE( eg.getDecay(state, 127) == 0.0f );
|
||||
REQUIRE( eg.getDecay(state, 0_norm) == 1.0f );
|
||||
REQUIRE( eg.getDecay(state, 127_norm) == 0.0f );
|
||||
state.ccEvent(0, 63, 127_norm);
|
||||
REQUIRE( eg.getDecay(state, 127) == 1.0f );
|
||||
REQUIRE( eg.getDecay(state, 0) == 2.27f );
|
||||
REQUIRE( eg.getDecay(state, 127_norm) == 1.0f );
|
||||
REQUIRE( eg.getDecay(state, 0_norm) == 2.27f );
|
||||
eg.ccDecay = { 63, 127.0f };
|
||||
REQUIRE( eg.getDecay(state, 0) == 100.0f );
|
||||
REQUIRE( eg.getDecay(state, 0_norm) == 100.0f );
|
||||
}
|
||||
|
||||
TEST_CASE("[EGDescription] Release range")
|
||||
|
|
@ -66,13 +66,13 @@ TEST_CASE("[EGDescription] Release range")
|
|||
eg.release = 1;
|
||||
eg.vel2release = -1.27f;
|
||||
eg.ccRelease = { 63, 1.27f };
|
||||
REQUIRE( eg.getRelease(state, 0) == 1.0f );
|
||||
REQUIRE( eg.getRelease(state, 127) == 0.0f );
|
||||
REQUIRE( eg.getRelease(state, 0_norm) == 1.0f );
|
||||
REQUIRE( eg.getRelease(state, 127_norm) == 0.0f );
|
||||
state.ccEvent(0, 63, 127_norm);
|
||||
REQUIRE( eg.getRelease(state, 127) == 1.0f );
|
||||
REQUIRE( eg.getRelease(state, 0) == 2.27f );
|
||||
REQUIRE( eg.getRelease(state, 127_norm) == 1.0f );
|
||||
REQUIRE( eg.getRelease(state, 0_norm) == 2.27f );
|
||||
eg.ccRelease = { 63, 127.0f };
|
||||
REQUIRE( eg.getRelease(state, 0) == 100.0f );
|
||||
REQUIRE( eg.getRelease(state, 0_norm) == 100.0f );
|
||||
}
|
||||
|
||||
TEST_CASE("[EGDescription] Hold range")
|
||||
|
|
@ -82,13 +82,13 @@ TEST_CASE("[EGDescription] Hold range")
|
|||
eg.hold = 1;
|
||||
eg.vel2hold = -1.27f;
|
||||
eg.ccHold = { 63, 1.27f };
|
||||
REQUIRE( eg.getHold(state, 0) == 1.0f );
|
||||
REQUIRE( eg.getHold(state, 127) == 0.0f );
|
||||
REQUIRE( eg.getHold(state, 0_norm) == 1.0f );
|
||||
REQUIRE( eg.getHold(state, 127_norm) == 0.0f );
|
||||
state.ccEvent(0, 63, 127_norm);
|
||||
REQUIRE( eg.getHold(state, 127) == 1.0f );
|
||||
REQUIRE( eg.getHold(state, 0) == 2.27f );
|
||||
REQUIRE( eg.getHold(state, 127_norm) == 1.0f );
|
||||
REQUIRE( eg.getHold(state, 0_norm) == 2.27f );
|
||||
eg.ccHold = { 63, 127.0f };
|
||||
REQUIRE( eg.getHold(state, 0) == 100.0f );
|
||||
REQUIRE( eg.getHold(state, 0_norm) == 100.0f );
|
||||
}
|
||||
|
||||
TEST_CASE("[EGDescription] Sustain level")
|
||||
|
|
@ -98,12 +98,12 @@ TEST_CASE("[EGDescription] Sustain level")
|
|||
eg.sustain = 50;
|
||||
eg.vel2sustain = -100;
|
||||
eg.ccSustain = { 63, 100.0f };
|
||||
REQUIRE( eg.getSustain(state, 0) == 50.0f );
|
||||
REQUIRE( eg.getSustain(state, 127) == 0.0f );
|
||||
REQUIRE( eg.getSustain(state, 0_norm) == 50.0f );
|
||||
REQUIRE( eg.getSustain(state, 127_norm) == 0.0f );
|
||||
state.ccEvent(0, 63, 127_norm);
|
||||
REQUIRE( eg.getSustain(state, 127) == 50.0f );
|
||||
REQUIRE( eg.getSustain(state, 127_norm) == 50.0f );
|
||||
eg.ccSustain = { 63, 200.0f };
|
||||
REQUIRE( eg.getSustain(state, 0) == 100.0f );
|
||||
REQUIRE( eg.getSustain(state, 0_norm) == 100.0f );
|
||||
}
|
||||
|
||||
TEST_CASE("[EGDescription] Start level")
|
||||
|
|
@ -112,10 +112,10 @@ TEST_CASE("[EGDescription] Start level")
|
|||
sfz::MidiState state;
|
||||
eg.start = 0;
|
||||
eg.ccStart = { 63, 127.0f };
|
||||
REQUIRE( eg.getStart(state, 0) == 0.0f );
|
||||
REQUIRE( eg.getStart(state, 127) == 0.0f );
|
||||
REQUIRE( eg.getStart(state, 0_norm) == 0.0f );
|
||||
REQUIRE( eg.getStart(state, 127_norm) == 0.0f );
|
||||
state.ccEvent(0, 63, 127_norm);
|
||||
REQUIRE( eg.getStart(state, 0) == 100.0f );
|
||||
REQUIRE( eg.getStart(state, 0_norm) == 100.0f );
|
||||
eg.ccStart = { 63, -127.0f };
|
||||
REQUIRE( eg.getStart(state, 0) == 0.0f );
|
||||
REQUIRE( eg.getStart(state, 0_norm) == 0.0f );
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue