13
0

changes/extensions to RTMidiBuffer API to make it more suitable for slots/triggers

This commit is contained in:
Paul Davis 2021-10-24 09:26:35 -06:00
parent 65f85dfdfe
commit 2b754568a0
2 changed files with 58 additions and 15 deletions

View File

@ -29,6 +29,8 @@
#include "evoral/Event.h" #include "evoral/Event.h"
#include "evoral/EventSink.h" #include "evoral/EventSink.h"
#include "evoral/midi_util.h"
#include "ardour/types.h" #include "ardour/types.h"
namespace ARDOUR { namespace ARDOUR {
@ -39,6 +41,12 @@ class MidiStateTracker;
/** */ /** */
class LIBARDOUR_API RTMidiBuffer : public Evoral::EventSink<samplepos_t> class LIBARDOUR_API RTMidiBuffer : public Evoral::EventSink<samplepos_t>
{ {
private:
struct Blob {
uint32_t size;
uint8_t data[0];
};
public: public:
typedef samplepos_t TimeType; typedef samplepos_t TimeType;
@ -48,6 +56,9 @@ class LIBARDOUR_API RTMidiBuffer : public Evoral::EventSink<samplepos_t>
void clear(); void clear();
void resize(size_t); void resize(size_t);
size_t size() const { return _size; } 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 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); 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<samplepos_t>
}; };
}; };
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<Blob*> (&_pool[offset]);
size = blob->size;
return blob->data;
}
}
private: private:
friend struct WriteProtectRender; 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 /* The main store. Holds Items (timestamp+up to 3 bytes of data OR
* offset into secondary storage below) * offset into secondary storage below)
*/ */

View File

@ -24,8 +24,6 @@
#include "pbd/error.h" #include "pbd/error.h"
#include "pbd/debug.h" #include "pbd/debug.h"
#include "evoral/midi_util.h"
#include "ardour/debug.h" #include "ardour/debug.h"
#include "ardour/midi_buffer.h" #include "ardour/midi_buffer.h"
#include "ardour/midi_state_tracker.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" */ /* This buffer stores only MIDI, we don't care about the value of "type" */
if (_size == _capacity) { if (_size + size >= _capacity) {
resize (_capacity + 1024); // XXX 1024 is completely arbitrary 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; _data[_size].timestamp = time;
@ -232,13 +234,15 @@ RTMidiBuffer::write (TimeType time, Evoral::EventType /*type*/, uint32_t size, c
return size; return size;
} }
/* These (non-matching) comparison arguments weren't supported prior to C99 !!! /* requires C++20 to be usable */
/*
static static
bool 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; return item.timestamp < time;
}*/ }
*/
static static
bool bool
@ -260,9 +264,8 @@ RTMidiBuffer::read (MidiBuffer& dst, samplepos_t start, samplepos_t end, MidiSta
Item foo; Item foo;
Item* iend; Item* iend;
Item* item; Item* item;
uint32_t count = 0;
foo.timestamp = start; foo.timestamp = start;
uint32_t count = 0;
if (start < end) { if (start < end) {
iend = _data+_size; iend = _data+_size;
@ -271,7 +274,7 @@ RTMidiBuffer::read (MidiBuffer& dst, samplepos_t start, samplepos_t end, MidiSta
} else { } else {
iend = _data; iend = _data;
--iend; /* yes, this is technically "illegal" but we will never indirect */ --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); item = upper_bound (_data, uend, foo, item_item_earlier);
if (item == uend) { if (item == uend) {
@ -412,3 +415,17 @@ RTMidiBuffer::clear ()
/* rendering new data .. it will not be reversed */ /* rendering new data .. it will not be reversed */
_reversed = false; _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;
}