From 4267d5b0d7943c2cff8eea35b4fb357dd6421e29 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Fri, 21 Jun 2024 22:15:45 -0600 Subject: [PATCH] MidiStateTracker: extend API to allow "diffs" between two MidiStateTrackers --- libs/ardour/ardour/midi_state_tracker.h | 3 +- libs/ardour/midi_state_tracker.cc | 53 +++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/libs/ardour/ardour/midi_state_tracker.h b/libs/ardour/ardour/midi_state_tracker.h index 984baf8aeb..15075d7b98 100644 --- a/libs/ardour/ardour/midi_state_tracker.h +++ b/libs/ardour/ardour/midi_state_tracker.h @@ -60,7 +60,7 @@ public: bool empty() const { return _on == 0; } 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; } @@ -89,6 +89,7 @@ class LIBARDOUR_API MidiStateTracker : public MidiNoteTracker void flush (MidiBuffer&, samplepos_t, bool reset); void resolve_state (Evoral::EventSink&, Evoral::EventList const&, samplepos_t time, bool reset = true); + void resolve_diff (MidiStateTracker const& other, Evoral::EventSink&, samplepos_t time, bool reset = true); private: uint8_t program[16]; diff --git a/libs/ardour/midi_state_tracker.cc b/libs/ardour/midi_state_tracker.cc index e72c48d1b8..b839c79845 100644 --- a/libs/ardour/midi_state_tracker.cc +++ b/libs/ardour/midi_state_tracker.cc @@ -514,3 +514,56 @@ MidiStateTracker::resolve_state (Evoral::EventSink& dst, Evoral::Ev } } } + +void +MidiStateTracker::resolve_diff (MidiStateTracker const & other, Evoral::EventSink& 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); + } + } +}