Modularize the cc dispatch and the matching between a playing voice and release regions
This commit is contained in:
parent
01c43f03d4
commit
e32348190f
2 changed files with 50 additions and 48 deletions
|
|
@ -911,15 +911,22 @@ void sfz::Synth::startVoice(Region* region, int delay, const TriggerEvent& trigg
|
||||||
polyphonyGroups[region->group].registerVoice(selectedVoice);
|
polyphonyGroups[region->group].registerVoice(selectedVoice);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool matchReleaseRegionAndVoice(const sfz::Region& region, const sfz::Voice& voice)
|
bool sfz::Synth::matchAttackRegion(const Region* releaseRegion) noexcept
|
||||||
{
|
{
|
||||||
const sfz::TriggerEvent& event = voice.getTriggerEvent();
|
const auto compatibleVoice = [releaseRegion](const Voice* v) -> bool {
|
||||||
|
const sfz::TriggerEvent& event = v->getTriggerEvent();
|
||||||
return (
|
return (
|
||||||
!voice.isFree()
|
!v->isFree()
|
||||||
&& event.type == sfz::TriggerEventType::NoteOn
|
&& event.type == sfz::TriggerEventType::NoteOn
|
||||||
&& region.keyRange.containsWithEnd(event.number)
|
&& releaseRegion->keyRange.containsWithEnd(event.number)
|
||||||
&& region.velocityRange.containsWithEnd(event.value)
|
&& releaseRegion->velocityRange.containsWithEnd(event.value)
|
||||||
);
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (absl::c_find_if(voiceViewArray, compatibleVoice) == voiceViewArray.end())
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sfz::Synth::noteOffDispatch(int delay, int noteNumber, float velocity) noexcept
|
void sfz::Synth::noteOffDispatch(int delay, int noteNumber, float velocity) noexcept
|
||||||
|
|
@ -930,19 +937,8 @@ void sfz::Synth::noteOffDispatch(int delay, int noteNumber, float velocity) noex
|
||||||
|
|
||||||
for (auto& region : noteActivationLists[noteNumber]) {
|
for (auto& region : noteActivationLists[noteNumber]) {
|
||||||
if (region->registerNoteOff(noteNumber, velocity, randValue)) {
|
if (region->registerNoteOff(noteNumber, velocity, randValue)) {
|
||||||
if (region->triggerOnNote && region->trigger == SfzTrigger::release && !region->rtDead) {
|
if (region->trigger == SfzTrigger::release && !region->rtDead && !matchAttackRegion(region))
|
||||||
// check that a voice with compatible trigger is playing
|
|
||||||
// FIXME: we're going twice over the voices, when the synth
|
|
||||||
// handles the regions completely these dispatch functions
|
|
||||||
// should be overhauled, also to include voice stealing on
|
|
||||||
// all events
|
|
||||||
const auto compatibleVoice = [region](const VoicePtr& v) -> bool {
|
|
||||||
return matchReleaseRegionAndVoice(*region, *v);
|
|
||||||
};
|
|
||||||
|
|
||||||
if (absl::c_find_if(voices, compatibleVoice) == voices.end())
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
startVoice(region, delay, triggerEvent, ring);
|
startVoice(region, delay, triggerEvent, ring);
|
||||||
}
|
}
|
||||||
|
|
@ -1036,6 +1032,16 @@ void sfz::Synth::checkSetPolyphony(const Region* region, int delay) noexcept
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sfz::Synth::checkOffGroups(Region* region, int delay) noexcept
|
||||||
|
{
|
||||||
|
for (auto& voice : voices) {
|
||||||
|
if (voice->checkOffGroup(delay, region->group)) {
|
||||||
|
const TriggerEvent& event = voice->getTriggerEvent();
|
||||||
|
noteOffDispatch(delay, event.number, event.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void sfz::Synth::noteOnDispatch(int delay, int noteNumber, float velocity) noexcept
|
void sfz::Synth::noteOnDispatch(int delay, int noteNumber, float velocity) noexcept
|
||||||
{
|
{
|
||||||
const auto randValue = randNoteDistribution(Random::randomGenerator);
|
const auto randValue = randNoteDistribution(Random::randomGenerator);
|
||||||
|
|
@ -1044,28 +1050,17 @@ void sfz::Synth::noteOnDispatch(int delay, int noteNumber, float velocity) noexc
|
||||||
|
|
||||||
for (auto& region : noteActivationLists[noteNumber]) {
|
for (auto& region : noteActivationLists[noteNumber]) {
|
||||||
if (region->registerNoteOn(noteNumber, velocity, randValue)) {
|
if (region->registerNoteOn(noteNumber, velocity, randValue)) {
|
||||||
for (auto& voice : voices) {
|
checkOffGroups(region, delay);
|
||||||
if (voice->checkOffGroup(delay, region->group)) {
|
|
||||||
const TriggerEvent& event = voice->getTriggerEvent();
|
|
||||||
noteOffDispatch(delay, event.number, event.value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
startVoice(region, delay, triggerEvent, ring);
|
startVoice(region, delay, triggerEvent, ring);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void sfz::Synth::checkDelayedReleases(Region* region, int delay, SisterVoiceRingBuilder& ring) noexcept
|
void sfz::Synth::startDelayedReleaseVoices(Region* region, int delay, SisterVoiceRingBuilder& ring) noexcept
|
||||||
{
|
{
|
||||||
if (!region->rtDead) {
|
if (!region->rtDead && !matchAttackRegion(region)) {
|
||||||
// check that a voice with compatible trigger is playing
|
|
||||||
const auto compatibleVoice = [region](const VoicePtr& v) -> bool {
|
|
||||||
return matchReleaseRegionAndVoice(*region, *v);
|
|
||||||
};
|
|
||||||
|
|
||||||
if (absl::c_find_if(voices, compatibleVoice) == voices.end())
|
|
||||||
region->delayedReleases.clear();
|
region->delayedReleases.clear();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& note: region->delayedReleases) {
|
for (auto& note: region->delayedReleases) {
|
||||||
|
|
@ -1073,7 +1068,6 @@ void sfz::Synth::checkDelayedReleases(Region* region, int delay, SisterVoiceRing
|
||||||
const TriggerEvent noteOffEvent { TriggerEventType::NoteOff, note.first, note.second };
|
const TriggerEvent noteOffEvent { TriggerEventType::NoteOff, note.first, note.second };
|
||||||
startVoice(region, delay, noteOffEvent, ring);
|
startVoice(region, delay, noteOffEvent, ring);
|
||||||
}
|
}
|
||||||
|
|
||||||
region->delayedReleases.clear();
|
region->delayedReleases.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1084,6 +1078,19 @@ void sfz::Synth::cc(int delay, int ccNumber, uint8_t ccValue) noexcept
|
||||||
hdcc(delay, ccNumber, normalizedCC);
|
hdcc(delay, ccNumber, normalizedCC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sfz::Synth::ccDispatch(int delay, int ccNumber, float value) noexcept
|
||||||
|
{
|
||||||
|
SisterVoiceRingBuilder ring;
|
||||||
|
const TriggerEvent triggerEvent { TriggerEventType::CC, ccNumber, value };
|
||||||
|
for (auto& region : ccActivationLists[ccNumber]) {
|
||||||
|
if (ccNumber == region->sustainCC)
|
||||||
|
startDelayedReleaseVoices(region, delay, ring);
|
||||||
|
|
||||||
|
if (region->registerCC(ccNumber, value))
|
||||||
|
startVoice(region, delay, triggerEvent, ring);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void sfz::Synth::hdcc(int delay, int ccNumber, float normValue) noexcept
|
void sfz::Synth::hdcc(int delay, int ccNumber, float normValue) noexcept
|
||||||
{
|
{
|
||||||
ASSERT(ccNumber < config::numCCs);
|
ASSERT(ccNumber < config::numCCs);
|
||||||
|
|
@ -1111,15 +1118,7 @@ void sfz::Synth::hdcc(int delay, int ccNumber, float normValue) noexcept
|
||||||
for (auto& voice : voices)
|
for (auto& voice : voices)
|
||||||
voice->registerCC(delay, ccNumber, normValue);
|
voice->registerCC(delay, ccNumber, normValue);
|
||||||
|
|
||||||
SisterVoiceRingBuilder ring;
|
ccDispatch(delay, ccNumber, normValue);
|
||||||
const TriggerEvent triggerEvent { TriggerEventType::CC, ccNumber, normValue };
|
|
||||||
for (auto& region : ccActivationLists[ccNumber]) {
|
|
||||||
if (ccNumber == region->sustainCC)
|
|
||||||
checkDelayedReleases(region, delay, ring);
|
|
||||||
|
|
||||||
if (region->registerCC(ccNumber, normValue))
|
|
||||||
startVoice(region, delay, triggerEvent, ring);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void sfz::Synth::pitchWheel(int delay, int pitch) noexcept
|
void sfz::Synth::pitchWheel(int delay, int pitch) noexcept
|
||||||
|
|
|
||||||
|
|
@ -727,6 +727,7 @@ private:
|
||||||
|
|
||||||
void noteOnDispatch(int delay, int noteNumber, float velocity) noexcept;
|
void noteOnDispatch(int delay, int noteNumber, float velocity) noexcept;
|
||||||
void noteOffDispatch(int delay, int noteNumber, float velocity) noexcept;
|
void noteOffDispatch(int delay, int noteNumber, float velocity) noexcept;
|
||||||
|
void ccDispatch(int delay, int ccNumber, float value) noexcept;
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
static void updateUsedCCsFromCCMap(std::bitset<sfz::config::numCCs>& usedCCs, const CCMap<T> map)
|
static void updateUsedCCsFromCCMap(std::bitset<sfz::config::numCCs>& usedCCs, const CCMap<T> map)
|
||||||
|
|
@ -785,7 +786,9 @@ private:
|
||||||
void checkGroupPolyphony(const Region* region, int delay) noexcept;
|
void checkGroupPolyphony(const Region* region, int delay) noexcept;
|
||||||
void checkSetPolyphony(const Region* region, int delay) noexcept;
|
void checkSetPolyphony(const Region* region, int delay) noexcept;
|
||||||
void startVoice(Region* region, int delay, const TriggerEvent& triggerEvent, SisterVoiceRingBuilder& ring) noexcept;
|
void startVoice(Region* region, int delay, const TriggerEvent& triggerEvent, SisterVoiceRingBuilder& ring) noexcept;
|
||||||
void checkDelayedReleases(Region* region, int delay, SisterVoiceRingBuilder& ring) noexcept;
|
void checkOffGroups(Region* region, int delay) noexcept;
|
||||||
|
void startDelayedReleaseVoices(Region* region, int delay, SisterVoiceRingBuilder& ring) noexcept;
|
||||||
|
bool matchAttackRegion(const Region* region) noexcept;
|
||||||
|
|
||||||
std::array<RegionViewVector, 128> noteActivationLists;
|
std::array<RegionViewVector, 128> noteActivationLists;
|
||||||
std::array<RegionViewVector, config::numCCs> ccActivationLists;
|
std::array<RegionViewVector, config::numCCs> ccActivationLists;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue