Use the soft engine polyphony limit

This commit is contained in:
Paul Ferrand 2020-10-06 21:49:28 +02:00
parent 8071cd0131
commit 480a7d4628
5 changed files with 32 additions and 7 deletions

View file

@ -61,13 +61,14 @@ struct SisterVoiceRing {
*
* @param voice
* @param delay
* @param fast whether to apply a fast release
*/
template<class T,
absl::enable_if_t<std::is_same<Voice, absl::remove_const_t<T>>::value, int> = 0>
static void offAllSisters(T* voice, int delay) {
static void offAllSisters(T* voice, int delay, bool fast = false) {
if (voice != nullptr) {
SisterVoiceRing::applyToRing(voice, [&] (Voice* v) {
v->off(delay);
v->off(delay, fast);
});
}
}

View file

@ -71,6 +71,7 @@ void sfz::Synth::onVoiceStateChanged(NumericId<Voice> id, Voice::State state)
if (state == Voice::State::idle) {
auto voice = getVoiceById(id);
RegionSet::removeVoiceFromHierarchy(voice->getRegion(), voice);
engineSet->removeVoice(voice);
polyphonyGroups[voice->getRegion()->group].removeVoice(voice);
}
@ -744,7 +745,7 @@ sfz::Voice* sfz::Synth::findFreeVoice() noexcept
if (freeVoice != voices.end())
return freeVoice->get();
DBG("Engine polyphony reached");
DBG("Engine hard polyphony reached");
return {};
}
@ -972,6 +973,7 @@ void sfz::Synth::startVoice(Region* region, int delay, const TriggerEvent& trigg
checkRegionPolyphony(region, delay);
checkGroupPolyphony(region, delay);
checkSetPolyphony(region, delay);
checkEnginePolyphony(delay);
Voice* selectedVoice = findFreeVoice();
if (selectedVoice == nullptr)
@ -980,6 +982,7 @@ void sfz::Synth::startVoice(Region* region, int delay, const TriggerEvent& trigg
ASSERT(selectedVoice->isFree());
selectedVoice->startVoice(region, delay, triggerEvent);
ring.addVoiceToRing(selectedVoice);
engineSet->registerVoice(selectedVoice);
RegionSet::registerVoiceInHierarchy(region, selectedVoice);
polyphonyGroups[region->group].registerVoice(selectedVoice);
}
@ -1108,6 +1111,19 @@ void sfz::Synth::checkSetPolyphony(const Region* region, int delay) noexcept
}
}
void sfz::Synth::checkEnginePolyphony(int delay) noexcept
{
auto& activeVoices = engineSet->getActiveVoices();
if (activeVoices.size() >= static_cast<size_t>(numRequiredVoices)) {
tempPolyphonyArray.clear();
absl::c_copy_if(activeVoices,
std::back_inserter(tempPolyphonyArray), [](Voice* v) { return !v->releasedOrFree(); });
const auto voiceToSteal = stealer.steal(absl::MakeSpan(tempPolyphonyArray));
SisterVoiceRing::offAllSisters(voiceToSteal, delay, true);
}
}
void sfz::Synth::noteOnDispatch(int delay, int noteNumber, float velocity) noexcept
{
const auto randValue = randNoteDistribution(Random::randomGenerator);

View file

@ -865,6 +865,13 @@ private:
*/
void checkSetPolyphony(const Region* region, int delay) noexcept;
/**
* @brief Check the engine polyphony, fast releasing voices if necessary
*
* @param delay
*/
void checkEnginePolyphony(int delay) noexcept;
/**
* @brief Start a voice for a specific region.
* This will do the needed polyphony checks and voice stealing.

View file

@ -167,11 +167,11 @@ void sfz::Voice::release(int delay) noexcept
resources.modMatrix.releaseVoice(id, region->getId(), delay);
}
void sfz::Voice::off(int delay) noexcept
void sfz::Voice::off(int delay, bool fast) noexcept
{
if (!region->flexAmpEG) {
if (region->offMode == SfzOffMode::fast) {
egAmplitude.setReleaseTime( Default::offTime );
if (region->offMode == SfzOffMode::fast || fast) {
egAmplitude.setReleaseTime(Default::offTime);
} else if (region->offMode == SfzOffMode::time) {
egAmplitude.setReleaseTime(region->offTime);
}

View file

@ -328,8 +328,9 @@ public:
* and set the envelopes if necessary.
*
* @param delay
* @param fast whether to apply a fast release regardless of the off mode
*/
void off(int delay) noexcept;
void off(int delay, bool fast = false) noexcept;
/**
* @brief gets the age of the Voice