Add support for curvecc opcodes on v1 EGs
This commit is contained in:
parent
000b263344
commit
adefb7d60e
8 changed files with 442 additions and 144 deletions
2
external/st_audiofile/thirdparty/wavpack
vendored
2
external/st_audiofile/thirdparty/wavpack
vendored
|
|
@ -1 +1 @@
|
||||||
Subproject commit 78e75a8527fffe2f87cdd56d5989ff01c0723ef7
|
Subproject commit 36b08dbcb1de136e9ae477e9f1e2b57c958fff18
|
||||||
|
|
@ -58,13 +58,13 @@ void ADSREnvelope::reset(const EGDescription& desc, const Region& region, int de
|
||||||
void ADSREnvelope::updateValues(int delay) noexcept
|
void ADSREnvelope::updateValues(int delay) noexcept
|
||||||
{
|
{
|
||||||
if (currentState == State::Delay)
|
if (currentState == State::Delay)
|
||||||
this->delay = delay + secondsToSamples(desc_->getDelay(midiState_, triggerVelocity_, delay));
|
this->delay = delay + secondsToSamples(desc_->getDelay(midiState_, curveSet_, triggerVelocity_, delay));
|
||||||
this->attackStep = secondsToLinRate(desc_->getAttack(midiState_, triggerVelocity_, delay));
|
this->attackStep = secondsToLinRate(desc_->getAttack(midiState_, curveSet_, triggerVelocity_, delay));
|
||||||
this->decayRate = secondsToExpRate(desc_->getDecay(midiState_, triggerVelocity_, delay));
|
this->decayRate = secondsToExpRate(desc_->getDecay(midiState_, curveSet_, triggerVelocity_, delay));
|
||||||
this->releaseRate = secondsToExpRate(desc_->getRelease(midiState_, triggerVelocity_, delay));
|
this->releaseRate = secondsToExpRate(desc_->getRelease(midiState_, curveSet_, triggerVelocity_, delay));
|
||||||
this->hold = secondsToSamples(desc_->getHold(midiState_, triggerVelocity_, delay));
|
this->hold = secondsToSamples(desc_->getHold(midiState_, curveSet_, triggerVelocity_, delay));
|
||||||
this->sustain = clamp(desc_->getSustain(midiState_, triggerVelocity_, delay), 0.0f, 1.0f);
|
this->sustain = clamp(desc_->getSustain(midiState_, curveSet_, triggerVelocity_, delay), 0.0f, 1.0f);
|
||||||
this->start = clamp(desc_->getStart(midiState_, triggerVelocity_, delay), 0.0f, 1.0f);
|
this->start = clamp(desc_->getStart(midiState_, curveSet_, triggerVelocity_, delay), 0.0f, 1.0f);
|
||||||
sustainThreshold = this->sustain + config::virtuallyZero;
|
sustainThreshold = this->sustain + config::virtuallyZero;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,12 +14,13 @@ namespace sfz {
|
||||||
* @brief Describe an attack/delay/sustain/release envelope that can
|
* @brief Describe an attack/delay/sustain/release envelope that can
|
||||||
* produce its coefficient in a blockwise manner for SIMD-type operations.
|
* produce its coefficient in a blockwise manner for SIMD-type operations.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class ADSREnvelope {
|
class ADSREnvelope {
|
||||||
public:
|
public:
|
||||||
using Float = float;
|
using Float = float;
|
||||||
|
|
||||||
ADSREnvelope(const MidiState& state)
|
ADSREnvelope(const MidiState& state, CurveSet& curveSet)
|
||||||
: midiState_(state) {}
|
: midiState_(state), curveSet_(curveSet) {}
|
||||||
/**
|
/**
|
||||||
* @brief Resets the ADSR envelope given a Region, the current midi state, and a delay and
|
* @brief Resets the ADSR envelope given a Region, the current midi state, and a delay and
|
||||||
* trigger velocity
|
* trigger velocity
|
||||||
|
|
@ -104,6 +105,7 @@ private:
|
||||||
Float currentValue { 0.0 };
|
Float currentValue { 0.0 };
|
||||||
const EGDescription* desc_ { nullptr };
|
const EGDescription* desc_ { nullptr };
|
||||||
const MidiState& midiState_;
|
const MidiState& midiState_;
|
||||||
|
CurveSet& curveSet_;
|
||||||
float triggerVelocity_ { 0.0f };
|
float triggerVelocity_ { 0.0f };
|
||||||
bool dynamic_ { false };
|
bool dynamic_ { false };
|
||||||
int delay { 0 };
|
int delay { 0 };
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,8 @@
|
||||||
#include "utility/LeakDetector.h"
|
#include "utility/LeakDetector.h"
|
||||||
#include <absl/types/optional.h>
|
#include <absl/types/optional.h>
|
||||||
|
|
||||||
|
#include "Curve.h"
|
||||||
|
|
||||||
namespace sfz {
|
namespace sfz {
|
||||||
/**
|
/**
|
||||||
* @brief A description for an SFZ envelope generator, with its envelope parameters
|
* @brief A description for an SFZ envelope generator, with its envelope parameters
|
||||||
|
|
@ -66,13 +68,20 @@ struct EGDescription {
|
||||||
float vel2sustain { Default::egPercentMod };
|
float vel2sustain { Default::egPercentMod };
|
||||||
float vel2depth { Default::egVel2Depth };
|
float vel2depth { Default::egVel2Depth };
|
||||||
|
|
||||||
CCMap<float> ccAttack;
|
CCMap<ModifierCurvePair<float>> ccAttack { ModifierCurvePair<float>{ Default::egTime, Default::curveCC } };
|
||||||
CCMap<float> ccDecay;
|
CCMap<ModifierCurvePair<float>> ccDecay { ModifierCurvePair<float>{ Default::egTime, Default::curveCC } };
|
||||||
CCMap<float> ccDelay;
|
CCMap<ModifierCurvePair<float>> ccDelay { ModifierCurvePair<float>{ Default::egTime, Default::curveCC } };
|
||||||
CCMap<float> ccHold;
|
CCMap<ModifierCurvePair<float>> ccHold { ModifierCurvePair<float>{ Default::egTime, Default::curveCC } };
|
||||||
CCMap<float> ccRelease;
|
CCMap<ModifierCurvePair<float>> ccRelease { ModifierCurvePair<float>{ Default::egTime, Default::curveCC } };
|
||||||
CCMap<float> ccStart;
|
CCMap<ModifierCurvePair<float>> ccStart { ModifierCurvePair<float>{ Default::egPercentMod, Default::curveCC } };
|
||||||
CCMap<float> ccSustain;
|
CCMap<ModifierCurvePair<float>> ccSustain { ModifierCurvePair<float>{ Default:: egPercentMod, Default::curveCC } };
|
||||||
|
//CCMap<float> ccAttack;
|
||||||
|
//CCMap<float> ccDecay;
|
||||||
|
//CCMap<float> ccDelay;
|
||||||
|
//CCMap<float> ccHold;
|
||||||
|
//CCMap<float> ccRelease;
|
||||||
|
//CCMap<float> ccStart;
|
||||||
|
//CCMap<float> ccSustain;
|
||||||
bool dynamic { false };
|
bool dynamic { false };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -82,12 +91,13 @@ struct EGDescription {
|
||||||
* @param velocity
|
* @param velocity
|
||||||
* @return float
|
* @return float
|
||||||
*/
|
*/
|
||||||
float getAttack(const MidiState& state, float velocity, int delay = 0) const noexcept
|
float getAttack(const MidiState& state, CurveSet& curveSet, float velocity, int delay = 0) const noexcept
|
||||||
{
|
{
|
||||||
ASSERT(velocity >= 0.0f && velocity <= 1.0f);
|
ASSERT(velocity >= 0.0f && velocity <= 1.0f);
|
||||||
float returnedValue { attack + velocity * vel2attack };
|
float returnedValue { attack + velocity * vel2attack };
|
||||||
for (auto& mod: ccAttack) {
|
for (auto& mod: ccAttack) {
|
||||||
returnedValue += state.getCCValueAt(mod.cc, delay) * mod.data;
|
const auto& curve = curveSet.getCurve(mod.data.curve);
|
||||||
|
returnedValue += curve.evalNormalized(state.getCCValueAt(mod.cc, delay)) * mod.data.modifier;
|
||||||
}
|
}
|
||||||
return returnedValue;
|
return returnedValue;
|
||||||
}
|
}
|
||||||
|
|
@ -98,12 +108,13 @@ struct EGDescription {
|
||||||
* @param velocity
|
* @param velocity
|
||||||
* @return float
|
* @return float
|
||||||
*/
|
*/
|
||||||
float getDecay(const MidiState& state, float velocity, int delay = 0) const noexcept
|
float getDecay(const MidiState& state, CurveSet& curveSet, float velocity, int delay = 0) const noexcept
|
||||||
{
|
{
|
||||||
ASSERT(velocity >= 0.0f && velocity <= 1.0f);
|
ASSERT(velocity >= 0.0f && velocity <= 1.0f);
|
||||||
float returnedValue { decay + velocity * vel2decay };
|
float returnedValue { decay + velocity * vel2decay };
|
||||||
for (auto& mod: ccDecay) {
|
for (auto& mod: ccDecay) {
|
||||||
returnedValue += state.getCCValueAt(mod.cc, delay) * mod.data;
|
const auto& curve = curveSet.getCurve(mod.data.curve);
|
||||||
|
returnedValue += curve.evalNormalized(state.getCCValueAt(mod.cc, delay)) * mod.data.modifier;
|
||||||
}
|
}
|
||||||
return returnedValue;
|
return returnedValue;
|
||||||
}
|
}
|
||||||
|
|
@ -114,12 +125,13 @@ struct EGDescription {
|
||||||
* @param velocity
|
* @param velocity
|
||||||
* @return float
|
* @return float
|
||||||
*/
|
*/
|
||||||
float getDelay(const MidiState& state, float velocity, int delay = 0) const noexcept
|
float getDelay(const MidiState& state, CurveSet& curveSet, float velocity, int delay = 0) const noexcept
|
||||||
{
|
{
|
||||||
ASSERT(velocity >= 0.0f && velocity <= 1.0f);
|
ASSERT(velocity >= 0.0f && velocity <= 1.0f);
|
||||||
float returnedValue { this->delay + velocity * vel2delay };
|
float returnedValue { this->delay + velocity * vel2delay };
|
||||||
for (auto& mod: ccDelay) {
|
for (auto& mod: ccDelay) {
|
||||||
returnedValue += state.getCCValueAt(mod.cc, delay) * mod.data;
|
const auto& curve = curveSet.getCurve(mod.data.curve);
|
||||||
|
returnedValue += curve.evalNormalized(state.getCCValueAt(mod.cc, delay)) * mod.data.modifier;
|
||||||
}
|
}
|
||||||
return returnedValue;
|
return returnedValue;
|
||||||
}
|
}
|
||||||
|
|
@ -130,12 +142,13 @@ struct EGDescription {
|
||||||
* @param velocity
|
* @param velocity
|
||||||
* @return float
|
* @return float
|
||||||
*/
|
*/
|
||||||
float getHold(const MidiState& state, float velocity, int delay = 0) const noexcept
|
float getHold(const MidiState& state, CurveSet& curveSet, float velocity, int delay = 0) const noexcept
|
||||||
{
|
{
|
||||||
ASSERT(velocity >= 0.0f && velocity <= 1.0f);
|
ASSERT(velocity >= 0.0f && velocity <= 1.0f);
|
||||||
float returnedValue { hold + velocity * vel2hold };
|
float returnedValue { hold + velocity * vel2hold };
|
||||||
for (auto& mod: ccHold) {
|
for (auto& mod: ccHold) {
|
||||||
returnedValue += state.getCCValueAt(mod.cc, delay) * mod.data;
|
const auto& curve = curveSet.getCurve(mod.data.curve);
|
||||||
|
returnedValue += curve.evalNormalized(state.getCCValueAt(mod.cc, delay)) * mod.data.modifier;
|
||||||
}
|
}
|
||||||
return returnedValue;
|
return returnedValue;
|
||||||
}
|
}
|
||||||
|
|
@ -146,12 +159,13 @@ struct EGDescription {
|
||||||
* @param velocity
|
* @param velocity
|
||||||
* @return float
|
* @return float
|
||||||
*/
|
*/
|
||||||
float getRelease(const MidiState& state, float velocity, int delay = 0) const noexcept
|
float getRelease(const MidiState& state, CurveSet& curveSet, float velocity, int delay = 0) const noexcept
|
||||||
{
|
{
|
||||||
ASSERT(velocity >= 0.0f && velocity <= 1.0f);
|
ASSERT(velocity >= 0.0f && velocity <= 1.0f);
|
||||||
float returnedValue { release + velocity * vel2release };
|
float returnedValue { release + velocity * vel2release };
|
||||||
for (auto& mod: ccRelease) {
|
for (auto& mod: ccRelease) {
|
||||||
returnedValue += state.getCCValueAt(mod.cc, delay) * mod.data;
|
const auto& curve = curveSet.getCurve(mod.data.curve);
|
||||||
|
returnedValue += curve.evalNormalized(state.getCCValueAt(mod.cc, delay)) * mod.data.modifier;
|
||||||
}
|
}
|
||||||
return returnedValue;
|
return returnedValue;
|
||||||
}
|
}
|
||||||
|
|
@ -162,12 +176,13 @@ struct EGDescription {
|
||||||
* @param velocity
|
* @param velocity
|
||||||
* @return float
|
* @return float
|
||||||
*/
|
*/
|
||||||
float getStart(const MidiState& state, float velocity, int delay = 0) const noexcept
|
float getStart(const MidiState& state, CurveSet& curveSet, float velocity, int delay = 0) const noexcept
|
||||||
{
|
{
|
||||||
UNUSED(velocity);
|
ASSERT(velocity >= 0.0f && velocity <= 1.0f);
|
||||||
float returnedValue { start };
|
float returnedValue { start };
|
||||||
for (auto& mod: ccStart) {
|
for (auto& mod: ccStart) {
|
||||||
returnedValue += state.getCCValueAt(mod.cc, delay) * mod.data;
|
const auto& curve = curveSet.getCurve(mod.data.curve);
|
||||||
|
returnedValue += curve.evalNormalized(state.getCCValueAt(mod.cc, delay)) * mod.data.modifier;
|
||||||
}
|
}
|
||||||
return returnedValue;
|
return returnedValue;
|
||||||
}
|
}
|
||||||
|
|
@ -178,12 +193,13 @@ struct EGDescription {
|
||||||
* @param velocity
|
* @param velocity
|
||||||
* @return float
|
* @return float
|
||||||
*/
|
*/
|
||||||
float getSustain(const MidiState& state, float velocity, int delay = 0) const noexcept
|
float getSustain(const MidiState& state, CurveSet& curveSet, float velocity, int delay = 0) const noexcept
|
||||||
{
|
{
|
||||||
ASSERT(velocity >= 0.0f && velocity <= 1.0f);
|
ASSERT(velocity >= 0.0f && velocity <= 1.0f);
|
||||||
float returnedValue { sustain + velocity * vel2sustain };
|
float returnedValue { sustain + velocity * vel2sustain };
|
||||||
for (auto& mod: ccSustain) {
|
for (auto& mod: ccSustain) {
|
||||||
returnedValue += state.getCCValueAt(mod.cc, delay) * mod.data;
|
const auto& curve = curveSet.getCurve(mod.data.curve);
|
||||||
|
returnedValue += curve.evalNormalized(state.getCCValueAt(mod.cc, delay)) * mod.data.modifier;
|
||||||
}
|
}
|
||||||
return returnedValue;
|
return returnedValue;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1110,49 +1110,98 @@ bool sfz::Region::parseEGOpcode(const Opcode& opcode, EGDescription& eg)
|
||||||
if (opcode.parameters.back() >= config::numCCs)
|
if (opcode.parameters.back() >= config::numCCs)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
eg.ccAttack[opcode.parameters.back()] = opcode.read(Default::egTimeMod);
|
eg.ccAttack[opcode.parameters.back()].modifier = opcode.read(Default::egTimeMod);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case_any_eg("attack_curvecc&"): // also attackcc&
|
||||||
|
if (opcode.parameters.back() >= config::numCCs)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
eg.ccAttack[opcode.parameters.back()].curve = opcode.read(Default::curveCC);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case_any_eg("decay_oncc&"): // also decaycc&
|
case_any_eg("decay_oncc&"): // also decaycc&
|
||||||
if (opcode.parameters.back() >= config::numCCs)
|
if (opcode.parameters.back() >= config::numCCs)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
eg.ccDecay[opcode.parameters.back()] = opcode.read(Default::egTimeMod);
|
eg.ccDecay[opcode.parameters.back()].modifier = opcode.read(Default::egTimeMod);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case_any_eg("decay_curvecc&"): // also attackcc&
|
||||||
|
if (opcode.parameters.back() >= config::numCCs)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
eg.ccDecay[opcode.parameters.back()].curve = opcode.read(Default::curveCC);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case_any_eg("delay_oncc&"): // also delaycc&
|
case_any_eg("delay_oncc&"): // also delaycc&
|
||||||
if (opcode.parameters.back() >= config::numCCs)
|
if (opcode.parameters.back() >= config::numCCs)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
eg.ccDelay[opcode.parameters.back()] = opcode.read(Default::egTimeMod);
|
eg.ccDelay[opcode.parameters.back()].modifier = opcode.read(Default::egTimeMod);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case_any_eg("delay_curvecc&"): // also attackcc&
|
||||||
|
if (opcode.parameters.back() >= config::numCCs)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
eg.ccDelay[opcode.parameters.back()].curve = opcode.read(Default::curveCC);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case_any_eg("hold_oncc&"): // also holdcc&
|
case_any_eg("hold_oncc&"): // also holdcc&
|
||||||
if (opcode.parameters.back() >= config::numCCs)
|
if (opcode.parameters.back() >= config::numCCs)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
eg.ccHold[opcode.parameters.back()] = opcode.read(Default::egTimeMod);
|
eg.ccHold[opcode.parameters.back()].modifier = opcode.read(Default::egTimeMod);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case_any_eg("hold_curvecc&"): // also attackcc&
|
||||||
|
if (opcode.parameters.back() >= config::numCCs)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
eg.ccHold[opcode.parameters.back()].curve = opcode.read(Default::curveCC);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case_any_eg("release_oncc&"): // also releasecc&
|
case_any_eg("release_oncc&"): // also releasecc&
|
||||||
if (opcode.parameters.back() >= config::numCCs)
|
if (opcode.parameters.back() >= config::numCCs)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
eg.ccRelease[opcode.parameters.back()] = opcode.read(Default::egTimeMod);
|
eg.ccRelease[opcode.parameters.back()].modifier = opcode.read(Default::egTimeMod);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case_any_eg("release_curvecc&"): // also attackcc&
|
||||||
|
if (opcode.parameters.back() >= config::numCCs)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
eg.ccRelease[opcode.parameters.back()].curve = opcode.read(Default::curveCC);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case_any_eg("start_oncc&"): // also startcc&
|
case_any_eg("start_oncc&"): // also startcc&
|
||||||
if (opcode.parameters.back() >= config::numCCs)
|
if (opcode.parameters.back() >= config::numCCs)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
eg.ccStart[opcode.parameters.back()] = opcode.read(Default::egPercentMod);
|
eg.ccStart[opcode.parameters.back()].modifier = opcode.read(Default::egPercentMod);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case_any_eg("start_curvecc&"): // also startcc&
|
||||||
|
if (opcode.parameters.back() >= config::numCCs)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
eg.ccStart[opcode.parameters.back()].curve = opcode.read(Default::curveCC);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case_any_eg("sustain_oncc&"): // also sustaincc&
|
case_any_eg("sustain_oncc&"): // also sustaincc&
|
||||||
if (opcode.parameters.back() >= config::numCCs)
|
if (opcode.parameters.back() >= config::numCCs)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
eg.ccSustain[opcode.parameters.back()] = opcode.read(Default::egPercentMod);
|
eg.ccSustain[opcode.parameters.back()].modifier = opcode.read(Default::egPercentMod);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case_any_eg("sustain_curvecc&"): // also attackcc&
|
||||||
|
if (opcode.parameters.back() >= config::numCCs)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
eg.ccSustain[opcode.parameters.back()].curve = opcode.read(Default::curveCC);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1222,6 +1222,90 @@ void sfz::Synth::dispatchMessage(Client& client, int delay, const char* path, co
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
MATCH("/region&/pitcheg_attack_cc&", "") {
|
||||||
|
GET_REGION_OR_BREAK(indices[0])
|
||||||
|
const auto& cc = region.pitchEG->ccAttack.getWithDefault(indices[1]);
|
||||||
|
client.receive<'f'>(delay, path, cc.modifier);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
MATCH("/region&/pitcheg_decay_cc&", "") {
|
||||||
|
GET_REGION_OR_BREAK(indices[0])
|
||||||
|
const auto& cc = region.pitchEG->ccDecay.getWithDefault(indices[1]);
|
||||||
|
client.receive<'f'>(delay, path, cc.modifier);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
MATCH("/region&/pitcheg_delay_cc&", "") {
|
||||||
|
GET_REGION_OR_BREAK(indices[0])
|
||||||
|
const auto& cc = region.pitchEG->ccDelay.getWithDefault(indices[1]);
|
||||||
|
client.receive<'f'>(delay, path, cc.modifier);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
MATCH("/region&/pitcheg_hold_cc&", "") {
|
||||||
|
GET_REGION_OR_BREAK(indices[0])
|
||||||
|
const auto& cc = region.pitchEG->ccHold.getWithDefault(indices[1]);
|
||||||
|
client.receive<'f'>(delay, path, cc.modifier);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
MATCH("/region&/pitcheg_release_cc&", "") {
|
||||||
|
GET_REGION_OR_BREAK(indices[0])
|
||||||
|
const auto& cc = region.pitchEG->ccRelease.getWithDefault(indices[1]);
|
||||||
|
client.receive<'f'>(delay, path, cc.modifier);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
MATCH("/region&/pitcheg_start_cc&", "") {
|
||||||
|
GET_REGION_OR_BREAK(indices[0])
|
||||||
|
const auto& cc = region.pitchEG->ccStart.getWithDefault(indices[1]);
|
||||||
|
client.receive<'f'>(delay, path, cc.modifier * 100.0f);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
MATCH("/region&/pitcheg_sustain_cc&", "") {
|
||||||
|
GET_REGION_OR_BREAK(indices[0])
|
||||||
|
const auto& cc = region.pitchEG->ccSustain.getWithDefault(indices[1]);
|
||||||
|
client.receive<'f'>(delay, path, cc.modifier * 100.0f);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
MATCH("/region&/pitcheg_attack_curvecc&", "") {
|
||||||
|
GET_REGION_OR_BREAK(indices[0])
|
||||||
|
const auto& cc = region.pitchEG->ccAttack.getWithDefault(indices[1]);
|
||||||
|
client.receive<'f'>(delay, path, cc.curve);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
MATCH("/region&/pitcheg_decay_curvecc&", "") {
|
||||||
|
GET_REGION_OR_BREAK(indices[0])
|
||||||
|
const auto& cc = region.pitchEG->ccDecay.getWithDefault(indices[1]);
|
||||||
|
client.receive<'f'>(delay, path, cc.curve);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
MATCH("/region&/pitcheg_delay_curvecc&", "") {
|
||||||
|
GET_REGION_OR_BREAK(indices[0])
|
||||||
|
const auto& cc = region.pitchEG->ccDelay.getWithDefault(indices[1]);
|
||||||
|
client.receive<'f'>(delay, path, cc.curve);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
MATCH("/region&/pitcheg_hold_curvecc&", "") {
|
||||||
|
GET_REGION_OR_BREAK(indices[0])
|
||||||
|
const auto& cc = region.pitchEG->ccHold.getWithDefault(indices[1]);
|
||||||
|
client.receive<'f'>(delay, path, cc.curve);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
MATCH("/region&/pitcheg_release_curvecc&", "") {
|
||||||
|
GET_REGION_OR_BREAK(indices[0])
|
||||||
|
const auto& cc = region.pitchEG->ccRelease.getWithDefault(indices[1]);
|
||||||
|
client.receive<'f'>(delay, path, cc.curve);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
MATCH("/region&/pitcheg_start_curvecc&", "") {
|
||||||
|
GET_REGION_OR_BREAK(indices[0])
|
||||||
|
const auto& cc = region.pitchEG->ccStart.getWithDefault(indices[1]);
|
||||||
|
client.receive<'f'>(delay, path, cc.curve);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
MATCH("/region&/pitcheg_sustain_curvecc&", "") {
|
||||||
|
GET_REGION_OR_BREAK(indices[0])
|
||||||
|
const auto& cc = region.pitchEG->ccSustain.getWithDefault(indices[1]);
|
||||||
|
client.receive<'f'>(delay, path, cc.curve);
|
||||||
|
} break;
|
||||||
|
|
||||||
MATCH("/region&/note_polyphony", "") {
|
MATCH("/region&/note_polyphony", "") {
|
||||||
GET_REGION_OR_BREAK(indices[0])
|
GET_REGION_OR_BREAK(indices[0])
|
||||||
if (region.notePolyphony) {
|
if (region.notePolyphony) {
|
||||||
|
|
@ -1338,44 +1422,86 @@ void sfz::Synth::dispatchMessage(Client& client, int delay, const char* path, co
|
||||||
|
|
||||||
MATCH("/region&/ampeg_attack_cc&", "") {
|
MATCH("/region&/ampeg_attack_cc&", "") {
|
||||||
GET_REGION_OR_BREAK(indices[0])
|
GET_REGION_OR_BREAK(indices[0])
|
||||||
float value = region.amplitudeEG.ccAttack.getWithDefault(indices[1]);
|
const auto& cc = region.amplitudeEG.ccAttack.getWithDefault(indices[1]);
|
||||||
client.receive<'f'>(delay, path, value);
|
client.receive<'f'>(delay, path, cc.modifier);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
MATCH("/region&/ampeg_decay_cc&", "") {
|
MATCH("/region&/ampeg_decay_cc&", "") {
|
||||||
GET_REGION_OR_BREAK(indices[0])
|
GET_REGION_OR_BREAK(indices[0])
|
||||||
float value = region.amplitudeEG.ccDecay.getWithDefault(indices[1]);
|
const auto& cc = region.amplitudeEG.ccDecay.getWithDefault(indices[1]);
|
||||||
client.receive<'f'>(delay, path, value);
|
client.receive<'f'>(delay, path, cc.modifier);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
MATCH("/region&/ampeg_delay_cc&", "") {
|
MATCH("/region&/ampeg_delay_cc&", "") {
|
||||||
GET_REGION_OR_BREAK(indices[0])
|
GET_REGION_OR_BREAK(indices[0])
|
||||||
float value = region.amplitudeEG.ccDelay.getWithDefault(indices[1]);
|
const auto& cc = region.amplitudeEG.ccDelay.getWithDefault(indices[1]);
|
||||||
client.receive<'f'>(delay, path, value);
|
client.receive<'f'>(delay, path, cc.modifier);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
MATCH("/region&/ampeg_hold_cc&", "") {
|
MATCH("/region&/ampeg_hold_cc&", "") {
|
||||||
GET_REGION_OR_BREAK(indices[0])
|
GET_REGION_OR_BREAK(indices[0])
|
||||||
float value = region.amplitudeEG.ccHold.getWithDefault(indices[1]);
|
const auto& cc = region.amplitudeEG.ccHold.getWithDefault(indices[1]);
|
||||||
client.receive<'f'>(delay, path, value);
|
client.receive<'f'>(delay, path, cc.modifier);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
MATCH("/region&/ampeg_release_cc&", "") {
|
MATCH("/region&/ampeg_release_cc&", "") {
|
||||||
GET_REGION_OR_BREAK(indices[0])
|
GET_REGION_OR_BREAK(indices[0])
|
||||||
float value = region.amplitudeEG.ccRelease.getWithDefault(indices[1]);
|
const auto& cc = region.amplitudeEG.ccRelease.getWithDefault(indices[1]);
|
||||||
client.receive<'f'>(delay, path, value);
|
client.receive<'f'>(delay, path, cc.modifier);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
MATCH("/region&/ampeg_start_cc&", "") {
|
MATCH("/region&/ampeg_start_cc&", "") {
|
||||||
GET_REGION_OR_BREAK(indices[0])
|
GET_REGION_OR_BREAK(indices[0])
|
||||||
float value = region.amplitudeEG.ccStart.getWithDefault(indices[1]);
|
const auto& cc = region.amplitudeEG.ccStart.getWithDefault(indices[1]);
|
||||||
client.receive<'f'>(delay, path, value * 100.0f);
|
client.receive<'f'>(delay, path, cc.modifier * 100.0f);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
MATCH("/region&/ampeg_sustain_cc&", "") {
|
MATCH("/region&/ampeg_sustain_cc&", "") {
|
||||||
GET_REGION_OR_BREAK(indices[0])
|
GET_REGION_OR_BREAK(indices[0])
|
||||||
float value = region.amplitudeEG.ccSustain.getWithDefault(indices[1]);
|
const auto& cc = region.amplitudeEG.ccSustain.getWithDefault(indices[1]);
|
||||||
client.receive<'f'>(delay, path, value * 100.0f);
|
client.receive<'f'>(delay, path, cc.modifier * 100.0f);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
MATCH("/region&/ampeg_attack_curvecc&", "") {
|
||||||
|
GET_REGION_OR_BREAK(indices[0])
|
||||||
|
const auto& cc = region.amplitudeEG.ccAttack.getWithDefault(indices[1]);
|
||||||
|
client.receive<'f'>(delay, path, cc.curve);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
MATCH("/region&/ampeg_decay_curvecc&", "") {
|
||||||
|
GET_REGION_OR_BREAK(indices[0])
|
||||||
|
const auto& cc = region.amplitudeEG.ccDecay.getWithDefault(indices[1]);
|
||||||
|
client.receive<'f'>(delay, path, cc.curve);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
MATCH("/region&/ampeg_delay_curvecc&", "") {
|
||||||
|
GET_REGION_OR_BREAK(indices[0])
|
||||||
|
const auto& cc = region.amplitudeEG.ccDelay.getWithDefault(indices[1]);
|
||||||
|
client.receive<'f'>(delay, path, cc.curve);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
MATCH("/region&/ampeg_hold_curvecc&", "") {
|
||||||
|
GET_REGION_OR_BREAK(indices[0])
|
||||||
|
const auto& cc = region.amplitudeEG.ccHold.getWithDefault(indices[1]);
|
||||||
|
client.receive<'f'>(delay, path, cc.curve);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
MATCH("/region&/ampeg_release_curvecc&", "") {
|
||||||
|
GET_REGION_OR_BREAK(indices[0])
|
||||||
|
const auto& cc = region.amplitudeEG.ccRelease.getWithDefault(indices[1]);
|
||||||
|
client.receive<'f'>(delay, path, cc.curve);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
MATCH("/region&/ampeg_start_curvecc&", "") {
|
||||||
|
GET_REGION_OR_BREAK(indices[0])
|
||||||
|
const auto& cc = region.amplitudeEG.ccStart.getWithDefault(indices[1]);
|
||||||
|
client.receive<'f'>(delay, path, cc.curve);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
MATCH("/region&/ampeg_sustain_curvecc&", "") {
|
||||||
|
GET_REGION_OR_BREAK(indices[0])
|
||||||
|
const auto& cc = region.amplitudeEG.ccSustain.getWithDefault(indices[1]);
|
||||||
|
client.receive<'f'>(delay, path, cc.curve);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
MATCH("/region&/filter&/cutoff", "") {
|
MATCH("/region&/filter&/cutoff", "") {
|
||||||
|
|
@ -1495,6 +1621,104 @@ void sfz::Synth::dispatchMessage(Client& client, int delay, const char* path, co
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
MATCH("/region&/filter&/fileg_attack_cc&", "") {
|
||||||
|
GET_REGION_OR_BREAK(indices[0])
|
||||||
|
GET_FILTER_OR_BREAK(indices[1])
|
||||||
|
const auto& cc = region.filterEG->ccAttack.getWithDefault(indices[2]);
|
||||||
|
client.receive<'f'>(delay, path, cc.modifier);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
MATCH("/region&/filter&/fileg_decay_cc&", "") {
|
||||||
|
GET_REGION_OR_BREAK(indices[0])
|
||||||
|
GET_FILTER_OR_BREAK(indices[1])
|
||||||
|
const auto& cc = region.filterEG->ccDecay.getWithDefault(indices[2]);
|
||||||
|
client.receive<'f'>(delay, path, cc.modifier);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
MATCH("/region&/filter&/fileg_delay_cc&", "") {
|
||||||
|
GET_REGION_OR_BREAK(indices[0])
|
||||||
|
GET_FILTER_OR_BREAK(indices[1])
|
||||||
|
const auto& cc = region.filterEG->ccDelay.getWithDefault(indices[2]);
|
||||||
|
client.receive<'f'>(delay, path, cc.modifier);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
MATCH("/region&/filter&/fileg_hold_cc&", "") {
|
||||||
|
GET_REGION_OR_BREAK(indices[0])
|
||||||
|
GET_FILTER_OR_BREAK(indices[1])
|
||||||
|
const auto& cc = region.filterEG->ccHold.getWithDefault(indices[2]);
|
||||||
|
client.receive<'f'>(delay, path, cc.modifier);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
MATCH("/region&/filter&/fileg_release_cc&", "") {
|
||||||
|
GET_REGION_OR_BREAK(indices[0])
|
||||||
|
GET_FILTER_OR_BREAK(indices[1])
|
||||||
|
const auto& cc = region.filterEG->ccRelease.getWithDefault(indices[2]);
|
||||||
|
client.receive<'f'>(delay, path, cc.modifier);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
MATCH("/region&/filter&/fileg_start_cc&", "") {
|
||||||
|
GET_REGION_OR_BREAK(indices[0])
|
||||||
|
GET_FILTER_OR_BREAK(indices[1])
|
||||||
|
const auto& cc = region.filterEG->ccStart.getWithDefault(indices[2]);
|
||||||
|
client.receive<'f'>(delay, path, cc.modifier * 100.0f);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
MATCH("/region&/filter&/fileg_sustain_cc&", "") {
|
||||||
|
GET_REGION_OR_BREAK(indices[0])
|
||||||
|
GET_FILTER_OR_BREAK(indices[1])
|
||||||
|
const auto& cc = region.filterEG->ccSustain.getWithDefault(indices[2]);
|
||||||
|
client.receive<'f'>(delay, path, cc.modifier * 100.0f);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
MATCH("/region&/filter&/fileg_attack_curvecc&", "") {
|
||||||
|
GET_REGION_OR_BREAK(indices[0])
|
||||||
|
GET_FILTER_OR_BREAK(indices[1])
|
||||||
|
const auto& cc = region.filterEG->ccAttack.getWithDefault(indices[2]);
|
||||||
|
client.receive<'f'>(delay, path, cc.curve);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
MATCH("/region&/filter&/fileg_decay_curvecc&", "") {
|
||||||
|
GET_REGION_OR_BREAK(indices[0])
|
||||||
|
GET_FILTER_OR_BREAK(indices[1])
|
||||||
|
const auto& cc = region.filterEG->ccDecay.getWithDefault(indices[2]);
|
||||||
|
client.receive<'f'>(delay, path, cc.curve);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
MATCH("/region&/filter&/fileg_delay_curvecc&", "") {
|
||||||
|
GET_REGION_OR_BREAK(indices[0])
|
||||||
|
GET_FILTER_OR_BREAK(indices[1])
|
||||||
|
const auto& cc = region.filterEG->ccDelay.getWithDefault(indices[2]);
|
||||||
|
client.receive<'f'>(delay, path, cc.curve);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
MATCH("/region&/filter&/fileg_hold_curvecc&", "") {
|
||||||
|
GET_REGION_OR_BREAK(indices[0])
|
||||||
|
GET_FILTER_OR_BREAK(indices[1])
|
||||||
|
const auto& cc = region.filterEG->ccHold.getWithDefault(indices[2]);
|
||||||
|
client.receive<'f'>(delay, path, cc.curve);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
MATCH("/region&/filter&/fileg_release_curvecc&", "") {
|
||||||
|
GET_REGION_OR_BREAK(indices[0])
|
||||||
|
GET_FILTER_OR_BREAK(indices[1])
|
||||||
|
const auto& cc = region.filterEG->ccRelease.getWithDefault(indices[2]);
|
||||||
|
client.receive<'f'>(delay, path, cc.curve);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
MATCH("/region&/filter&/fileg_start_curvecc&", "") {
|
||||||
|
GET_REGION_OR_BREAK(indices[0])
|
||||||
|
GET_FILTER_OR_BREAK(indices[1])
|
||||||
|
const auto& cc = region.filterEG->ccStart.getWithDefault(indices[2]);
|
||||||
|
client.receive<'f'>(delay, path, cc.curve);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
MATCH("/region&/filter&/fileg_sustain_curvecc&", "") {
|
||||||
|
GET_REGION_OR_BREAK(indices[0])
|
||||||
|
GET_FILTER_OR_BREAK(indices[1])
|
||||||
|
const auto& cc = region.filterEG->ccSustain.getWithDefault(indices[2]);
|
||||||
|
client.receive<'f'>(delay, path, cc.curve);
|
||||||
|
} break;
|
||||||
|
|
||||||
MATCH("/region&/eq&/gain", "") {
|
MATCH("/region&/eq&/gain", "") {
|
||||||
GET_REGION_OR_BREAK(indices[0])
|
GET_REGION_OR_BREAK(indices[0])
|
||||||
GET_EQ_OR_BREAK(indices[1])
|
GET_EQ_OR_BREAK(indices[1])
|
||||||
|
|
|
||||||
|
|
@ -275,7 +275,7 @@ struct Voice::Impl
|
||||||
std::unique_ptr<LFO> lfoPitch_;
|
std::unique_ptr<LFO> lfoPitch_;
|
||||||
std::unique_ptr<LFO> lfoFilter_;
|
std::unique_ptr<LFO> lfoFilter_;
|
||||||
|
|
||||||
ADSREnvelope egAmplitude_ { resources_.getMidiState() };
|
ADSREnvelope egAmplitude_ { resources_.getMidiState(), resources_.getCurves() };
|
||||||
std::unique_ptr<ADSREnvelope> egPitch_;
|
std::unique_ptr<ADSREnvelope> egPitch_;
|
||||||
std::unique_ptr<ADSREnvelope> egFilter_;
|
std::unique_ptr<ADSREnvelope> egFilter_;
|
||||||
|
|
||||||
|
|
@ -1853,7 +1853,7 @@ void Voice::setPitchEGEnabledPerVoice(bool havePitchEG)
|
||||||
{
|
{
|
||||||
Impl& impl = *impl_;
|
Impl& impl = *impl_;
|
||||||
if (havePitchEG)
|
if (havePitchEG)
|
||||||
impl.egPitch_.reset(new ADSREnvelope(impl.resources_.getMidiState()));
|
impl.egPitch_.reset(new ADSREnvelope(impl.resources_.getMidiState(), impl.resources_.getCurves()));
|
||||||
else
|
else
|
||||||
impl.egPitch_.reset();
|
impl.egPitch_.reset();
|
||||||
}
|
}
|
||||||
|
|
@ -1862,7 +1862,7 @@ void Voice::setFilterEGEnabledPerVoice(bool haveFilterEG)
|
||||||
{
|
{
|
||||||
Impl& impl = *impl_;
|
Impl& impl = *impl_;
|
||||||
if (haveFilterEG)
|
if (haveFilterEG)
|
||||||
impl.egFilter_.reset(new ADSREnvelope(impl.resources_.getMidiState()));
|
impl.egFilter_.reset(new ADSREnvelope(impl.resources_.getMidiState(), impl.resources_.getCurves()));
|
||||||
else
|
else
|
||||||
impl.egFilter_.reset();
|
impl.egFilter_.reset();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,158 +15,165 @@ TEST_CASE("[EGDescription] Attack range")
|
||||||
{
|
{
|
||||||
sfz::EGDescription eg;
|
sfz::EGDescription eg;
|
||||||
sfz::MidiState state;
|
sfz::MidiState state;
|
||||||
|
sfz::CurveSet curveSet;
|
||||||
eg.attack = 1;
|
eg.attack = 1;
|
||||||
eg.vel2attack = -1.27f;
|
eg.vel2attack = -1.27f;
|
||||||
eg.ccAttack[63] = 1.27f;
|
eg.ccAttack[63].modifier = 1.27f;
|
||||||
REQUIRE(eg.getAttack(state, 0_norm) == 1.0f);
|
REQUIRE(eg.getAttack(state, curveSet, 0_norm) == 1.0f);
|
||||||
//REQUIRE(eg.getAttack(state, 127_norm) == 0.0f);
|
//REQUIRE(eg.getAttack(state, curveSet, 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, curveSet, 127_norm) == 1.0f);
|
||||||
REQUIRE(eg.getAttack(state, 0_norm) == 2.27f);
|
REQUIRE(eg.getAttack(state, curveSet, 0_norm) == 2.27f);
|
||||||
//eg.ccAttack[63] = 127.0f;
|
//eg.ccAttack[63].modifier = 127.0f;
|
||||||
//REQUIRE(eg.getAttack(state, 0_norm) == 100.0f);
|
//REQUIRE(eg.getAttack(state, curveSet, 0_norm) == 100.0f);
|
||||||
eg.ccAttack[63] = 1.27f;
|
eg.ccAttack[63].modifier = 1.27f;
|
||||||
eg.ccAttack[65] = 1.0f;
|
eg.ccAttack[65].modifier = 1.0f;
|
||||||
REQUIRE(eg.getAttack(state, 0_norm) == 2.27f);
|
REQUIRE(eg.getAttack(state, curveSet, 0_norm) == 2.27f);
|
||||||
REQUIRE(eg.getAttack(state, 127_norm) == 1.0f);
|
REQUIRE(eg.getAttack(state, curveSet, 127_norm) == 1.0f);
|
||||||
state.ccEvent(0, 65, 127_norm);
|
state.ccEvent(0, 65, 127_norm);
|
||||||
REQUIRE(eg.getAttack(state, 0_norm) == 3.27f);
|
REQUIRE(eg.getAttack(state, curveSet, 0_norm) == 3.27f);
|
||||||
REQUIRE(eg.getAttack(state, 127_norm) == 2.0f);
|
REQUIRE(eg.getAttack(state, curveSet, 127_norm) == 2.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("[EGDescription] Delay range")
|
TEST_CASE("[EGDescription] Delay range")
|
||||||
{
|
{
|
||||||
sfz::EGDescription eg;
|
sfz::EGDescription eg;
|
||||||
sfz::MidiState state;
|
sfz::MidiState state;
|
||||||
|
sfz::CurveSet curveSet;
|
||||||
eg.delay = 1;
|
eg.delay = 1;
|
||||||
eg.vel2delay = -1.27f;
|
eg.vel2delay = -1.27f;
|
||||||
eg.ccDelay[63] = 1.27f;
|
eg.ccDelay[63].modifier = 1.27f;
|
||||||
REQUIRE(eg.getDelay(state, 0_norm) == 1.0f);
|
REQUIRE(eg.getDelay(state, curveSet, 0_norm) == 1.0f);
|
||||||
//REQUIRE(eg.getDelay(state, 127_norm) == 0.0f);
|
//REQUIRE(eg.getDelay(state, curveSet, 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, curveSet, 127_norm) == 1.0f);
|
||||||
REQUIRE(eg.getDelay(state, 0_norm, 1) == 2.27f);
|
REQUIRE(eg.getDelay(state, curveSet, 0_norm, 1) == 2.27f);
|
||||||
//eg.ccDelay[63] = 127.0f;
|
//eg.ccDelay[63].modifier = 127.0f;
|
||||||
//REQUIRE(eg.getDelay(state, 0_norm) == 100.0f);
|
//REQUIRE(eg.getDelay(state, curveSet, 0_norm) == 100.0f);
|
||||||
eg.ccDelay[63] = 1.27f;
|
eg.ccDelay[63].modifier = 1.27f;
|
||||||
eg.ccDelay[65] = 1.0f;
|
eg.ccDelay[65].modifier = 1.0f;
|
||||||
REQUIRE(eg.getDelay(state, 0_norm) == 2.27f);
|
REQUIRE(eg.getDelay(state, curveSet, 0_norm) == 2.27f);
|
||||||
REQUIRE(eg.getDelay(state, 127_norm) == 1.0f);
|
REQUIRE(eg.getDelay(state, curveSet, 127_norm) == 1.0f);
|
||||||
state.ccEvent(0, 65, 127_norm);
|
state.ccEvent(0, 65, 127_norm);
|
||||||
REQUIRE(eg.getDelay(state, 0_norm) == 3.27f);
|
REQUIRE(eg.getDelay(state, curveSet, 0_norm) == 3.27f);
|
||||||
REQUIRE(eg.getDelay(state, 127_norm) == 2.0f);
|
REQUIRE(eg.getDelay(state, curveSet, 127_norm) == 2.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("[EGDescription] Decay range")
|
TEST_CASE("[EGDescription] Decay range")
|
||||||
{
|
{
|
||||||
sfz::EGDescription eg;
|
sfz::EGDescription eg;
|
||||||
sfz::MidiState state;
|
sfz::MidiState state;
|
||||||
|
sfz::CurveSet curveSet;
|
||||||
eg.decay = 1.0f;
|
eg.decay = 1.0f;
|
||||||
eg.vel2decay = -1.27f;
|
eg.vel2decay = -1.27f;
|
||||||
eg.ccDecay[63] = 1.27f;
|
eg.ccDecay[63].modifier = 1.27f;
|
||||||
REQUIRE(eg.getDecay(state, 0_norm) == 1.0f);
|
REQUIRE(eg.getDecay(state, curveSet, 0_norm) == 1.0f);
|
||||||
//REQUIRE(eg.getDecay(state, 127_norm) == 0.0f);
|
//REQUIRE(eg.getDecay(state, curveSet, 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, curveSet, 127_norm) == 1.0f);
|
||||||
REQUIRE(eg.getDecay(state, 0_norm) == 2.27f);
|
REQUIRE(eg.getDecay(state, curveSet, 0_norm) == 2.27f);
|
||||||
//eg.ccDecay[63] = 127.0f;
|
//eg.ccDecay[63].modifier = 127.0f;
|
||||||
//REQUIRE(eg.getDecay(state, 0_norm) == 100.0f);
|
//REQUIRE(eg.getDecay(state, curveSet, 0_norm) == 100.0f);
|
||||||
eg.ccDecay[63] = 1.27f;
|
eg.ccDecay[63].modifier = 1.27f;
|
||||||
eg.ccDecay[65] = 1.0f;
|
eg.ccDecay[65].modifier = 1.0f;
|
||||||
REQUIRE(eg.getDecay(state, 0_norm) == 2.27f);
|
REQUIRE(eg.getDecay(state, curveSet, 0_norm) == 2.27f);
|
||||||
REQUIRE(eg.getDecay(state, 127_norm) == 1.0f);
|
REQUIRE(eg.getDecay(state, curveSet, 127_norm) == 1.0f);
|
||||||
state.ccEvent(0, 65, 127_norm);
|
state.ccEvent(0, 65, 127_norm);
|
||||||
REQUIRE(eg.getDecay(state, 0_norm) == 3.27f);
|
REQUIRE(eg.getDecay(state, curveSet, 0_norm) == 3.27f);
|
||||||
REQUIRE(eg.getDecay(state, 127_norm) == 2.0f);
|
REQUIRE(eg.getDecay(state, curveSet, 127_norm) == 2.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("[EGDescription] Release range")
|
TEST_CASE("[EGDescription] Release range")
|
||||||
{
|
{
|
||||||
sfz::EGDescription eg;
|
sfz::EGDescription eg;
|
||||||
sfz::MidiState state;
|
sfz::MidiState state;
|
||||||
|
sfz::CurveSet curveSet;
|
||||||
eg.release = 1;
|
eg.release = 1;
|
||||||
eg.vel2release = -1.27f;
|
eg.vel2release = -1.27f;
|
||||||
eg.ccRelease[63] = 1.27f;
|
eg.ccRelease[63].modifier = 1.27f;
|
||||||
REQUIRE(eg.getRelease(state, 0_norm) == 1.0f);
|
REQUIRE(eg.getRelease(state, curveSet, 0_norm) == 1.0f);
|
||||||
//REQUIRE(eg.getRelease(state, 127_norm) == 0.0f);
|
//REQUIRE(eg.getRelease(state, curveSet, 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, curveSet, 127_norm) == 1.0f);
|
||||||
REQUIRE(eg.getRelease(state, 0_norm) == 2.27f);
|
REQUIRE(eg.getRelease(state, curveSet, 0_norm) == 2.27f);
|
||||||
//eg.ccRelease[63] = 127.0f;
|
//eg.ccRelease[63].modifier = 127.0f;
|
||||||
//REQUIRE(eg.getRelease(state, 0_norm) == 100.0f);
|
//REQUIRE(eg.getRelease(state, curveSet, 0_norm) == 100.0f);
|
||||||
eg.ccRelease[63] = 1.27f;
|
eg.ccRelease[63].modifier = 1.27f;
|
||||||
eg.ccRelease[65] = 1.0f;
|
eg.ccRelease[65].modifier = 1.0f;
|
||||||
REQUIRE(eg.getRelease(state, 0_norm) == 2.27f);
|
REQUIRE(eg.getRelease(state, curveSet, 0_norm) == 2.27f);
|
||||||
REQUIRE(eg.getRelease(state, 127_norm) == 1.0f);
|
REQUIRE(eg.getRelease(state, curveSet, 127_norm) == 1.0f);
|
||||||
state.ccEvent(0, 65, 127_norm);
|
state.ccEvent(0, 65, 127_norm);
|
||||||
REQUIRE(eg.getRelease(state, 0_norm) == 3.27f);
|
REQUIRE(eg.getRelease(state, curveSet, 0_norm) == 3.27f);
|
||||||
REQUIRE(eg.getRelease(state, 127_norm) == 2.0f);
|
REQUIRE(eg.getRelease(state, curveSet, 127_norm) == 2.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("[EGDescription] Hold range")
|
TEST_CASE("[EGDescription] Hold range")
|
||||||
{
|
{
|
||||||
sfz::EGDescription eg;
|
sfz::EGDescription eg;
|
||||||
sfz::MidiState state;
|
sfz::MidiState state;
|
||||||
|
sfz::CurveSet curveSet;
|
||||||
eg.hold = 1;
|
eg.hold = 1;
|
||||||
eg.vel2hold = -1.27f;
|
eg.vel2hold = -1.27f;
|
||||||
eg.ccHold[63] = 1.27f;
|
eg.ccHold[63].modifier = 1.27f;
|
||||||
REQUIRE(eg.getHold(state, 0_norm) == 1.0f);
|
REQUIRE(eg.getHold(state, curveSet, 0_norm) == 1.0f);
|
||||||
//REQUIRE(eg.getHold(state, 127_norm) == 0.0f);
|
//REQUIRE(eg.getHold(state, curveSet, 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, curveSet, 127_norm) == 1.0f);
|
||||||
REQUIRE(eg.getHold(state, 0_norm) == 2.27f);
|
REQUIRE(eg.getHold(state, curveSet, 0_norm) == 2.27f);
|
||||||
//eg.ccHold[63] = 127.0f;
|
//eg.ccHold[63].modifier = 127.0f;
|
||||||
//REQUIRE(eg.getHold(state, 0_norm) == 100.0f);
|
//REQUIRE(eg.getHold(state, curveSet, 0_norm) == 100.0f);
|
||||||
eg.ccHold[63] = 1.27f;
|
eg.ccHold[63].modifier = 1.27f;
|
||||||
eg.ccHold[65] = 1.0f;
|
eg.ccHold[65].modifier = 1.0f;
|
||||||
REQUIRE(eg.getHold(state, 0_norm) == 2.27f);
|
REQUIRE(eg.getHold(state, curveSet, 0_norm) == 2.27f);
|
||||||
REQUIRE(eg.getHold(state, 127_norm) == 1.0f);
|
REQUIRE(eg.getHold(state, curveSet, 127_norm) == 1.0f);
|
||||||
state.ccEvent(0, 65, 127_norm);
|
state.ccEvent(0, 65, 127_norm);
|
||||||
REQUIRE(eg.getHold(state, 0_norm) == 3.27f);
|
REQUIRE(eg.getHold(state, curveSet, 0_norm) == 3.27f);
|
||||||
REQUIRE(eg.getHold(state, 127_norm) == 2.0f);
|
REQUIRE(eg.getHold(state, curveSet, 127_norm) == 2.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("[EGDescription] Sustain level")
|
TEST_CASE("[EGDescription] Sustain level")
|
||||||
{
|
{
|
||||||
sfz::EGDescription eg;
|
sfz::EGDescription eg;
|
||||||
sfz::MidiState state;
|
sfz::MidiState state;
|
||||||
|
sfz::CurveSet curveSet;
|
||||||
eg.sustain = 50;
|
eg.sustain = 50;
|
||||||
eg.vel2sustain = -100;
|
eg.vel2sustain = -100;
|
||||||
eg.ccSustain[63] = 100.0f;
|
eg.ccSustain[63].modifier = 100.0f;
|
||||||
REQUIRE(eg.getSustain(state, 0_norm) == 50.0f);
|
REQUIRE(eg.getSustain(state, curveSet, 0_norm) == 50.0f);
|
||||||
//REQUIRE(eg.getSustain(state, 127_norm) == 0.0f);
|
//REQUIRE(eg.getSustain(state, curveSet, 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, curveSet, 127_norm) == 50.0f);
|
||||||
//eg.ccSustain[63] = 200.0f;
|
//eg.ccSustain[63].modifier = 200.0f;
|
||||||
//REQUIRE(eg.getSustain(state, 0_norm) == 100.0f);
|
//REQUIRE(eg.getSustain(state, curveSet, 0_norm) == 100.0f);
|
||||||
eg.sustain = 0;
|
eg.sustain = 0;
|
||||||
eg.ccSustain[63] = 50.0f;
|
eg.ccSustain[63].modifier = 50.0f;
|
||||||
eg.ccSustain[65] = 50.0f;
|
eg.ccSustain[65].modifier = 50.0f;
|
||||||
REQUIRE(eg.getSustain(state, 0_norm) == 50.0f);
|
REQUIRE(eg.getSustain(state, curveSet, 0_norm) == 50.0f);
|
||||||
//REQUIRE(eg.getSustain(state, 127_norm) == 0.0f);
|
//REQUIRE(eg.getSustain(state, curveSet, 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, curveSet, 0_norm) == 100.0f);
|
||||||
REQUIRE(eg.getSustain(state, 127_norm) == 0.0f);
|
REQUIRE(eg.getSustain(state, curveSet, 127_norm) == 0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("[EGDescription] Start level")
|
TEST_CASE("[EGDescription] Start level")
|
||||||
{
|
{
|
||||||
sfz::EGDescription eg;
|
sfz::EGDescription eg;
|
||||||
sfz::MidiState state;
|
sfz::MidiState state;
|
||||||
|
sfz::CurveSet curveSet;
|
||||||
eg.start = 0;
|
eg.start = 0;
|
||||||
eg.ccStart[63] = 127.0f;
|
eg.ccStart[63].modifier = 127.0f;
|
||||||
REQUIRE(eg.getStart(state, 0_norm) == 0.0f);
|
REQUIRE(eg.getStart(state, curveSet, 0_norm) == 0.0f);
|
||||||
REQUIRE(eg.getStart(state, 127_norm) == 0.0f);
|
REQUIRE(eg.getStart(state, curveSet, 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, curveSet, 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, curveSet, 0_norm) == 0.0f);
|
||||||
eg.start = 0;
|
eg.start = 0;
|
||||||
eg.ccStart[63] = 50.0f;
|
eg.ccStart[63].modifier = 50.0f;
|
||||||
eg.ccStart[65] = 50.0f;
|
eg.ccStart[65].modifier = 50.0f;
|
||||||
REQUIRE(eg.getStart(state, 0_norm) == 50.0f);
|
REQUIRE(eg.getStart(state, curveSet, 0_norm) == 50.0f);
|
||||||
REQUIRE(eg.getStart(state, 127_norm) == 50.0f);
|
REQUIRE(eg.getStart(state, curveSet, 127_norm) == 50.0f);
|
||||||
state.ccEvent(0, 65, 127_norm);
|
state.ccEvent(0, 65, 127_norm);
|
||||||
REQUIRE(eg.getStart(state, 0_norm) == 100.0f);
|
REQUIRE(eg.getStart(state, curveSet, 0_norm) == 100.0f);
|
||||||
REQUIRE(eg.getStart(state, 127_norm) == 100.0f);
|
REQUIRE(eg.getStart(state, curveSet, 127_norm) == 100.0f);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue