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
|
||||
{
|
||||
if (currentState == State::Delay)
|
||||
this->delay = delay + secondsToSamples(desc_->getDelay(midiState_, triggerVelocity_, delay));
|
||||
this->attackStep = secondsToLinRate(desc_->getAttack(midiState_, triggerVelocity_, delay));
|
||||
this->decayRate = secondsToExpRate(desc_->getDecay(midiState_, triggerVelocity_, delay));
|
||||
this->releaseRate = secondsToExpRate(desc_->getRelease(midiState_, triggerVelocity_, delay));
|
||||
this->hold = secondsToSamples(desc_->getHold(midiState_, triggerVelocity_, delay));
|
||||
this->sustain = clamp(desc_->getSustain(midiState_, triggerVelocity_, delay), 0.0f, 1.0f);
|
||||
this->start = clamp(desc_->getStart(midiState_, triggerVelocity_, delay), 0.0f, 1.0f);
|
||||
this->delay = delay + secondsToSamples(desc_->getDelay(midiState_, curveSet_, triggerVelocity_, delay));
|
||||
this->attackStep = secondsToLinRate(desc_->getAttack(midiState_, curveSet_, triggerVelocity_, delay));
|
||||
this->decayRate = secondsToExpRate(desc_->getDecay(midiState_, curveSet_, triggerVelocity_, delay));
|
||||
this->releaseRate = secondsToExpRate(desc_->getRelease(midiState_, curveSet_, triggerVelocity_, delay));
|
||||
this->hold = secondsToSamples(desc_->getHold(midiState_, curveSet_, triggerVelocity_, delay));
|
||||
this->sustain = clamp(desc_->getSustain(midiState_, curveSet_, triggerVelocity_, delay), 0.0f, 1.0f);
|
||||
this->start = clamp(desc_->getStart(midiState_, curveSet_, triggerVelocity_, delay), 0.0f, 1.0f);
|
||||
sustainThreshold = this->sustain + config::virtuallyZero;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,12 +14,13 @@ namespace sfz {
|
|||
* @brief Describe an attack/delay/sustain/release envelope that can
|
||||
* produce its coefficient in a blockwise manner for SIMD-type operations.
|
||||
*/
|
||||
|
||||
class ADSREnvelope {
|
||||
public:
|
||||
using Float = float;
|
||||
|
||||
ADSREnvelope(const MidiState& state)
|
||||
: midiState_(state) {}
|
||||
ADSREnvelope(const MidiState& state, CurveSet& curveSet)
|
||||
: midiState_(state), curveSet_(curveSet) {}
|
||||
/**
|
||||
* @brief Resets the ADSR envelope given a Region, the current midi state, and a delay and
|
||||
* trigger velocity
|
||||
|
|
@ -104,6 +105,7 @@ private:
|
|||
Float currentValue { 0.0 };
|
||||
const EGDescription* desc_ { nullptr };
|
||||
const MidiState& midiState_;
|
||||
CurveSet& curveSet_;
|
||||
float triggerVelocity_ { 0.0f };
|
||||
bool dynamic_ { false };
|
||||
int delay { 0 };
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@
|
|||
#include "utility/LeakDetector.h"
|
||||
#include <absl/types/optional.h>
|
||||
|
||||
#include "Curve.h"
|
||||
|
||||
namespace sfz {
|
||||
/**
|
||||
* @brief A description for an SFZ envelope generator, with its envelope parameters
|
||||
|
|
@ -66,13 +68,20 @@ struct EGDescription {
|
|||
float vel2sustain { Default::egPercentMod };
|
||||
float vel2depth { Default::egVel2Depth };
|
||||
|
||||
CCMap<float> ccAttack;
|
||||
CCMap<float> ccDecay;
|
||||
CCMap<float> ccDelay;
|
||||
CCMap<float> ccHold;
|
||||
CCMap<float> ccRelease;
|
||||
CCMap<float> ccStart;
|
||||
CCMap<float> ccSustain;
|
||||
CCMap<ModifierCurvePair<float>> ccAttack { ModifierCurvePair<float>{ Default::egTime, Default::curveCC } };
|
||||
CCMap<ModifierCurvePair<float>> ccDecay { ModifierCurvePair<float>{ Default::egTime, Default::curveCC } };
|
||||
CCMap<ModifierCurvePair<float>> ccDelay { ModifierCurvePair<float>{ Default::egTime, Default::curveCC } };
|
||||
CCMap<ModifierCurvePair<float>> ccHold { ModifierCurvePair<float>{ Default::egTime, Default::curveCC } };
|
||||
CCMap<ModifierCurvePair<float>> ccRelease { ModifierCurvePair<float>{ Default::egTime, Default::curveCC } };
|
||||
CCMap<ModifierCurvePair<float>> ccStart { ModifierCurvePair<float>{ Default::egPercentMod, Default::curveCC } };
|
||||
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 };
|
||||
|
||||
/**
|
||||
|
|
@ -82,12 +91,13 @@ struct EGDescription {
|
|||
* @param velocity
|
||||
* @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);
|
||||
float returnedValue { attack + velocity * vel2attack };
|
||||
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;
|
||||
}
|
||||
|
|
@ -98,12 +108,13 @@ struct EGDescription {
|
|||
* @param velocity
|
||||
* @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);
|
||||
float returnedValue { decay + velocity * vel2decay };
|
||||
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;
|
||||
}
|
||||
|
|
@ -114,12 +125,13 @@ struct EGDescription {
|
|||
* @param velocity
|
||||
* @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);
|
||||
float returnedValue { this->delay + velocity * vel2delay };
|
||||
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;
|
||||
}
|
||||
|
|
@ -130,12 +142,13 @@ struct EGDescription {
|
|||
* @param velocity
|
||||
* @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);
|
||||
float returnedValue { hold + velocity * vel2hold };
|
||||
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;
|
||||
}
|
||||
|
|
@ -146,12 +159,13 @@ struct EGDescription {
|
|||
* @param velocity
|
||||
* @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);
|
||||
float returnedValue { release + velocity * vel2release };
|
||||
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;
|
||||
}
|
||||
|
|
@ -162,12 +176,13 @@ struct EGDescription {
|
|||
* @param velocity
|
||||
* @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 };
|
||||
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;
|
||||
}
|
||||
|
|
@ -178,12 +193,13 @@ struct EGDescription {
|
|||
* @param velocity
|
||||
* @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);
|
||||
float returnedValue { sustain + velocity * vel2sustain };
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1110,49 +1110,98 @@ bool sfz::Region::parseEGOpcode(const Opcode& opcode, EGDescription& eg)
|
|||
if (opcode.parameters.back() >= config::numCCs)
|
||||
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;
|
||||
case_any_eg("decay_oncc&"): // also decaycc&
|
||||
if (opcode.parameters.back() >= config::numCCs)
|
||||
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;
|
||||
case_any_eg("delay_oncc&"): // also delaycc&
|
||||
if (opcode.parameters.back() >= config::numCCs)
|
||||
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;
|
||||
case_any_eg("hold_oncc&"): // also holdcc&
|
||||
if (opcode.parameters.back() >= config::numCCs)
|
||||
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;
|
||||
case_any_eg("release_oncc&"): // also releasecc&
|
||||
if (opcode.parameters.back() >= config::numCCs)
|
||||
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;
|
||||
case_any_eg("start_oncc&"): // also startcc&
|
||||
if (opcode.parameters.back() >= config::numCCs)
|
||||
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;
|
||||
case_any_eg("sustain_oncc&"): // also sustaincc&
|
||||
if (opcode.parameters.back() >= config::numCCs)
|
||||
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;
|
||||
|
||||
|
|
|
|||
|
|
@ -1222,6 +1222,90 @@ void sfz::Synth::dispatchMessage(Client& client, int delay, const char* path, co
|
|||
}
|
||||
} 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", "") {
|
||||
GET_REGION_OR_BREAK(indices[0])
|
||||
if (region.notePolyphony) {
|
||||
|
|
@ -1338,44 +1422,86 @@ void sfz::Synth::dispatchMessage(Client& client, int delay, const char* path, co
|
|||
|
||||
MATCH("/region&/ampeg_attack_cc&", "") {
|
||||
GET_REGION_OR_BREAK(indices[0])
|
||||
float value = region.amplitudeEG.ccAttack.getWithDefault(indices[1]);
|
||||
client.receive<'f'>(delay, path, value);
|
||||
const auto& cc = region.amplitudeEG.ccAttack.getWithDefault(indices[1]);
|
||||
client.receive<'f'>(delay, path, cc.modifier);
|
||||
} break;
|
||||
|
||||
MATCH("/region&/ampeg_decay_cc&", "") {
|
||||
GET_REGION_OR_BREAK(indices[0])
|
||||
float value = region.amplitudeEG.ccDecay.getWithDefault(indices[1]);
|
||||
client.receive<'f'>(delay, path, value);
|
||||
const auto& cc = region.amplitudeEG.ccDecay.getWithDefault(indices[1]);
|
||||
client.receive<'f'>(delay, path, cc.modifier);
|
||||
} break;
|
||||
|
||||
MATCH("/region&/ampeg_delay_cc&", "") {
|
||||
GET_REGION_OR_BREAK(indices[0])
|
||||
float value = region.amplitudeEG.ccDelay.getWithDefault(indices[1]);
|
||||
client.receive<'f'>(delay, path, value);
|
||||
const auto& cc = region.amplitudeEG.ccDelay.getWithDefault(indices[1]);
|
||||
client.receive<'f'>(delay, path, cc.modifier);
|
||||
} break;
|
||||
|
||||
MATCH("/region&/ampeg_hold_cc&", "") {
|
||||
GET_REGION_OR_BREAK(indices[0])
|
||||
float value = region.amplitudeEG.ccHold.getWithDefault(indices[1]);
|
||||
client.receive<'f'>(delay, path, value);
|
||||
const auto& cc = region.amplitudeEG.ccHold.getWithDefault(indices[1]);
|
||||
client.receive<'f'>(delay, path, cc.modifier);
|
||||
} break;
|
||||
|
||||
MATCH("/region&/ampeg_release_cc&", "") {
|
||||
GET_REGION_OR_BREAK(indices[0])
|
||||
float value = region.amplitudeEG.ccRelease.getWithDefault(indices[1]);
|
||||
client.receive<'f'>(delay, path, value);
|
||||
const auto& cc = region.amplitudeEG.ccRelease.getWithDefault(indices[1]);
|
||||
client.receive<'f'>(delay, path, cc.modifier);
|
||||
} break;
|
||||
|
||||
MATCH("/region&/ampeg_start_cc&", "") {
|
||||
GET_REGION_OR_BREAK(indices[0])
|
||||
float value = region.amplitudeEG.ccStart.getWithDefault(indices[1]);
|
||||
client.receive<'f'>(delay, path, value * 100.0f);
|
||||
const auto& cc = region.amplitudeEG.ccStart.getWithDefault(indices[1]);
|
||||
client.receive<'f'>(delay, path, cc.modifier * 100.0f);
|
||||
} break;
|
||||
|
||||
MATCH("/region&/ampeg_sustain_cc&", "") {
|
||||
GET_REGION_OR_BREAK(indices[0])
|
||||
float value = region.amplitudeEG.ccSustain.getWithDefault(indices[1]);
|
||||
client.receive<'f'>(delay, path, value * 100.0f);
|
||||
const auto& cc = region.amplitudeEG.ccSustain.getWithDefault(indices[1]);
|
||||
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;
|
||||
|
||||
MATCH("/region&/filter&/cutoff", "") {
|
||||
|
|
@ -1495,6 +1621,104 @@ void sfz::Synth::dispatchMessage(Client& client, int delay, const char* path, co
|
|||
}
|
||||
} 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", "") {
|
||||
GET_REGION_OR_BREAK(indices[0])
|
||||
GET_EQ_OR_BREAK(indices[1])
|
||||
|
|
|
|||
|
|
@ -275,7 +275,7 @@ struct Voice::Impl
|
|||
std::unique_ptr<LFO> lfoPitch_;
|
||||
std::unique_ptr<LFO> lfoFilter_;
|
||||
|
||||
ADSREnvelope egAmplitude_ { resources_.getMidiState() };
|
||||
ADSREnvelope egAmplitude_ { resources_.getMidiState(), resources_.getCurves() };
|
||||
std::unique_ptr<ADSREnvelope> egPitch_;
|
||||
std::unique_ptr<ADSREnvelope> egFilter_;
|
||||
|
||||
|
|
@ -1853,7 +1853,7 @@ void Voice::setPitchEGEnabledPerVoice(bool havePitchEG)
|
|||
{
|
||||
Impl& impl = *impl_;
|
||||
if (havePitchEG)
|
||||
impl.egPitch_.reset(new ADSREnvelope(impl.resources_.getMidiState()));
|
||||
impl.egPitch_.reset(new ADSREnvelope(impl.resources_.getMidiState(), impl.resources_.getCurves()));
|
||||
else
|
||||
impl.egPitch_.reset();
|
||||
}
|
||||
|
|
@ -1862,7 +1862,7 @@ void Voice::setFilterEGEnabledPerVoice(bool haveFilterEG)
|
|||
{
|
||||
Impl& impl = *impl_;
|
||||
if (haveFilterEG)
|
||||
impl.egFilter_.reset(new ADSREnvelope(impl.resources_.getMidiState()));
|
||||
impl.egFilter_.reset(new ADSREnvelope(impl.resources_.getMidiState(), impl.resources_.getCurves()));
|
||||
else
|
||||
impl.egFilter_.reset();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,158 +15,165 @@ TEST_CASE("[EGDescription] Attack range")
|
|||
{
|
||||
sfz::EGDescription eg;
|
||||
sfz::MidiState state;
|
||||
sfz::CurveSet curveSet;
|
||||
eg.attack = 1;
|
||||
eg.vel2attack = -1.27f;
|
||||
eg.ccAttack[63] = 1.27f;
|
||||
REQUIRE(eg.getAttack(state, 0_norm) == 1.0f);
|
||||
//REQUIRE(eg.getAttack(state, 127_norm) == 0.0f);
|
||||
eg.ccAttack[63].modifier = 1.27f;
|
||||
REQUIRE(eg.getAttack(state, curveSet, 0_norm) == 1.0f);
|
||||
//REQUIRE(eg.getAttack(state, curveSet, 127_norm) == 0.0f);
|
||||
state.ccEvent(0, 63, 127_norm);
|
||||
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_norm) == 100.0f);
|
||||
eg.ccAttack[63] = 1.27f;
|
||||
eg.ccAttack[65] = 1.0f;
|
||||
REQUIRE(eg.getAttack(state, 0_norm) == 2.27f);
|
||||
REQUIRE(eg.getAttack(state, 127_norm) == 1.0f);
|
||||
REQUIRE(eg.getAttack(state, curveSet, 127_norm) == 1.0f);
|
||||
REQUIRE(eg.getAttack(state, curveSet, 0_norm) == 2.27f);
|
||||
//eg.ccAttack[63].modifier = 127.0f;
|
||||
//REQUIRE(eg.getAttack(state, curveSet, 0_norm) == 100.0f);
|
||||
eg.ccAttack[63].modifier = 1.27f;
|
||||
eg.ccAttack[65].modifier = 1.0f;
|
||||
REQUIRE(eg.getAttack(state, curveSet, 0_norm) == 2.27f);
|
||||
REQUIRE(eg.getAttack(state, curveSet, 127_norm) == 1.0f);
|
||||
state.ccEvent(0, 65, 127_norm);
|
||||
REQUIRE(eg.getAttack(state, 0_norm) == 3.27f);
|
||||
REQUIRE(eg.getAttack(state, 127_norm) == 2.0f);
|
||||
REQUIRE(eg.getAttack(state, curveSet, 0_norm) == 3.27f);
|
||||
REQUIRE(eg.getAttack(state, curveSet, 127_norm) == 2.0f);
|
||||
}
|
||||
|
||||
TEST_CASE("[EGDescription] Delay range")
|
||||
{
|
||||
sfz::EGDescription eg;
|
||||
sfz::MidiState state;
|
||||
sfz::CurveSet curveSet;
|
||||
eg.delay = 1;
|
||||
eg.vel2delay = -1.27f;
|
||||
eg.ccDelay[63] = 1.27f;
|
||||
REQUIRE(eg.getDelay(state, 0_norm) == 1.0f);
|
||||
//REQUIRE(eg.getDelay(state, 127_norm) == 0.0f);
|
||||
eg.ccDelay[63].modifier = 1.27f;
|
||||
REQUIRE(eg.getDelay(state, curveSet, 0_norm) == 1.0f);
|
||||
//REQUIRE(eg.getDelay(state, curveSet, 127_norm) == 0.0f);
|
||||
state.ccEvent(0, 63, 127_norm);
|
||||
REQUIRE(eg.getDelay(state, 127_norm) == 1.0f);
|
||||
REQUIRE(eg.getDelay(state, 0_norm, 1) == 2.27f);
|
||||
//eg.ccDelay[63] = 127.0f;
|
||||
//REQUIRE(eg.getDelay(state, 0_norm) == 100.0f);
|
||||
eg.ccDelay[63] = 1.27f;
|
||||
eg.ccDelay[65] = 1.0f;
|
||||
REQUIRE(eg.getDelay(state, 0_norm) == 2.27f);
|
||||
REQUIRE(eg.getDelay(state, 127_norm) == 1.0f);
|
||||
REQUIRE(eg.getDelay(state, curveSet, 127_norm) == 1.0f);
|
||||
REQUIRE(eg.getDelay(state, curveSet, 0_norm, 1) == 2.27f);
|
||||
//eg.ccDelay[63].modifier = 127.0f;
|
||||
//REQUIRE(eg.getDelay(state, curveSet, 0_norm) == 100.0f);
|
||||
eg.ccDelay[63].modifier = 1.27f;
|
||||
eg.ccDelay[65].modifier = 1.0f;
|
||||
REQUIRE(eg.getDelay(state, curveSet, 0_norm) == 2.27f);
|
||||
REQUIRE(eg.getDelay(state, curveSet, 127_norm) == 1.0f);
|
||||
state.ccEvent(0, 65, 127_norm);
|
||||
REQUIRE(eg.getDelay(state, 0_norm) == 3.27f);
|
||||
REQUIRE(eg.getDelay(state, 127_norm) == 2.0f);
|
||||
REQUIRE(eg.getDelay(state, curveSet, 0_norm) == 3.27f);
|
||||
REQUIRE(eg.getDelay(state, curveSet, 127_norm) == 2.0f);
|
||||
}
|
||||
|
||||
TEST_CASE("[EGDescription] Decay range")
|
||||
{
|
||||
sfz::EGDescription eg;
|
||||
sfz::MidiState state;
|
||||
sfz::CurveSet curveSet;
|
||||
eg.decay = 1.0f;
|
||||
eg.vel2decay = -1.27f;
|
||||
eg.ccDecay[63] = 1.27f;
|
||||
REQUIRE(eg.getDecay(state, 0_norm) == 1.0f);
|
||||
//REQUIRE(eg.getDecay(state, 127_norm) == 0.0f);
|
||||
eg.ccDecay[63].modifier = 1.27f;
|
||||
REQUIRE(eg.getDecay(state, curveSet, 0_norm) == 1.0f);
|
||||
//REQUIRE(eg.getDecay(state, curveSet, 127_norm) == 0.0f);
|
||||
state.ccEvent(0, 63, 127_norm);
|
||||
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_norm) == 100.0f);
|
||||
eg.ccDecay[63] = 1.27f;
|
||||
eg.ccDecay[65] = 1.0f;
|
||||
REQUIRE(eg.getDecay(state, 0_norm) == 2.27f);
|
||||
REQUIRE(eg.getDecay(state, 127_norm) == 1.0f);
|
||||
REQUIRE(eg.getDecay(state, curveSet, 127_norm) == 1.0f);
|
||||
REQUIRE(eg.getDecay(state, curveSet, 0_norm) == 2.27f);
|
||||
//eg.ccDecay[63].modifier = 127.0f;
|
||||
//REQUIRE(eg.getDecay(state, curveSet, 0_norm) == 100.0f);
|
||||
eg.ccDecay[63].modifier = 1.27f;
|
||||
eg.ccDecay[65].modifier = 1.0f;
|
||||
REQUIRE(eg.getDecay(state, curveSet, 0_norm) == 2.27f);
|
||||
REQUIRE(eg.getDecay(state, curveSet, 127_norm) == 1.0f);
|
||||
state.ccEvent(0, 65, 127_norm);
|
||||
REQUIRE(eg.getDecay(state, 0_norm) == 3.27f);
|
||||
REQUIRE(eg.getDecay(state, 127_norm) == 2.0f);
|
||||
REQUIRE(eg.getDecay(state, curveSet, 0_norm) == 3.27f);
|
||||
REQUIRE(eg.getDecay(state, curveSet, 127_norm) == 2.0f);
|
||||
}
|
||||
|
||||
TEST_CASE("[EGDescription] Release range")
|
||||
{
|
||||
sfz::EGDescription eg;
|
||||
sfz::MidiState state;
|
||||
sfz::CurveSet curveSet;
|
||||
eg.release = 1;
|
||||
eg.vel2release = -1.27f;
|
||||
eg.ccRelease[63] = 1.27f;
|
||||
REQUIRE(eg.getRelease(state, 0_norm) == 1.0f);
|
||||
//REQUIRE(eg.getRelease(state, 127_norm) == 0.0f);
|
||||
eg.ccRelease[63].modifier = 1.27f;
|
||||
REQUIRE(eg.getRelease(state, curveSet, 0_norm) == 1.0f);
|
||||
//REQUIRE(eg.getRelease(state, curveSet, 127_norm) == 0.0f);
|
||||
state.ccEvent(0, 63, 127_norm);
|
||||
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_norm) == 100.0f);
|
||||
eg.ccRelease[63] = 1.27f;
|
||||
eg.ccRelease[65] = 1.0f;
|
||||
REQUIRE(eg.getRelease(state, 0_norm) == 2.27f);
|
||||
REQUIRE(eg.getRelease(state, 127_norm) == 1.0f);
|
||||
REQUIRE(eg.getRelease(state, curveSet, 127_norm) == 1.0f);
|
||||
REQUIRE(eg.getRelease(state, curveSet, 0_norm) == 2.27f);
|
||||
//eg.ccRelease[63].modifier = 127.0f;
|
||||
//REQUIRE(eg.getRelease(state, curveSet, 0_norm) == 100.0f);
|
||||
eg.ccRelease[63].modifier = 1.27f;
|
||||
eg.ccRelease[65].modifier = 1.0f;
|
||||
REQUIRE(eg.getRelease(state, curveSet, 0_norm) == 2.27f);
|
||||
REQUIRE(eg.getRelease(state, curveSet, 127_norm) == 1.0f);
|
||||
state.ccEvent(0, 65, 127_norm);
|
||||
REQUIRE(eg.getRelease(state, 0_norm) == 3.27f);
|
||||
REQUIRE(eg.getRelease(state, 127_norm) == 2.0f);
|
||||
REQUIRE(eg.getRelease(state, curveSet, 0_norm) == 3.27f);
|
||||
REQUIRE(eg.getRelease(state, curveSet, 127_norm) == 2.0f);
|
||||
}
|
||||
|
||||
TEST_CASE("[EGDescription] Hold range")
|
||||
{
|
||||
sfz::EGDescription eg;
|
||||
sfz::MidiState state;
|
||||
sfz::CurveSet curveSet;
|
||||
eg.hold = 1;
|
||||
eg.vel2hold = -1.27f;
|
||||
eg.ccHold[63] = 1.27f;
|
||||
REQUIRE(eg.getHold(state, 0_norm) == 1.0f);
|
||||
//REQUIRE(eg.getHold(state, 127_norm) == 0.0f);
|
||||
eg.ccHold[63].modifier = 1.27f;
|
||||
REQUIRE(eg.getHold(state, curveSet, 0_norm) == 1.0f);
|
||||
//REQUIRE(eg.getHold(state, curveSet, 127_norm) == 0.0f);
|
||||
state.ccEvent(0, 63, 127_norm);
|
||||
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_norm) == 100.0f);
|
||||
eg.ccHold[63] = 1.27f;
|
||||
eg.ccHold[65] = 1.0f;
|
||||
REQUIRE(eg.getHold(state, 0_norm) == 2.27f);
|
||||
REQUIRE(eg.getHold(state, 127_norm) == 1.0f);
|
||||
REQUIRE(eg.getHold(state, curveSet, 127_norm) == 1.0f);
|
||||
REQUIRE(eg.getHold(state, curveSet, 0_norm) == 2.27f);
|
||||
//eg.ccHold[63].modifier = 127.0f;
|
||||
//REQUIRE(eg.getHold(state, curveSet, 0_norm) == 100.0f);
|
||||
eg.ccHold[63].modifier = 1.27f;
|
||||
eg.ccHold[65].modifier = 1.0f;
|
||||
REQUIRE(eg.getHold(state, curveSet, 0_norm) == 2.27f);
|
||||
REQUIRE(eg.getHold(state, curveSet, 127_norm) == 1.0f);
|
||||
state.ccEvent(0, 65, 127_norm);
|
||||
REQUIRE(eg.getHold(state, 0_norm) == 3.27f);
|
||||
REQUIRE(eg.getHold(state, 127_norm) == 2.0f);
|
||||
REQUIRE(eg.getHold(state, curveSet, 0_norm) == 3.27f);
|
||||
REQUIRE(eg.getHold(state, curveSet, 127_norm) == 2.0f);
|
||||
}
|
||||
|
||||
TEST_CASE("[EGDescription] Sustain level")
|
||||
{
|
||||
sfz::EGDescription eg;
|
||||
sfz::MidiState state;
|
||||
sfz::CurveSet curveSet;
|
||||
eg.sustain = 50;
|
||||
eg.vel2sustain = -100;
|
||||
eg.ccSustain[63] = 100.0f;
|
||||
REQUIRE(eg.getSustain(state, 0_norm) == 50.0f);
|
||||
//REQUIRE(eg.getSustain(state, 127_norm) == 0.0f);
|
||||
eg.ccSustain[63].modifier = 100.0f;
|
||||
REQUIRE(eg.getSustain(state, curveSet, 0_norm) == 50.0f);
|
||||
//REQUIRE(eg.getSustain(state, curveSet, 127_norm) == 0.0f);
|
||||
state.ccEvent(0, 63, 127_norm);
|
||||
REQUIRE(eg.getSustain(state, 127_norm) == 50.0f);
|
||||
//eg.ccSustain[63] = 200.0f;
|
||||
//REQUIRE(eg.getSustain(state, 0_norm) == 100.0f);
|
||||
REQUIRE(eg.getSustain(state, curveSet, 127_norm) == 50.0f);
|
||||
//eg.ccSustain[63].modifier = 200.0f;
|
||||
//REQUIRE(eg.getSustain(state, curveSet, 0_norm) == 100.0f);
|
||||
eg.sustain = 0;
|
||||
eg.ccSustain[63] = 50.0f;
|
||||
eg.ccSustain[65] = 50.0f;
|
||||
REQUIRE(eg.getSustain(state, 0_norm) == 50.0f);
|
||||
//REQUIRE(eg.getSustain(state, 127_norm) == 0.0f);
|
||||
eg.ccSustain[63].modifier = 50.0f;
|
||||
eg.ccSustain[65].modifier = 50.0f;
|
||||
REQUIRE(eg.getSustain(state, curveSet, 0_norm) == 50.0f);
|
||||
//REQUIRE(eg.getSustain(state, curveSet, 127_norm) == 0.0f);
|
||||
state.ccEvent(0, 65, 127_norm);
|
||||
REQUIRE(eg.getSustain(state, 0_norm) == 100.0f);
|
||||
REQUIRE(eg.getSustain(state, 127_norm) == 0.0f);
|
||||
REQUIRE(eg.getSustain(state, curveSet, 0_norm) == 100.0f);
|
||||
REQUIRE(eg.getSustain(state, curveSet, 127_norm) == 0.0f);
|
||||
}
|
||||
|
||||
TEST_CASE("[EGDescription] Start level")
|
||||
{
|
||||
sfz::EGDescription eg;
|
||||
sfz::MidiState state;
|
||||
sfz::CurveSet curveSet;
|
||||
eg.start = 0;
|
||||
eg.ccStart[63] = 127.0f;
|
||||
REQUIRE(eg.getStart(state, 0_norm) == 0.0f);
|
||||
REQUIRE(eg.getStart(state, 127_norm) == 0.0f);
|
||||
eg.ccStart[63].modifier = 127.0f;
|
||||
REQUIRE(eg.getStart(state, curveSet, 0_norm) == 0.0f);
|
||||
REQUIRE(eg.getStart(state, curveSet, 127_norm) == 0.0f);
|
||||
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;
|
||||
//REQUIRE(eg.getStart(state, 0_norm) == 0.0f);
|
||||
//REQUIRE(eg.getStart(state, curveSet, 0_norm) == 0.0f);
|
||||
eg.start = 0;
|
||||
eg.ccStart[63] = 50.0f;
|
||||
eg.ccStart[65] = 50.0f;
|
||||
REQUIRE(eg.getStart(state, 0_norm) == 50.0f);
|
||||
REQUIRE(eg.getStart(state, 127_norm) == 50.0f);
|
||||
eg.ccStart[63].modifier = 50.0f;
|
||||
eg.ccStart[65].modifier = 50.0f;
|
||||
REQUIRE(eg.getStart(state, curveSet, 0_norm) == 50.0f);
|
||||
REQUIRE(eg.getStart(state, curveSet, 127_norm) == 50.0f);
|
||||
state.ccEvent(0, 65, 127_norm);
|
||||
REQUIRE(eg.getStart(state, 0_norm) == 100.0f);
|
||||
REQUIRE(eg.getStart(state, 127_norm) == 100.0f);
|
||||
REQUIRE(eg.getStart(state, curveSet, 0_norm) == 100.0f);
|
||||
REQUIRE(eg.getStart(state, curveSet, 127_norm) == 100.0f);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue