Fix voice groups destroyed after polyphony changed

This commit is contained in:
Jean Pierre Cimalando 2021-02-02 12:28:32 +01:00
parent 00f2e7e261
commit 53fc2a03fa
3 changed files with 26 additions and 10 deletions

View file

@ -17,6 +17,11 @@ void sfz::PolyphonyGroup::removeVoice(const Voice* voice) noexcept
swapAndPopFirst(voices, [voice](const Voice* v) { return v == voice; }); swapAndPopFirst(voices, [voice](const Voice* v) { return v == voice; });
} }
void sfz::PolyphonyGroup::removeAllVoices() noexcept
{
voices.clear();
}
unsigned sfz::PolyphonyGroup::numPlayingVoices() const noexcept unsigned sfz::PolyphonyGroup::numPlayingVoices() const noexcept
{ {
return absl::c_count_if(voices, [](const Voice* v) { return absl::c_count_if(voices, [](const Voice* v) {

View file

@ -35,6 +35,10 @@ public:
* @param voice * @param voice
*/ */
void removeVoice(const Voice* voice) noexcept; void removeVoice(const Voice* voice) noexcept;
/**
* @brief Remove all the voices from this polyphony group.
*/
void removeAllVoices() noexcept;
/** /**
* @brief Get the polyphony limit for this group * @brief Get the polyphony limit for this group
* *

View file

@ -13,17 +13,22 @@ namespace sfz {
void VoiceManager::onVoiceStateChanging(NumericId<Voice> id, Voice::State state) void VoiceManager::onVoiceStateChanging(NumericId<Voice> id, Voice::State state)
{ {
(void)id;
if (state == Voice::State::idle) { if (state == Voice::State::idle) {
auto voice = getVoiceById(id); Voice* voice = getVoiceById(id);
RegionSet::removeVoiceFromHierarchy(voice->getRegion(), voice); const Region* region = voice->getRegion();
const uint32_t group = region->group;
RegionSet::removeVoiceFromHierarchy(region, voice);
swapAndPopFirst(activeVoices_, [voice](const Voice* v) { return v == voice; }); swapAndPopFirst(activeVoices_, [voice](const Voice* v) { return v == voice; });
polyphonyGroups_[voice->getRegion()->group].removeVoice(voice); ASSERT(group < polyphonyGroups_.size());
polyphonyGroups_[group].removeVoice(voice);
} else if (state == Voice::State::playing) { } else if (state == Voice::State::playing) {
auto voice = getVoiceById(id); Voice* voice = getVoiceById(id);
const Region* region = voice->getRegion();
const uint32_t group = region->group;
activeVoices_.push_back(voice); activeVoices_.push_back(voice);
RegionSet::registerVoiceInHierarchy(voice->getRegion(), voice); RegionSet::registerVoiceInHierarchy(region, voice);
polyphonyGroups_[voice->getRegion()->group].registerVoice(voice); ASSERT(group < polyphonyGroups_.size());
polyphonyGroups_[group].registerVoice(voice);
} }
} }
@ -81,8 +86,9 @@ bool VoiceManager::playingAttackVoice(const Region* releaseRegion) noexcept
void VoiceManager::ensureNumPolyphonyGroups(unsigned groupIdx) noexcept void VoiceManager::ensureNumPolyphonyGroups(unsigned groupIdx) noexcept
{ {
while (polyphonyGroups_.size() <= groupIdx) size_t neededSize = static_cast<size_t>(groupIdx) + 1;
polyphonyGroups_.emplace_back(); if (polyphonyGroups_.size() < neededSize)
polyphonyGroups_.resize(neededSize);
} }
void VoiceManager::setGroupPolyphony(unsigned groupIdx, unsigned polyphony) noexcept void VoiceManager::setGroupPolyphony(unsigned groupIdx, unsigned polyphony) noexcept
@ -99,7 +105,8 @@ const PolyphonyGroup* VoiceManager::getPolyphonyGroupView(int idx) const noexcep
void VoiceManager::clear() void VoiceManager::clear()
{ {
reset(); for (PolyphonyGroup& pg : polyphonyGroups_)
pg.removeAllVoices();
list_.clear(); list_.clear();
activeVoices_.clear(); activeVoices_.clear();
} }