From 2b754568a00cdc88e15cb57edbfb335891fcb775 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Sun, 24 Oct 2021 09:26:35 -0600 Subject: [PATCH] changes/extensions to RTMidiBuffer API to make it more suitable for slots/triggers --- libs/ardour/ardour/rt_midibuffer.h | 36 +++++++++++++++++++++++++---- libs/ardour/rt_midibuffer.cc | 37 ++++++++++++++++++++++-------- 2 files changed, 58 insertions(+), 15 deletions(-) diff --git a/libs/ardour/ardour/rt_midibuffer.h b/libs/ardour/ardour/rt_midibuffer.h index 0f379b2dce..fcc6e9b1ab 100644 --- a/libs/ardour/ardour/rt_midibuffer.h +++ b/libs/ardour/ardour/rt_midibuffer.h @@ -29,6 +29,8 @@ #include "evoral/Event.h" #include "evoral/EventSink.h" +#include "evoral/midi_util.h" + #include "ardour/types.h" namespace ARDOUR { @@ -39,6 +41,12 @@ class MidiStateTracker; /** */ class LIBARDOUR_API RTMidiBuffer : public Evoral::EventSink { + private: + struct Blob { + uint32_t size; + uint8_t data[0]; + }; + public: typedef samplepos_t TimeType; @@ -48,6 +56,9 @@ class LIBARDOUR_API RTMidiBuffer : public Evoral::EventSink void clear(); void resize(size_t); size_t size() const { return _size; } + bool empty() const { return _size == 0; } + + samplecnt_t span() const; uint32_t write (TimeType time, Evoral::EventType type, uint32_t size, const uint8_t* buf); uint32_t read (MidiBuffer& dst, samplepos_t start, samplepos_t end, MidiStateTracker& tracker, samplecnt_t offset = 0); @@ -64,14 +75,29 @@ class LIBARDOUR_API RTMidiBuffer : public Evoral::EventSink }; }; + Item const & operator[](size_t n) const { + if (n >= _size) { + throw std::exception (); + } + return _data[n]; + } + + uint8_t const * bytes (Item const & item, uint32_t& size) { + if (item.bytes[0]) { + size = Evoral::midi_event_size (item.bytes[1]); + return item.bytes; + } else { + uint32_t offset = item.offset & ~(1<<(CHAR_BIT-1)); + Blob* blob = reinterpret_cast (&_pool[offset]); + + size = blob->size; + return blob->data; + } + } + private: friend struct WriteProtectRender; - struct Blob { - uint32_t size; - uint8_t data[0]; - }; - /* The main store. Holds Items (timestamp+up to 3 bytes of data OR * offset into secondary storage below) */ diff --git a/libs/ardour/rt_midibuffer.cc b/libs/ardour/rt_midibuffer.cc index 2e92c44647..85f5f4c7cd 100644 --- a/libs/ardour/rt_midibuffer.cc +++ b/libs/ardour/rt_midibuffer.cc @@ -24,8 +24,6 @@ #include "pbd/error.h" #include "pbd/debug.h" -#include "evoral/midi_util.h" - #include "ardour/debug.h" #include "ardour/midi_buffer.h" #include "ardour/midi_state_tracker.h" @@ -194,8 +192,12 @@ RTMidiBuffer::write (TimeType time, Evoral::EventType /*type*/, uint32_t size, c { /* This buffer stores only MIDI, we don't care about the value of "type" */ - if (_size == _capacity) { - resize (_capacity + 1024); // XXX 1024 is completely arbitrary + if (_size + size >= _capacity) { + if (size > 1024) { + resize (_capacity + size + 1024); // XXX 1024 is completely arbitrary + } else { + resize (_capacity + 1024); // XXX 1024 is completely arbitrary + } } _data[_size].timestamp = time; @@ -232,13 +234,15 @@ RTMidiBuffer::write (TimeType time, Evoral::EventType /*type*/, uint32_t size, c return size; } -/* These (non-matching) comparison arguments weren't supported prior to C99 !!! +/* requires C++20 to be usable */ +/* static bool -item_timestamp_earlier (ARDOUR::RTMidiBuffer::Item const & item, samplepos_t time) +item_timestamp_earlier (ARDOUR::RTMidiBuffer::Item const & item, samplepos_t const & time) { return item.timestamp < time; -}*/ +} +*/ static bool @@ -260,9 +264,8 @@ RTMidiBuffer::read (MidiBuffer& dst, samplepos_t start, samplepos_t end, MidiSta Item foo; Item* iend; Item* item; - - uint32_t count = 0; foo.timestamp = start; + uint32_t count = 0; if (start < end) { iend = _data+_size; @@ -271,7 +274,7 @@ RTMidiBuffer::read (MidiBuffer& dst, samplepos_t start, samplepos_t end, MidiSta } else { iend = _data; --iend; /* yes, this is technically "illegal" but we will never indirect */ - Item* uend = _data+_size; + Item* uend = _data + _size; item = upper_bound (_data, uend, foo, item_item_earlier); if (item == uend) { @@ -412,3 +415,17 @@ RTMidiBuffer::clear () /* rendering new data .. it will not be reversed */ _reversed = false; } + +samplecnt_t +RTMidiBuffer::span() const +{ + if (_size == 0 || _size == 1) { + return 0; + } + + const Item* last = &_data[_size-1]; + const Item* first = &_data[0]; + + return last->timestamp - first->timestamp; +} +