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/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<samplepos_t>
{
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<samplepos_t>
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<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:
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)
*/

View File

@ -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;
}