Use the new boolean helper and test the ampeg connection

This commit is contained in:
Paul Ferrand 2020-10-04 23:00:52 +02:00
parent ab3715f7a9
commit 5b4e673fe7
5 changed files with 102 additions and 18 deletions

View file

@ -1169,11 +1169,10 @@ bool sfz::Region::parseOpcode(const Opcode& rawOpcode)
return false; return false;
if (!extendIfNecessary(flexEGs, egNumber, Default::numFlexEGs)) if (!extendIfNecessary(flexEGs, egNumber, Default::numFlexEGs))
return false; return false;
if (auto value = readOpcode(opcode.value, Range<int> { 0, 1 })) { if (auto ampeg = readBooleanFromOpcode(opcode)) {
FlexEGDescription& desc = flexEGs[egNumber - 1]; FlexEGDescription& desc = flexEGs[egNumber - 1];
bool ampeg = *value != 0; if (desc.ampeg != *ampeg) {
if (desc.ampeg != ampeg) { desc.ampeg = *ampeg;
desc.ampeg = ampeg;
flexAmpEG = absl::nullopt; flexAmpEG = absl::nullopt;
for (size_t i = 0, n = flexEGs.size(); i < n && !flexAmpEG; ++i) { for (size_t i = 0, n = flexEGs.size(); i < n && !flexAmpEG; ++i) {
if (flexEGs[i].ampeg) if (flexEGs[i].ampeg)

View file

@ -41,7 +41,7 @@ TEST_CASE("[FlexEG] Values")
REQUIRE( egDescription.points[4].time == .4_a ); REQUIRE( egDescription.points[4].time == .4_a );
REQUIRE( egDescription.points[4].level == 1.0_a ); REQUIRE( egDescription.points[4].level == 1.0_a );
REQUIRE( egDescription.sustain == 3 ); REQUIRE( egDescription.sustain == 3 );
REQUIRE(synth.getResources().modMatrix.toDotGraph() == createReferenceGraph({ REQUIRE(synth.getResources().modMatrix.toDotGraph() == createDefaultGraph({
R"("EG 1 {0}" -> "Amplitude {0}")", R"("EG 1 {0}" -> "Amplitude {0}")",
})); }));
} }
@ -67,7 +67,7 @@ TEST_CASE("[FlexEG] Default values")
REQUIRE( egDescription.points[1].level == 0.0_a ); REQUIRE( egDescription.points[1].level == 0.0_a );
REQUIRE( egDescription.points[2].time == .1_a ); REQUIRE( egDescription.points[2].time == .1_a );
REQUIRE( egDescription.points[2].level == .25_a ); REQUIRE( egDescription.points[2].level == .25_a );
REQUIRE( synth.getResources().modMatrix.toDotGraph() == createReferenceGraph({}) ); REQUIRE( synth.getResources().modMatrix.toDotGraph() == createDefaultGraph({}) );
} }
TEST_CASE("[FlexEG] Connections") TEST_CASE("[FlexEG] Connections")
@ -85,7 +85,7 @@ TEST_CASE("[FlexEG] Connections")
REQUIRE(synth.getNumRegions() == 6); REQUIRE(synth.getNumRegions() == 6);
REQUIRE( synth.getRegionView(0)->flexEGs.size() == 1 ); REQUIRE( synth.getRegionView(0)->flexEGs.size() == 1 );
REQUIRE( synth.getRegionView(0)->flexEGs[0].points.size() == 2 ); REQUIRE( synth.getRegionView(0)->flexEGs[0].points.size() == 2 );
REQUIRE( synth.getResources().modMatrix.toDotGraph() == createReferenceGraph({ REQUIRE( synth.getResources().modMatrix.toDotGraph() == createDefaultGraph({
R"("EG 1 {0}" -> "Amplitude {0}")", R"("EG 1 {0}" -> "Amplitude {0}")",
R"("EG 1 {1}" -> "Pan {1}")", R"("EG 1 {1}" -> "Pan {1}")",
R"("EG 1 {2}" -> "Width {2}")", R"("EG 1 {2}" -> "Width {2}")",

View file

@ -92,7 +92,7 @@ width_oncc425=29
)"); )");
const std::string graph = synth.getResources().modMatrix.toDotGraph(); const std::string graph = synth.getResources().modMatrix.toDotGraph();
REQUIRE(graph == createReferenceGraph({ REQUIRE(graph == createDefaultGraph({
R"("Controller 20 {curve=3, smooth=0, value=59, step=0}" -> "Amplitude {0}")", R"("Controller 20 {curve=3, smooth=0, value=59, step=0}" -> "Amplitude {0}")",
R"("Controller 42 {curve=0, smooth=32, value=71, step=0}" -> "Pitch {0}")", R"("Controller 42 {curve=0, smooth=32, value=71, step=0}" -> "Pitch {0}")",
R"("Controller 36 {curve=0, smooth=0, value=14.5, step=1.5}" -> "Pan {0}")", R"("Controller 36 {curve=0, smooth=0, value=14.5, step=1.5}" -> "Pan {0}")",
@ -111,7 +111,7 @@ TEST_CASE("[Modulations] Filter CC connections")
)"); )");
const std::string graph = synth.getResources().modMatrix.toDotGraph(); const std::string graph = synth.getResources().modMatrix.toDotGraph();
REQUIRE(graph == createReferenceGraph({ REQUIRE(graph == createDefaultGraph({
R"("Controller 1 {curve=0, smooth=10, value=2, step=0}" -> "FilterResonance {0, N=3}")", R"("Controller 1 {curve=0, smooth=10, value=2, step=0}" -> "FilterResonance {0, N=3}")",
R"("Controller 2 {curve=2, smooth=0, value=100, step=0}" -> "FilterCutoff {0, N=2}")", R"("Controller 2 {curve=2, smooth=0, value=100, step=0}" -> "FilterCutoff {0, N=2}")",
R"("Controller 3 {curve=0, smooth=0, value=5, step=0.5}" -> "FilterGain {0, N=1}")", R"("Controller 3 {curve=0, smooth=0, value=5, step=0.5}" -> "FilterGain {0, N=1}")",
@ -129,7 +129,7 @@ TEST_CASE("[Modulations] EQ CC connections")
)"); )");
const std::string graph = synth.getResources().modMatrix.toDotGraph(); const std::string graph = synth.getResources().modMatrix.toDotGraph();
REQUIRE(graph == createReferenceGraph({ REQUIRE(graph == createDefaultGraph({
R"("Controller 1 {curve=0, smooth=10, value=2, step=0}" -> "EqBandwidth {0, N=3}")", R"("Controller 1 {curve=0, smooth=10, value=2, step=0}" -> "EqBandwidth {0, N=3}")",
R"("Controller 2 {curve=0, smooth=0, value=5, step=0.5}" -> "EqGain {0, N=1}")", R"("Controller 2 {curve=0, smooth=0, value=5, step=0.5}" -> "EqGain {0, N=1}")",
R"("Controller 3 {curve=3, smooth=0, value=300, step=0}" -> "EqFrequency {0, N=2}")", R"("Controller 3 {curve=3, smooth=0, value=300, step=0}" -> "EqFrequency {0, N=2}")",
@ -150,7 +150,7 @@ TEST_CASE("[Modulations] LFO Filter connections")
)"); )");
const std::string graph = synth.getResources().modMatrix.toDotGraph(); const std::string graph = synth.getResources().modMatrix.toDotGraph();
REQUIRE(graph == createReferenceGraph({ REQUIRE(graph == createDefaultGraph({
R"("LFO 1 {0}" -> "FilterCutoff {0, N=1}")", R"("LFO 1 {0}" -> "FilterCutoff {0, N=1}")",
R"("LFO 2 {0}" -> "FilterCutoff {0, N=1}")", R"("LFO 2 {0}" -> "FilterCutoff {0, N=1}")",
R"("LFO 3 {0}" -> "FilterResonance {0, N=1}")", R"("LFO 3 {0}" -> "FilterResonance {0, N=1}")",
@ -174,7 +174,7 @@ TEST_CASE("[Modulations] EG Filter connections")
)"); )");
const std::string graph = synth.getResources().modMatrix.toDotGraph(); const std::string graph = synth.getResources().modMatrix.toDotGraph();
REQUIRE(graph == createReferenceGraph({ REQUIRE(graph == createDefaultGraph({
R"("EG 1 {0}" -> "FilterCutoff {0, N=1}")", R"("EG 1 {0}" -> "FilterCutoff {0, N=1}")",
R"("EG 2 {0}" -> "FilterCutoff {0, N=1}")", R"("EG 2 {0}" -> "FilterCutoff {0, N=1}")",
R"("EG 3 {0}" -> "FilterResonance {0, N=1}")", R"("EG 3 {0}" -> "FilterResonance {0, N=1}")",
@ -198,7 +198,7 @@ TEST_CASE("[Modulations] LFO EQ connections")
)"); )");
const std::string graph = synth.getResources().modMatrix.toDotGraph(); const std::string graph = synth.getResources().modMatrix.toDotGraph();
REQUIRE(graph == createReferenceGraph({ REQUIRE(graph == createDefaultGraph({
R"("LFO 1 {0}" -> "EqBandwidth {0, N=1}")", R"("LFO 1 {0}" -> "EqBandwidth {0, N=1}")",
R"("LFO 2 {0}" -> "EqFrequency {0, N=2}")", R"("LFO 2 {0}" -> "EqFrequency {0, N=2}")",
R"("LFO 3 {0}" -> "EqGain {0, N=3}")", R"("LFO 3 {0}" -> "EqGain {0, N=3}")",
@ -222,7 +222,7 @@ TEST_CASE("[Modulations] EG EQ connections")
)"); )");
const std::string graph = synth.getResources().modMatrix.toDotGraph(); const std::string graph = synth.getResources().modMatrix.toDotGraph();
REQUIRE(graph == createReferenceGraph({ REQUIRE(graph == createDefaultGraph({
R"("EG 1 {0}" -> "EqBandwidth {0, N=1}")", R"("EG 1 {0}" -> "EqBandwidth {0, N=1}")",
R"("EG 2 {0}" -> "EqFrequency {0, N=2}")", R"("EG 2 {0}" -> "EqFrequency {0, N=2}")",
R"("EG 3 {0}" -> "EqGain {0, N=3}")", R"("EG 3 {0}" -> "EqGain {0, N=3}")",
@ -231,3 +231,76 @@ TEST_CASE("[Modulations] EG EQ connections")
R"("EG 6 {0}" -> "EqFrequency {0, N=1}")", R"("EG 6 {0}" -> "EqFrequency {0, N=1}")",
})); }));
} }
TEST_CASE("[Modulations] FlexEG Ampeg target")
{
sfz::Synth synth;
synth.loadSfzString(fs::current_path(), R"(
<region> sample=*sine
eg1_time1=0 eg1_level1=1
eg1_time2=1 eg1_level2=0
eg1_time3=1 eg1_level3=.5 eg1_sustain=3
eg1_time4=1 eg1_level4=1
eg1_ampeg=1
)");
const std::string graph = synth.getResources().modMatrix.toDotGraph();
REQUIRE(graph == createModulationDotGraph({
R"("Controller 10 {curve=1, smooth=10, value=100, step=0}" -> "Pan {0}")",
R"("Controller 7 {curve=4, smooth=10, value=100, step=0}" -> "Amplitude {0}")",
R"("EG 1 {0}" -> "MasterAmplitude {0}")",
}));
}
TEST_CASE("[Modulations] FlexEG Ampeg target with 2 FlexEGs")
{
sfz::Synth synth;
synth.loadSfzString(fs::current_path(), R"(
<region> sample=*sine
eg1_time1=0 eg1_level1=1
eg1_time2=1 eg1_level2=0
eg1_time3=1 eg1_level3=.5 eg1_sustain=3
eg1_time4=1 eg1_level4=1
eg2_time1=0 eg2_level1=1
eg2_time2=1 eg2_level2=0
eg2_time3=1 eg2_level3=.5 eg1_sustain=3
eg2_ampeg=1
)");
const std::string graph = synth.getResources().modMatrix.toDotGraph();
REQUIRE(graph == createModulationDotGraph({
R"("Controller 10 {curve=1, smooth=10, value=100, step=0}" -> "Pan {0}")",
R"("Controller 7 {curve=4, smooth=10, value=100, step=0}" -> "Amplitude {0}")",
R"("EG 2 {0}" -> "MasterAmplitude {0}")",
}));
}
TEST_CASE("[Modulations] FlexEG Ampeg target with multiple EGs targeting ampeg")
{
sfz::Synth synth;
synth.loadSfzString(fs::current_path(), R"(
<region> sample=*sine
eg1_time1=0 eg1_level1=1
eg1_time2=1 eg1_level2=0
eg1_time3=1 eg1_level3=.5 eg1_sustain=3
eg1_time4=1 eg1_level4=1
eg1_ampeg=1
eg2_time1=0 eg2_level1=1
eg2_time2=1 eg2_level2=0
eg2_time3=1 eg2_level3=.5 eg1_sustain=3
eg2_ampeg=1
)");
const std::string graph = synth.getResources().modMatrix.toDotGraph();
REQUIRE(graph == createModulationDotGraph({
R"("Controller 10 {curve=1, smooth=10, value=100, step=0}" -> "Pan {0}")",
R"("Controller 7 {curve=4, smooth=10, value=100, step=0}" -> "Amplitude {0}")",
R"("EG 1 {0}" -> "MasterAmplitude {0}")",
}));
}

View file

@ -69,7 +69,7 @@ unsigned numPlayingVoices(const sfz::Synth& synth)
}); });
} }
std::string createReferenceGraph(std::vector<std::string> lines, int numRegions) std::string createDefaultGraph(std::vector<std::string> lines, int numRegions)
{ {
for (int regionIdx = 0; regionIdx < numRegions; ++regionIdx) { for (int regionIdx = 0; regionIdx < numRegions; ++regionIdx) {
lines.push_back(absl::StrCat( lines.push_back(absl::StrCat(
@ -87,6 +87,11 @@ std::string createReferenceGraph(std::vector<std::string> lines, int numRegions)
)); ));
} }
return createModulationDotGraph(lines);
};
std::string createModulationDotGraph(std::vector<std::string> lines)
{
std::sort(lines.begin(), lines.end()); std::sort(lines.begin(), lines.end());
std::string graph; std::string graph;
@ -101,4 +106,4 @@ std::string createReferenceGraph(std::vector<std::string> lines, int numRegions)
graph += "}\n"; graph += "}\n";
return graph; return graph;
}; }

View file

@ -67,10 +67,17 @@ const std::vector<const sfz::Voice*> getPlayingVoices(const sfz::Synth& synth);
unsigned numPlayingVoices(const sfz::Synth& synth); unsigned numPlayingVoices(const sfz::Synth& synth);
/** /**
* @brief Create the dot graph representation from a list of strings * @brief Create the default dot graph representation for standard regions
* *
*/ */
std::string createReferenceGraph(std::vector<std::string> lines, int numRegions = 1); std::string createDefaultGraph(std::vector<std::string> lines, int numRegions = 1);
/**
* @brief Create a dot graph with the specified lines.
* The lines are sorted.
*
*/
std::string createModulationDotGraph(std::vector<std::string> lines);
template <class Type> template <class Type>
inline bool approxEqual(absl::Span<const Type> lhs, absl::Span<const Type> rhs, Type eps = 1e-3) inline bool approxEqual(absl::Span<const Type> lhs, absl::Span<const Type> rhs, Type eps = 1e-3)