Add tests
This commit is contained in:
parent
503ff04f9b
commit
4de9b42427
4 changed files with 64 additions and 6 deletions
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include "FlexEGDescription.h"
|
#include "FlexEGDescription.h"
|
||||||
#include "Curve.h"
|
#include "Curve.h"
|
||||||
|
#include "MidiState.h"
|
||||||
#include <absl/container/flat_hash_map.h>
|
#include <absl/container/flat_hash_map.h>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
|
|
@ -84,4 +85,21 @@ void FlexEGs::clearUnusedCurves()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
float FlexEGPoint::getTime(const MidiState& state) const noexcept
|
||||||
|
{
|
||||||
|
float returnedValue { time };
|
||||||
|
for (const CCData<float>& mod : ccTime)
|
||||||
|
returnedValue += state.getCCValue(mod.cc) * mod.data;
|
||||||
|
return returnedValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
float FlexEGPoint::getLevel(const MidiState& state) const noexcept
|
||||||
|
{
|
||||||
|
float returnedValue { level };
|
||||||
|
for (const CCData<float>& mod : ccLevel)
|
||||||
|
returnedValue += state.getCCValue(mod.cc) * mod.data;
|
||||||
|
return returnedValue;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace sfz
|
} // namespace sfz
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
|
|
||||||
namespace sfz {
|
namespace sfz {
|
||||||
class Curve;
|
class Curve;
|
||||||
|
class MidiState;
|
||||||
|
|
||||||
namespace FlexEGs {
|
namespace FlexEGs {
|
||||||
std::shared_ptr<Curve> getShapeCurve(float shape);
|
std::shared_ptr<Curve> getShapeCurve(float shape);
|
||||||
|
|
@ -25,6 +26,9 @@ struct FlexEGPoint {
|
||||||
CCMap<float> ccTime;
|
CCMap<float> ccTime;
|
||||||
CCMap<float> ccLevel;
|
CCMap<float> ccLevel;
|
||||||
|
|
||||||
|
float getTime(const MidiState& state) const noexcept;
|
||||||
|
float getLevel(const MidiState& state) const noexcept;
|
||||||
|
|
||||||
void setShape(float shape);
|
void setShape(float shape);
|
||||||
float shape() const noexcept { return shape_; }
|
float shape() const noexcept { return shape_; }
|
||||||
const Curve& curve() const;
|
const Curve& curve() const;
|
||||||
|
|
|
||||||
|
|
@ -266,12 +266,8 @@ bool FlexEnvelope::Impl::advanceToStage(unsigned stageNumber)
|
||||||
|
|
||||||
const FlexEGPoint& point = desc.points[stageNumber];
|
const FlexEGPoint& point = desc.points[stageNumber];
|
||||||
stageSourceLevel_ = currentLevel_;
|
stageSourceLevel_ = currentLevel_;
|
||||||
stageTargetLevel_ = point.level;
|
stageTargetLevel_ = point.getLevel(midiState);
|
||||||
for (const CCData<float>& mod : point.ccLevel)
|
stageTime_ = point.getTime(midiState);
|
||||||
stageTargetLevel_ += midiState.getCCValue(mod.cc) * mod.data;
|
|
||||||
stageTime_ = point.time;
|
|
||||||
for (const CCData<float>& mod : point.ccTime)
|
|
||||||
stageTime_ += midiState.getCCValue(mod.cc) * mod.data;
|
|
||||||
stageSustained_ = int(stageNumber) == desc.sustain;
|
stageSustained_ = int(stageNumber) == desc.sustain;
|
||||||
stageCurve_ = &point.curve();
|
stageCurve_ = &point.curve();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -417,3 +417,43 @@ TEST_CASE("[FlexEG] Free-running flex AmpEG (no sustain)")
|
||||||
synth.renderBlock(buffer);
|
synth.renderBlock(buffer);
|
||||||
REQUIRE( synth.getNumActiveVoices() == 0 );
|
REQUIRE( synth.getNumActiveVoices() == 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("[FlexEG] Modulation of time and level")
|
||||||
|
{
|
||||||
|
sfz::Synth synth;
|
||||||
|
|
||||||
|
synth.loadSfzString(fs::current_path(), R"(
|
||||||
|
<region> sample=*noise
|
||||||
|
eg1_time1=0 eg1_level1=1
|
||||||
|
eg1_time2=0.7 eg1_level2=0.5
|
||||||
|
eg1_time2_oncc1=-0.7 eg1_level2_oncc2=0.5
|
||||||
|
eg1_time3=0.3 eg1_level3=0.0
|
||||||
|
)");
|
||||||
|
|
||||||
|
REQUIRE( synth.getNumRegions() == 1 );
|
||||||
|
const sfz::Region* region = synth.getRegionView(0);
|
||||||
|
REQUIRE( region->flexEGs.size() == 1 );
|
||||||
|
const sfz::FlexEGDescription& desc = synth.getRegionView(0)->flexEGs[0];
|
||||||
|
REQUIRE( desc.points.size() == 4 );
|
||||||
|
|
||||||
|
REQUIRE( desc.points[2].time == Approx(0.7f) );
|
||||||
|
REQUIRE( desc.points[2].level == Approx(0.5f) );
|
||||||
|
|
||||||
|
sfz::MidiState state;
|
||||||
|
|
||||||
|
REQUIRE( desc.points[2].getTime(state) == Approx(0.7f) );
|
||||||
|
state.ccEvent(0, 1, 0.0f);
|
||||||
|
REQUIRE( desc.points[2].getTime(state) == Approx(0.7f) );
|
||||||
|
state.ccEvent(0, 1, 0.5f);
|
||||||
|
REQUIRE( desc.points[2].getTime(state) == Approx(0.35f) );
|
||||||
|
state.ccEvent(0, 1, 1.0f);
|
||||||
|
REQUIRE( desc.points[2].getTime(state) == Approx(0.0f) );
|
||||||
|
|
||||||
|
REQUIRE( desc.points[2].getLevel(state) == Approx(0.5f) );
|
||||||
|
state.ccEvent(0, 2, 0.0f);
|
||||||
|
REQUIRE( desc.points[2].getLevel(state) == Approx(0.5f) );
|
||||||
|
state.ccEvent(0, 2, 0.5f);
|
||||||
|
REQUIRE( desc.points[2].getLevel(state) == Approx(0.75f) );
|
||||||
|
state.ccEvent(0, 2, 1.0f);
|
||||||
|
REQUIRE( desc.points[2].getLevel(state) == Approx(1.0f) );
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue