diff --git a/src/sfizz/Synth.cpp b/src/sfizz/Synth.cpp index ec102de3..52dfba4c 100644 --- a/src/sfizz/Synth.cpp +++ b/src/sfizz/Synth.cpp @@ -55,6 +55,8 @@ void sfz::Synth::onParseFullBlock(const std::string& header, const std::vector& members) } } -void sfz::Synth::handleGroupOpcodes(const std::vector& members) +void sfz::Synth::handleGroupOpcodes(const std::vector& members, const std::vector& masterMembers) { absl::optional groupIdx; unsigned maxPolyphony { config::maxVoices }; - for (auto& member : members) { + const auto parseOpcode = [&](const Opcode& member) { switch (member.lettersOnlyHash) { case hash("group"): setValueFromOpcode(member, groupIdx, Default::groupRange); @@ -191,7 +194,13 @@ void sfz::Synth::handleGroupOpcodes(const std::vector& members) setValueFromOpcode(member, maxPolyphony, Range(0, config::maxVoices)); break; } - } + }; + + for (auto& member : masterMembers) + parseOpcode(member); + + for (auto& member : members) + parseOpcode(member); if (groupIdx) setGroupPolyphony(*groupIdx, maxPolyphony); diff --git a/src/sfizz/Synth.h b/src/sfizz/Synth.h index a9ce64ab..16017f3a 100644 --- a/src/sfizz/Synth.h +++ b/src/sfizz/Synth.h @@ -454,7 +454,7 @@ private: * * @param members the opcodes of the block */ - void handleGroupOpcodes(const std::vector& members); + void handleGroupOpcodes(const std::vector& members, const std::vector& masterMembers); /** * @brief Helper function to dispatch opcodes * diff --git a/tests/SynthT.cpp b/tests/SynthT.cpp index 0434d9ce..bd0d28cc 100644 --- a/tests/SynthT.cpp +++ b/tests/SynthT.cpp @@ -397,3 +397,25 @@ TEST_CASE("[Synth] Not self-masking") REQUIRE(synth.getVoiceView(2)->getTriggerValue() == 64_norm); REQUIRE(!synth.getVoiceView(2)->canBeStolen()); } + +TEST_CASE("[Synth] Polyphony in master") +{ + sfz::Synth synth; + synth.loadSfzFile(fs::current_path() / "tests/TestFiles/master_polyphony.sfz"); + synth.noteOn(0, 65, 64); + synth.noteOn(0, 65, 64); + synth.noteOn(0, 65, 64); + REQUIRE(synth.getNumActiveVoices() == 2); // group polyphony should block the last note + synth.allSoundOff(); + REQUIRE(synth.getNumActiveVoices() == 0); + synth.noteOn(0, 63, 64); + synth.noteOn(0, 63, 64); + synth.noteOn(0, 63, 64); + REQUIRE(synth.getNumActiveVoices() == 2); // group polyphony should block the last note + synth.allSoundOff(); + REQUIRE(synth.getNumActiveVoices() == 0); + synth.noteOn(0, 61, 64); + synth.noteOn(0, 61, 64); + synth.noteOn(0, 61, 64); + REQUIRE(synth.getNumActiveVoices() == 3); +} diff --git a/tests/TestFiles/master_polyphony.sfz b/tests/TestFiles/master_polyphony.sfz new file mode 100644 index 00000000..88d7bd7a --- /dev/null +++ b/tests/TestFiles/master_polyphony.sfz @@ -0,0 +1,7 @@ + polyphony=2 + group=2 + sample=*sine key=65 + group=3 + sample=*sine key=63 + // Empty master resets the polyphony + sample=*sine key=61