13
0

MidiStateTracker: extend API to allow "diffs" between two MidiStateTrackers

This commit is contained in:
Paul Davis 2024-06-21 22:15:45 -06:00
parent 4bbdbc6d13
commit 4267d5b0d7
2 changed files with 55 additions and 1 deletions

View File

@ -60,7 +60,7 @@ public:
bool empty() const { return _on == 0; } bool empty() const { return _on == 0; }
uint16_t on() const { return _on; } uint16_t on() const { return _on; }
bool active (uint8_t note, uint8_t channel) { bool active (uint8_t note, uint8_t channel) const {
return _active_notes[(channel*128)+note] > 0; return _active_notes[(channel*128)+note] > 0;
} }
@ -89,6 +89,7 @@ class LIBARDOUR_API MidiStateTracker : public MidiNoteTracker
void flush (MidiBuffer&, samplepos_t, bool reset); void flush (MidiBuffer&, samplepos_t, bool reset);
void resolve_state (Evoral::EventSink<samplepos_t>&, Evoral::EventList<samplepos_t> const&, samplepos_t time, bool reset = true); void resolve_state (Evoral::EventSink<samplepos_t>&, Evoral::EventList<samplepos_t> const&, samplepos_t time, bool reset = true);
void resolve_diff (MidiStateTracker const& other, Evoral::EventSink<samplepos_t>&, samplepos_t time, bool reset = true);
private: private:
uint8_t program[16]; uint8_t program[16];

View File

@ -514,3 +514,56 @@ MidiStateTracker::resolve_state (Evoral::EventSink<samplepos_t>& dst, Evoral::Ev
} }
} }
} }
void
MidiStateTracker::resolve_diff (MidiStateTracker const & other, Evoral::EventSink<samplepos_t>& dst, samplepos_t time, bool reset)
{
/* This fills @param dst with the messages required to get the MIDI
* receiver's state (assumed to match ours) into the condition
* indicated by @param other
*/
uint8_t buf[3];
for (int channel = 0; channel < 16; ++channel) {
for (int n = 0; n < 128; ++n) {
bool on;
if ((on = active (n, channel)) != other.active (n, channel)) {
buf[0] = (on ? MIDI_CMD_NOTE_OFF : MIDI_CMD_NOTE_ON) | channel;
buf[1] = n;
buf[2] = 64; /* not good, needs nuance */
dst.write (time, Evoral::MIDI_EVENT, 3, buf);
}
if (control[channel][n] != other.control[channel][n]) {
buf[0] = MIDI_CMD_CONTROL | channel;
buf[1] = n;
buf[2] = control[channel][n];
dst.write (time, Evoral::MIDI_EVENT, 3, buf);
}
}
if (program[channel] != other.program[channel]) {
buf[0] = MIDI_CMD_PGM_CHANGE | channel;
buf[1] = other.program[channel];
dst.write (time, Evoral::MIDI_EVENT, 2, buf);
}
if (pressure[channel] != other.pressure[channel]) {
buf[0] = MIDI_CMD_CHANNEL_PRESSURE | channel;
buf[1] = other.pressure[channel];;
dst.write (0, Evoral::MIDI_EVENT, 2, buf);
}
if (bender[channel] != other.bender[channel]) {
buf[0] = MIDI_CMD_BENDER | channel;
buf[1] = other.bender[channel];
dst.write (0, Evoral::MIDI_EVENT, 2, buf);
}
}
}