From 7c37a18b7554080cef9bf5fe771f97e152bbc6ce Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Sat, 19 Sep 2020 22:36:17 +0200 Subject: [PATCH] Update MIDI buffer implementation to retain EventType --- libs/ardour/ardour/midi_buffer.h | 28 +++++++++++-------- libs/ardour/async_midi_port.cc | 4 +-- libs/ardour/luabindings.cc | 2 +- libs/ardour/midi_buffer.cc | 47 +++++++++++++++++++------------- libs/ardour/midi_ring_buffer.cc | 4 ++- 5 files changed, 51 insertions(+), 34 deletions(-) diff --git a/libs/ardour/ardour/midi_buffer.h b/libs/ardour/ardour/midi_buffer.h index 7e883e9ef3..1039da69f8 100644 --- a/libs/ardour/ardour/midi_buffer.h +++ b/libs/ardour/ardour/midi_buffer.h @@ -53,9 +53,9 @@ public: void skip_to (TimeType when); bool push_back(const Evoral::Event& event); - bool push_back(TimeType time, size_t size, const uint8_t* data); + bool push_back(TimeType time, size_t size, const uint8_t* data, Evoral::EventType event_type = Evoral::MIDI_EVENT); - uint8_t* reserve(TimeType time, size_t size); + uint8_t* reserve(TimeType time, Evoral::EventType event_type, size_t size); void resize(size_t); size_t size() const { return _size; } @@ -86,19 +86,21 @@ public: } inline EventType operator*() const { - uint8_t* ev_start = buffer->_data + offset + sizeof(TimeType); + uint8_t* ev_start = buffer->_data + offset + sizeof(TimeType) + sizeof (Evoral::EventType); int event_size = Evoral::midi_event_size(ev_start); assert(event_size >= 0); - return EventType(midi_parameter_type(*ev_start), + return EventType( + *((Evoral::EventType*)(buffer->_data + offset + sizeof(TimeType))), *((TimeType*)(buffer->_data + offset)), event_size, ev_start); } inline EventType operator*() { - uint8_t* ev_start = buffer->_data + offset + sizeof(TimeType); + uint8_t* ev_start = buffer->_data + offset + sizeof(TimeType) + sizeof (Evoral::EventType); int event_size = Evoral::midi_event_size(ev_start); assert(event_size >= 0); - return EventType(Evoral::MIDI_EVENT, + return EventType( + *(reinterpret_cast((uintptr_t)(buffer->_data + offset + sizeof(TimeType)))), *(reinterpret_cast((uintptr_t)(buffer->_data + offset))), event_size, ev_start); } @@ -107,11 +109,15 @@ public: return reinterpret_cast((uintptr_t)(buffer->_data + offset)); } + inline Evoral::EventType * event_type_ptr() { + return reinterpret_cast((uintptr_t)(buffer->_data + offset + sizeof(TimeType))); + } + inline iterator_base& operator++() { - uint8_t* ev_start = buffer->_data + offset + sizeof(TimeType); + uint8_t* ev_start = buffer->_data + offset + sizeof(TimeType) + sizeof (Evoral::EventType); int event_size = Evoral::midi_event_size(ev_start); assert(event_size >= 0); - offset += sizeof(TimeType) + event_size; + offset += sizeof(TimeType) + sizeof (Evoral::EventType) + event_size; return *this; } @@ -138,7 +144,7 @@ public: iterator erase(const iterator& i) { assert (i.buffer == this); - uint8_t* ev_start = _data + i.offset + sizeof (TimeType); + uint8_t* ev_start = _data + i.offset + sizeof (TimeType) + sizeof (Evoral::EventType); int event_size = Evoral::midi_event_size (ev_start); if (event_size < 0) { @@ -146,7 +152,7 @@ public: return end(); } - size_t total_data_deleted = sizeof(TimeType) + event_size; + size_t total_data_deleted = sizeof(TimeType) + sizeof (Evoral::EventType) + event_size; if (i.offset + total_data_deleted > _size) { _size = 0; @@ -182,7 +188,7 @@ private: friend class iterator_base< MidiBuffer, Evoral::Event >; friend class iterator_base< const MidiBuffer, const Evoral::Event >; - uint8_t* _data; ///< timestamp, event, timestamp, event, ... + uint8_t* _data; ///< [timestamp, event-type, event]* pframes_t _size; }; diff --git a/libs/ardour/async_midi_port.cc b/libs/ardour/async_midi_port.cc index 06a51279fe..75a1392cb5 100644 --- a/libs/ardour/async_midi_port.cc +++ b/libs/ardour/async_midi_port.cc @@ -83,7 +83,7 @@ AsyncMIDIPort::flush_output_fifo (MIDI::pframes_t nframes) assert (evp->buffer()); for (size_t n = 0; n < vec.len[0]; ++n, ++evp) { - if (mb.push_back (evp->time(), evp->size(), evp->buffer())) { + if (mb.push_back (evp->time(), evp->size(), evp->buffer(), evp->event_type ())) { written++; } } @@ -96,7 +96,7 @@ AsyncMIDIPort::flush_output_fifo (MIDI::pframes_t nframes) assert (evp->buffer()); for (size_t n = 0; n < vec.len[1]; ++n, ++evp) { - if (mb.push_back (evp->time(), evp->size(), evp->buffer())) { + if (mb.push_back (evp->time(), evp->size(), evp->buffer(), evp->event_type ())) { written++; } } diff --git a/libs/ardour/luabindings.cc b/libs/ardour/luabindings.cc index 41a4379022..595cf2ca0c 100644 --- a/libs/ardour/luabindings.cc +++ b/libs/ardour/luabindings.cc @@ -2731,7 +2731,7 @@ LuaBindings::dsp (lua_State* L) .addFunction ("resize", &MidiBuffer::resize) .addFunction ("copy", (void (MidiBuffer::*)(MidiBuffer const * const))&MidiBuffer::copy) .addFunction ("push_event", (bool (MidiBuffer::*)(const Evoral::Event&))&MidiBuffer::push_back) - .addFunction ("push_back", (bool (MidiBuffer::*)(samplepos_t, size_t, const uint8_t*))&MidiBuffer::push_back) + .addFunction ("push_back", (bool (MidiBuffer::*)(samplepos_t, size_t, const uint8_t*, Evoral::EventType))&MidiBuffer::push_back) // TODO iterators.. .addExtCFunction ("table", &luabridge::CFunc::listToTable, MidiBuffer>) .endClass() diff --git a/libs/ardour/midi_buffer.cc b/libs/ardour/midi_buffer.cc index b8cfdb15e3..8f4a7e5850 100644 --- a/libs/ardour/midi_buffer.cc +++ b/libs/ardour/midi_buffer.cc @@ -115,7 +115,7 @@ MidiBuffer::read_from (const Buffer& src, samplecnt_t nframes, sampleoffset_t ds const Evoral::Event ev(*i, false); if (ev.time() >= 0 && ev.time() < nframes) { - push_back (ev.time(), ev.size(), ev.buffer()); + push_back (ev.time(), ev.size(), ev.buffer(), ev.event_type ()); } else { cerr << "\t!!!! MIDI event @ " << ev.time() << " skipped, not within range 0 .. " << nframes << endl; PBD::stacktrace (cerr, 30); @@ -146,7 +146,7 @@ MidiBuffer::merge_from (const Buffer& src, samplecnt_t /*nframes*/, sampleoffset bool MidiBuffer::push_back(const Evoral::Event& ev) { - return push_back (ev.time(), ev.size(), ev.buffer()); + return push_back (ev.time(), ev.size(), ev.buffer(), ev.event_type ()); } @@ -158,9 +158,10 @@ MidiBuffer::push_back(const Evoral::Event& ev) * @return false if operation failed (not enough room) */ bool -MidiBuffer::push_back(TimeType time, size_t size, const uint8_t* data) +MidiBuffer::push_back(TimeType time, size_t size, const uint8_t* data, Evoral::EventType event_type) { const size_t stamp_size = sizeof(TimeType); + const size_t etype_size = sizeof(Evoral::EventType); #ifndef NDEBUG if (DEBUG_ENABLED(DEBUG::MidiIO)) { @@ -177,7 +178,7 @@ MidiBuffer::push_back(TimeType time, size_t size, const uint8_t* data) } #endif - if (_size + stamp_size + size >= _capacity) { + if (_size + stamp_size + etype_size + size >= _capacity) { return false; } @@ -187,9 +188,10 @@ MidiBuffer::push_back(TimeType time, size_t size, const uint8_t* data) uint8_t* const write_loc = _data + _size; *(reinterpret_cast((uintptr_t)write_loc)) = time; - memcpy(write_loc + stamp_size, data, size); + *(reinterpret_cast((uintptr_t)(write_loc + stamp_size))) = event_type; + memcpy(write_loc + stamp_size + etype_size, data, size); - _size += stamp_size + size; + _size += stamp_size + etype_size + size; _silent = false; return true; @@ -205,7 +207,9 @@ MidiBuffer::insert_event(const Evoral::Event& ev) } const size_t stamp_size = sizeof(TimeType); - const size_t bytes_to_merge = stamp_size + ev.size(); + const size_t etype_size = sizeof(Evoral::EventType); + + const size_t bytes_to_merge = stamp_size + etype_size + ev.size(); if (_size + bytes_to_merge >= _capacity) { cerr << string_compose ("MidiBuffer::push_back failed (buffer is full: size: %1 capacity %2 new bytes %3)", _size, _capacity, bytes_to_merge) << endl; @@ -243,7 +247,8 @@ MidiBuffer::insert_event(const Evoral::Event& ev) uint8_t* const write_loc = _data + insert_offset; *(reinterpret_cast((uintptr_t)write_loc)) = t; - memcpy(write_loc + stamp_size, ev.buffer(), ev.size()); + *(reinterpret_cast((uintptr_t)(write_loc + stamp_size))) = ev.event_type (); + memcpy(write_loc + stamp_size + etype_size, ev.buffer(), ev.size()); _size += bytes_to_merge; @@ -265,21 +270,23 @@ MidiBuffer::write(TimeType time, Evoral::EventType type, uint32_t size, const ui * location, or the buffer will be corrupted and very nasty things will happen. */ uint8_t* -MidiBuffer::reserve(TimeType time, size_t size) +MidiBuffer::reserve(TimeType time, Evoral::EventType event_type, size_t size) { const size_t stamp_size = sizeof(TimeType); - if (_size + stamp_size + size >= _capacity) { + const size_t etype_size = sizeof(Evoral::EventType); + if (_size + stamp_size + etype_size + size >= _capacity) { return 0; } - // write timestamp + // write timestamp and event-type uint8_t* write_loc = _data + _size; *(reinterpret_cast((uintptr_t)write_loc)) = time; + *(reinterpret_cast((uintptr_t)(write_loc + stamp_size))) = event_type; // move write_loc to begin of MIDI buffer data to write to - write_loc += stamp_size; + write_loc += stamp_size + etype_size; - _size += stamp_size + size; + _size += stamp_size + etype_size + size; _silent = false; return write_loc; @@ -422,6 +429,8 @@ MidiBuffer::second_simultaneous_midi_byte_is_first (uint8_t a, uint8_t b) bool MidiBuffer::merge_in_place (const MidiBuffer &other) { + const size_t header_size = sizeof(TimeType) + sizeof(Evoral::EventType); + if (other.size() && size()) { DEBUG_TRACE (DEBUG::MidiIO, string_compose ("merge in place, sizes %1/%2\n", size(), other.size())); } @@ -458,7 +467,7 @@ MidiBuffer::merge_in_place (const MidiBuffer &other) if (merge_offset == -1) { merge_offset = them.offset; } - bytes_to_merge += sizeof (TimeType) + (*them).size(); + bytes_to_merge += header_size + (*them).size(); ++them; } @@ -505,11 +514,11 @@ MidiBuffer::merge_in_place (const MidiBuffer &other) DEBUG_TRACE (DEBUG::MidiIO, string_compose ("simultaneous MIDI events discovered during merge, times %1/%2 status %3/%4\n", (*us).time(), (*them).time(), - (int) *(_data + us.offset + sizeof (TimeType)), - (int) *(other._data + them.offset + sizeof (TimeType)))); + (int) *(_data + us.offset + header_size), + (int) *(other._data + them.offset + header_size))); - uint8_t our_midi_status_byte = *(_data + us.offset + sizeof (TimeType)); - uint8_t their_midi_status_byte = *(other._data + them.offset + sizeof (TimeType)); + uint8_t our_midi_status_byte = *(_data + us.offset + header_size); + uint8_t their_midi_status_byte = *(other._data + them.offset + header_size); bool them_first = second_simultaneous_midi_byte_is_first (our_midi_status_byte, their_midi_status_byte); DEBUG_TRACE (DEBUG::MidiIO, string_compose ("other message came first ? %1\n", them_first)); @@ -519,7 +528,7 @@ MidiBuffer::merge_in_place (const MidiBuffer &other) ++us; } - bytes_to_merge = sizeof (TimeType) + (*them).size(); + bytes_to_merge = header_size + (*them).size(); /* move our remaining events later in the buffer by * enough to fit the one message we're going to merge diff --git a/libs/ardour/midi_ring_buffer.cc b/libs/ardour/midi_ring_buffer.cc index 3b811dfa58..381b78166d 100644 --- a/libs/ardour/midi_ring_buffer.cc +++ b/libs/ardour/midi_ring_buffer.cc @@ -48,6 +48,7 @@ MidiRingBuffer::read (MidiBuffer& dst, samplepos_t start, samplepos_t end, sa } T ev_time; + Evoral::EventType ev_type; uint32_t ev_size; size_t count = 0; const size_t prefix_size = sizeof(T) + sizeof(Evoral::EventType) + sizeof(uint32_t); @@ -62,6 +63,7 @@ MidiRingBuffer::read (MidiBuffer& dst, samplepos_t start, samplepos_t end, sa this->peek (peekbuf, prefix_size); ev_time = *(reinterpret_cast((uintptr_t)peekbuf)); + ev_type = *(reinterpret_cast((uintptr_t)(peekbuf + sizeof(T)))); ev_size = *(reinterpret_cast((uintptr_t)(peekbuf + sizeof(T) + sizeof (Evoral::EventType)))); if (this->read_space() < ev_size) { @@ -92,7 +94,7 @@ MidiRingBuffer::read (MidiBuffer& dst, samplepos_t start, samplepos_t end, sa /* lets see if we are going to be able to write this event into dst. */ - uint8_t* write_loc = dst.reserve (ev_time, ev_size); + uint8_t* write_loc = dst.reserve (ev_time, ev_type, ev_size); if (write_loc == 0) { if (stop_on_overflow_in_dst) { DEBUG_TRACE (DEBUG::MidiRingBuffer, string_compose ("MidiRingBuffer: overflow in destination MIDI buffer, stopped after %1 events\n", count));