diff --git a/src/sfizz/Region.cpp b/src/sfizz/Region.cpp index b48ed7f3..f7ff8798 100644 --- a/src/sfizz/Region.cpp +++ b/src/sfizz/Region.cpp @@ -1169,11 +1169,10 @@ bool sfz::Region::parseOpcode(const Opcode& rawOpcode) return false; if (!extendIfNecessary(flexEGs, egNumber, Default::numFlexEGs)) return false; - if (auto value = readOpcode(opcode.value, Range { 0, 1 })) { + if (auto ampeg = readBooleanFromOpcode(opcode)) { FlexEGDescription& desc = flexEGs[egNumber - 1]; - bool ampeg = *value != 0; - if (desc.ampeg != ampeg) { - desc.ampeg = ampeg; + if (desc.ampeg != *ampeg) { + desc.ampeg = *ampeg; flexAmpEG = absl::nullopt; for (size_t i = 0, n = flexEGs.size(); i < n && !flexAmpEG; ++i) { if (flexEGs[i].ampeg) diff --git a/tests/FlexEGT.cpp b/tests/FlexEGT.cpp index 229bee47..9d380127 100644 --- a/tests/FlexEGT.cpp +++ b/tests/FlexEGT.cpp @@ -41,7 +41,7 @@ TEST_CASE("[FlexEG] Values") REQUIRE( egDescription.points[4].time == .4_a ); REQUIRE( egDescription.points[4].level == 1.0_a ); REQUIRE( egDescription.sustain == 3 ); - REQUIRE(synth.getResources().modMatrix.toDotGraph() == createReferenceGraph({ + REQUIRE(synth.getResources().modMatrix.toDotGraph() == createDefaultGraph({ 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[2].time == .1_a ); REQUIRE( egDescription.points[2].level == .25_a ); - REQUIRE( synth.getResources().modMatrix.toDotGraph() == createReferenceGraph({}) ); + REQUIRE( synth.getResources().modMatrix.toDotGraph() == createDefaultGraph({}) ); } TEST_CASE("[FlexEG] Connections") @@ -85,7 +85,7 @@ TEST_CASE("[FlexEG] Connections") REQUIRE(synth.getNumRegions() == 6); REQUIRE( synth.getRegionView(0)->flexEGs.size() == 1 ); 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 {1}" -> "Pan {1}")", R"("EG 1 {2}" -> "Width {2}")", diff --git a/tests/ModulationsT.cpp b/tests/ModulationsT.cpp index 05136501..634a92a2 100644 --- a/tests/ModulationsT.cpp +++ b/tests/ModulationsT.cpp @@ -92,7 +92,7 @@ width_oncc425=29 )"); 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 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}")", @@ -111,7 +111,7 @@ TEST_CASE("[Modulations] Filter CC connections") )"); 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 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}")", @@ -129,7 +129,7 @@ TEST_CASE("[Modulations] EQ CC connections") )"); 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 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}")", @@ -150,7 +150,7 @@ TEST_CASE("[Modulations] LFO Filter connections") )"); const std::string graph = synth.getResources().modMatrix.toDotGraph(); - REQUIRE(graph == createReferenceGraph({ + REQUIRE(graph == createDefaultGraph({ R"("LFO 1 {0}" -> "FilterCutoff {0, N=1}")", R"("LFO 2 {0}" -> "FilterCutoff {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(); - REQUIRE(graph == createReferenceGraph({ + REQUIRE(graph == createDefaultGraph({ R"("EG 1 {0}" -> "FilterCutoff {0, N=1}")", R"("EG 2 {0}" -> "FilterCutoff {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(); - REQUIRE(graph == createReferenceGraph({ + REQUIRE(graph == createDefaultGraph({ R"("LFO 1 {0}" -> "EqBandwidth {0, N=1}")", R"("LFO 2 {0}" -> "EqFrequency {0, N=2}")", 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(); - REQUIRE(graph == createReferenceGraph({ + REQUIRE(graph == createDefaultGraph({ R"("EG 1 {0}" -> "EqBandwidth {0, N=1}")", R"("EG 2 {0}" -> "EqFrequency {0, N=2}")", 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}")", })); } + + +TEST_CASE("[Modulations] FlexEG Ampeg target") +{ + sfz::Synth synth; + + synth.loadSfzString(fs::current_path(), R"( + 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"( + 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"( + 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}")", + })); +} + diff --git a/tests/TestHelpers.cpp b/tests/TestHelpers.cpp index 6e1fee3f..300e1cef 100644 --- a/tests/TestHelpers.cpp +++ b/tests/TestHelpers.cpp @@ -69,7 +69,7 @@ unsigned numPlayingVoices(const sfz::Synth& synth) }); } -std::string createReferenceGraph(std::vector lines, int numRegions) +std::string createDefaultGraph(std::vector lines, int numRegions) { for (int regionIdx = 0; regionIdx < numRegions; ++regionIdx) { lines.push_back(absl::StrCat( @@ -87,6 +87,11 @@ std::string createReferenceGraph(std::vector lines, int numRegions) )); } + return createModulationDotGraph(lines); +}; + +std::string createModulationDotGraph(std::vector lines) +{ std::sort(lines.begin(), lines.end()); std::string graph; @@ -101,4 +106,4 @@ std::string createReferenceGraph(std::vector lines, int numRegions) graph += "}\n"; return graph; -}; +} diff --git a/tests/TestHelpers.h b/tests/TestHelpers.h index 272fb612..efc5d6d3 100644 --- a/tests/TestHelpers.h +++ b/tests/TestHelpers.h @@ -67,10 +67,17 @@ const std::vector getPlayingVoices(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 lines, int numRegions = 1); +std::string createDefaultGraph(std::vector lines, int numRegions = 1); + +/** + * @brief Create a dot graph with the specified lines. + * The lines are sorted. + * + */ +std::string createModulationDotGraph(std::vector lines); template inline bool approxEqual(absl::Span lhs, absl::Span rhs, Type eps = 1e-3)