Changed the legato logic
The midistate now counts the active notes instead of it being per-region
This commit is contained in:
parent
2dbc870f9a
commit
0d0cf64405
6 changed files with 40 additions and 10 deletions
|
|
@ -14,7 +14,21 @@ void sfz::MidiState::noteOnEvent(int noteNumber, uint8_t velocity) noexcept
|
|||
if (noteNumber >= 0 && noteNumber < 128) {
|
||||
lastNoteVelocities[noteNumber] = velocity;
|
||||
noteOnTimes[noteNumber] = std::chrono::steady_clock::now();
|
||||
activeNotes++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void sfz::MidiState::noteOffEvent(int noteNumber, uint8_t velocity [[maybe_unused]]) noexcept
|
||||
{
|
||||
ASSERT(noteNumber >= 0 && noteNumber <= 127);
|
||||
ASSERT(velocity >= 0 && velocity <= 127);
|
||||
|
||||
if (noteNumber >= 0 && noteNumber < 128) {
|
||||
activeNotes--;
|
||||
ASSERT(activeNotes >= 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
float sfz::MidiState::getNoteDuration(int noteNumber) const
|
||||
|
|
@ -78,6 +92,7 @@ void sfz::MidiState::reset() noexcept
|
|||
ccValue = 0;
|
||||
|
||||
pitchBend = 0;
|
||||
activeNotes = 0;
|
||||
}
|
||||
|
||||
void sfz::MidiState::resetAllControllers() noexcept
|
||||
|
|
|
|||
|
|
@ -23,6 +23,16 @@ public:
|
|||
*/
|
||||
void noteOnEvent(int noteNumber, uint8_t velocity) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Update the state after a note off event
|
||||
*
|
||||
* @param noteNumber
|
||||
* @param velocity
|
||||
*/
|
||||
void noteOffEvent(int noteNumber, uint8_t velocity) noexcept;
|
||||
|
||||
int getActiveNotes() const noexcept { return activeNotes; }
|
||||
|
||||
/**
|
||||
* @brief Register a note off and get the note duration
|
||||
*
|
||||
|
|
@ -91,6 +101,7 @@ private:
|
|||
template<class T>
|
||||
using MidiNoteArray = std::array<T, 128>;
|
||||
using NoteOnTime = std::chrono::steady_clock::time_point;
|
||||
int activeNotes { 0 };
|
||||
/**
|
||||
* @brief Stores the note on times.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -523,9 +523,6 @@ bool sfz::Region::registerNoteOn(int noteNumber, uint8_t velocity, float randVal
|
|||
|
||||
const bool keyOk = keyRange.containsWithEnd(noteNumber);
|
||||
if (keyOk) {
|
||||
// Update the number of notes playing for the region
|
||||
activeNotesInRange++;
|
||||
|
||||
// Sequence activation
|
||||
sequenceCounter += 1;
|
||||
if ((sequenceCounter % sequenceLength) == sequencePosition - 1)
|
||||
|
|
@ -552,9 +549,9 @@ bool sfz::Region::registerNoteOn(int noteNumber, uint8_t velocity, float randVal
|
|||
|
||||
const bool velOk = velocityRange.containsWithEnd(velocity);
|
||||
const bool randOk = randRange.contains(randValue) || (randValue == 1.0f && randRange.getEnd() == 1.0f);
|
||||
const bool firstLegatoNote = (trigger == SfzTrigger::first && activeNotesInRange == 0);
|
||||
const bool firstLegatoNote = (trigger == SfzTrigger::first && midiState.getActiveNotes() == 1);
|
||||
const bool attackTrigger = (trigger == SfzTrigger::attack);
|
||||
const bool notFirstLegatoNote = (trigger == SfzTrigger::legato && activeNotesInRange > 0);
|
||||
const bool notFirstLegatoNote = (trigger == SfzTrigger::legato && midiState.getActiveNotes() > 1);
|
||||
|
||||
return keyOk && velOk && randOk && (attackTrigger || firstLegatoNote || notFirstLegatoNote);
|
||||
}
|
||||
|
|
@ -571,10 +568,6 @@ bool sfz::Region::registerNoteOff(int noteNumber, uint8_t velocity [[maybe_unuse
|
|||
|
||||
const bool keyOk = keyRange.containsWithEnd(noteNumber);
|
||||
|
||||
// Update the number of notes playing for the region
|
||||
if (keyOk)
|
||||
activeNotesInRange--;
|
||||
|
||||
if (!isSwitchedOn())
|
||||
return false;
|
||||
|
||||
|
|
|
|||
|
|
@ -319,7 +319,6 @@ private:
|
|||
bool triggerOnCC { false };
|
||||
absl::string_view defaultPath { "" };
|
||||
|
||||
int activeNotesInRange { -1 };
|
||||
int sequenceCounter { 0 };
|
||||
|
||||
std::uniform_real_distribution<float> volumeDistribution { -sfz::Default::ampRandom, sfz::Default::ampRandom };
|
||||
|
|
|
|||
|
|
@ -417,6 +417,8 @@ void sfz::Synth::noteOff(int delay, int noteNumber, uint8_t velocity [[maybe_unu
|
|||
ASSERT(noteNumber < 128);
|
||||
ASSERT(noteNumber >= 0);
|
||||
|
||||
midiState.noteOffEvent(noteNumber, velocity);
|
||||
|
||||
AtomicGuard callbackGuard { inCallback };
|
||||
if (!canEnterCallback)
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -152,10 +152,15 @@ TEST_CASE("Legato triggers", "Region triggers")
|
|||
region.parseOpcode({ "lokey", "40" });
|
||||
region.parseOpcode({ "hikey", "50" });
|
||||
region.parseOpcode({ "trigger", "first" });
|
||||
midiState.noteOnEvent(40, 64);
|
||||
REQUIRE(region.registerNoteOn(40, 64, 0.5f));
|
||||
midiState.noteOnEvent(41, 64);
|
||||
REQUIRE(!region.registerNoteOn(41, 64, 0.5f));
|
||||
midiState.noteOffEvent(40, 0);
|
||||
region.registerNoteOff(40, 0, 0.5f);
|
||||
midiState.noteOffEvent(41, 0);
|
||||
region.registerNoteOff(41, 0, 0.5f);
|
||||
midiState.noteOnEvent(42, 64);
|
||||
REQUIRE(region.registerNoteOn(42, 64, 0.5f));
|
||||
}
|
||||
|
||||
|
|
@ -164,10 +169,15 @@ TEST_CASE("Legato triggers", "Region triggers")
|
|||
region.parseOpcode({ "lokey", "40" });
|
||||
region.parseOpcode({ "hikey", "50" });
|
||||
region.parseOpcode({ "trigger", "legato" });
|
||||
midiState.noteOnEvent(40, 64);
|
||||
REQUIRE(!region.registerNoteOn(40, 64, 0.5f));
|
||||
midiState.noteOnEvent(41, 64);
|
||||
REQUIRE(region.registerNoteOn(41, 64, 0.5f));
|
||||
midiState.noteOffEvent(40, 64);
|
||||
region.registerNoteOff(40, 0, 0.5f);
|
||||
midiState.noteOffEvent(41, 64);
|
||||
region.registerNoteOff(41, 0, 0.5f);
|
||||
midiState.noteOnEvent(42, 64);
|
||||
REQUIRE(!region.registerNoteOn(42, 64, 0.5f));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue