prepare midi buffer API for midi-delaylines
authorRobin Gareus <robin@gareus.org>
Wed, 11 Jun 2014 10:59:08 +0000 (12:59 +0200)
committerRobin Gareus <robin@gareus.org>
Wed, 11 Jun 2014 14:27:23 +0000 (16:27 +0200)
libs/ardour/ardour/midi_buffer.h
libs/ardour/midi_buffer.cc

index f1f8d678b979011321feb4a5437882b80dc6fed3..b6966faa0650e54f620412de5d56a4f5ec3ad053 100644 (file)
@@ -45,12 +45,14 @@ public:
 
        bool     push_back(const Evoral::MIDIEvent<TimeType>& event);
        bool     push_back(TimeType time, size_t size, const uint8_t* data);
+
        uint8_t* reserve(TimeType time, size_t size);
 
        void resize(size_t);
        size_t size() const { return _size; }
        bool empty() const { return _size == 0; }
 
+       bool insert_event(const Evoral::MIDIEvent<TimeType>& event);
        bool merge_in_place(const MidiBuffer &other);
 
        template<typename BufferType, typename EventType>
@@ -86,6 +88,10 @@ public:
                                        event_size, ev_start);
                }
 
+               inline TimeType * timeptr() {
+                       return ((TimeType*)(buffer->_data + offset));
+               }
+
                inline iterator_base<BufferType, EventType>& operator++() {
                        uint8_t* ev_start = buffer->_data + offset + sizeof(TimeType);
                        int event_size = Evoral::midi_event_size(ev_start);
index 1a6cb7fa2612d4fc461d8a3b28c88bce2b10728c..4715be928c18d39c88e68225da959fbbe8527bca 100644 (file)
@@ -199,6 +199,57 @@ MidiBuffer::push_back(TimeType time, size_t size, const uint8_t* data)
        return true;
 }
 
+bool
+MidiBuffer::insert_event(const Evoral::MIDIEvent<TimeType>& ev)
+{
+       if (size() == 0) {
+               return push_back(ev);
+       }
+
+       const size_t stamp_size = sizeof(TimeType);
+       const size_t bytes_to_merge = stamp_size + ev.size();
+
+       if (_size + bytes_to_merge >= _capacity) {
+               cerr << "MidiBuffer::push_back failed (buffer is full)" << endl;
+               PBD::stacktrace (cerr, 20);
+               return false;
+       }
+
+       TimeType t = ev.time();
+
+       ssize_t insert_offset = -1;
+       for (MidiBuffer::iterator m = begin(); m != end(); ++m) {
+               if ((*m).time() < t) {
+                       continue;
+               }
+               if ((*m).time() == t) {
+                       const uint8_t our_midi_status_byte = *(_data + m.offset + sizeof (TimeType));
+                       if (second_simultaneous_midi_byte_is_first (ev.type(), our_midi_status_byte)) {
+                               continue;
+                       }
+               }
+               insert_offset = m.offset;
+               break;
+       }
+       if (insert_offset == -1) {
+               return push_back(ev);
+       }
+
+       // don't use memmove - it may use malloc(!)
+       // memmove (_data + insert_offset + bytes_to_merge, _data + insert_offset, _size - insert_offset);
+       for (ssize_t a = _size + bytes_to_merge - 1, b = _size - 1; b >= insert_offset; --b, --a) {
+               _data[a] = _data[b];
+       }
+
+       uint8_t* const write_loc = _data + insert_offset;
+       *((TimeType*)write_loc) = t;
+       memcpy(write_loc + stamp_size, ev.buffer(), ev.size());
+
+       _size += bytes_to_merge;
+
+       return true;
+}
+
 /** Reserve space for a new event in the buffer.
  *
  * This call is for copying MIDI directly into the buffer, the data location