2 * Copyright (C) 2007-2016 David Robillard <d@drobilla.net>
3 * Copyright (C) 2007-2017 Paul Davis <paul@linuxaudiosystems.com>
4 * Copyright (C) 2008-2009 Hans Baier <hansfbaier@googlemail.com>
5 * Copyright (C) 2009-2012 Carl Hetherington <carl@carlh.net>
6 * Copyright (C) 2014-2016 Robin Gareus <robin@gareus.org>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 #include "pbd/malign.h"
26 #include "pbd/compose.h"
27 #include "pbd/debug.h"
28 #include "pbd/stacktrace.h"
30 #include "ardour/debug.h"
31 #include "ardour/midi_buffer.h"
32 #include "ardour/port.h"
35 using namespace ARDOUR;
38 // FIXME: mirroring for MIDI buffers?
39 MidiBuffer::MidiBuffer(size_t capacity)
40 : Buffer (DataType::MIDI)
50 MidiBuffer::~MidiBuffer()
52 cache_aligned_free(_data);
56 MidiBuffer::resize(size_t size)
58 if (_data && size < _capacity) {
68 cache_aligned_free (_data);
70 cache_aligned_malloc ((void**) &_data, size);
79 MidiBuffer::copy(const MidiBuffer& copy)
81 assert(_capacity >= copy._size);
83 memcpy(_data, copy._data, copy._size);
87 MidiBuffer::copy(MidiBuffer const * const copy)
89 assert(_capacity >= copy->size ());
90 _size = copy->size ();
91 memcpy(_data, copy->_data, _size);
95 /** Read events from @a src starting at time @a offset into the START of this buffer, for
96 * time duration @a nframes. Relative time, where 0 = start of buffer.
98 * Note that offset and nframes refer to sample time, NOT buffer offsets or event counts.
101 MidiBuffer::read_from (const Buffer& src, samplecnt_t nframes, sampleoffset_t dst_offset, sampleoffset_t /* src_offset*/)
103 assert (src.type() == DataType::MIDI);
104 assert (&src != this);
106 const MidiBuffer& msrc = (const MidiBuffer&) src;
108 assert (_capacity >= msrc.size());
110 if (dst_offset == 0) {
115 for (MidiBuffer::const_iterator i = msrc.begin(); i != msrc.end(); ++i) {
116 const Evoral::Event<TimeType> ev(*i, false);
118 if (dst_offset >= 0) {
119 /* Positive offset: shifting events from internal
120 buffer view of time (always relative to to start of
121 current possibly split cycle) to from global/port
122 view of time (always relative to start of process
125 Check it is within range of this (split) cycle, then shift.
127 if (ev.time() >= 0 && ev.time() < nframes) {
128 push_back (ev.time() + dst_offset, ev.size(), ev.buffer());
130 cerr << "\t!!!! MIDI event @ " << ev.time() << " skipped, not within range 0 .. " << nframes << ": ";
133 /* Negative offset: shifting events from global/port
134 view of time (always relative to start of process
135 cycle) back to internal buffer view of time (always
136 relative to to start of current possibly split
139 Shift first, then check it is within range of this
142 const samplepos_t evtime = ev.time() + dst_offset;
144 if (evtime >= 0 && evtime < nframes) {
145 push_back (evtime, ev.size(), ev.buffer());
147 cerr << "\t!!!! MIDI event @ " << evtime << " (based on " << ev.time() << " + " << dst_offset << ") skipped, not within range 0 .. " << nframes << ": ";
152 _silent = src.silent();
156 MidiBuffer::merge_from (const Buffer& src, samplecnt_t /*nframes*/, sampleoffset_t /*dst_offset*/, sampleoffset_t /*src_offset*/)
158 const MidiBuffer* mbuf = dynamic_cast<const MidiBuffer*>(&src);
160 assert (mbuf != this);
162 /* XXX use nframes, and possible offsets */
163 merge_in_place (*mbuf);
166 /** Push an event into the buffer.
168 * Note that the raw MIDI pointed to by ev will be COPIED and unmodified.
169 * That is, the caller still owns it, if it needs freeing it's Not My Problem(TM).
171 * @return false if operation failed (not enough room)
174 MidiBuffer::push_back(const Evoral::Event<TimeType>& ev)
176 return push_back (ev.time(), ev.size(), ev.buffer());
180 /** Push MIDI data into the buffer.
182 * Note that the raw MIDI pointed to by @param data will be COPIED and unmodified.
183 * That is, the caller still owns it, if it needs freeing it's Not My Problem(TM).
185 * @return false if operation failed (not enough room)
188 MidiBuffer::push_back(TimeType time, size_t size, const uint8_t* data)
190 const size_t stamp_size = sizeof(TimeType);
193 if (DEBUG_ENABLED(DEBUG::MidiIO)) {
195 DEBUG_STR_APPEND(a, string_compose ("midibuffer %1 push event @ %2 sz %3 ", this, time, size));
196 for (size_t i=0; i < size; ++i) {
197 DEBUG_STR_APPEND(a,hex);
198 DEBUG_STR_APPEND(a,"0x");
199 DEBUG_STR_APPEND(a,(int)data[i]);
200 DEBUG_STR_APPEND(a,' ');
202 DEBUG_STR_APPEND(a,'\n');
203 DEBUG_TRACE (DEBUG::MidiIO, DEBUG_STR(a).str());
207 if (_size + stamp_size + size >= _capacity) {
211 if (!Evoral::midi_event_is_valid(data, size)) {
215 uint8_t* const write_loc = _data + _size;
216 *(reinterpret_cast<TimeType*>((uintptr_t)write_loc)) = time;
217 memcpy(write_loc + stamp_size, data, size);
219 _size += stamp_size + size;
226 MidiBuffer::insert_event(const Evoral::Event<TimeType>& ev)
229 return push_back(ev);
232 const size_t stamp_size = sizeof(TimeType);
233 const size_t bytes_to_merge = stamp_size + ev.size();
235 if (_size + bytes_to_merge >= _capacity) {
236 cerr << "MidiBuffer::push_back failed (buffer is full)" << endl;
237 PBD::stacktrace (cerr, 20);
241 TimeType t = ev.time();
243 ssize_t insert_offset = -1;
244 for (MidiBuffer::iterator m = begin(); m != end(); ++m) {
245 if ((*m).time() < t) {
248 if ((*m).time() == t) {
249 const uint8_t our_midi_status_byte = *(_data + m.offset + sizeof (TimeType));
250 if (second_simultaneous_midi_byte_is_first (ev.type(), our_midi_status_byte)) {
254 insert_offset = m.offset;
257 if (insert_offset == -1) {
258 return push_back(ev);
261 // don't use memmove - it may use malloc(!)
262 // memmove (_data + insert_offset + bytes_to_merge, _data + insert_offset, _size - insert_offset);
263 for (ssize_t a = _size + bytes_to_merge - 1, b = _size - 1; b >= insert_offset; --b, --a) {
267 uint8_t* const write_loc = _data + insert_offset;
268 *(reinterpret_cast<TimeType*>((uintptr_t)write_loc)) = t;
269 memcpy(write_loc + stamp_size, ev.buffer(), ev.size());
271 _size += bytes_to_merge;
277 MidiBuffer::write(TimeType time, Evoral::EventType type, uint32_t size, const uint8_t* buf)
279 insert_event(Evoral::Event<TimeType>(type, time, size, const_cast<uint8_t*>(buf)));
283 /** Reserve space for a new event in the buffer.
285 * This call is for copying MIDI directly into the buffer, the data location
286 * (of sufficient size to write \a size bytes) is returned, or 0 on failure.
287 * This call MUST be immediately followed by a write to the returned data
288 * location, or the buffer will be corrupted and very nasty things will happen.
291 MidiBuffer::reserve(TimeType time, size_t size)
293 const size_t stamp_size = sizeof(TimeType);
294 if (_size + stamp_size + size >= _capacity) {
299 uint8_t* write_loc = _data + _size;
300 *(reinterpret_cast<TimeType*>((uintptr_t)write_loc)) = time;
302 // move write_loc to begin of MIDI buffer data to write to
303 write_loc += stamp_size;
305 _size += stamp_size + size;
313 MidiBuffer::silence (samplecnt_t /*nframes*/, samplecnt_t /*offset*/)
315 /* XXX iterate over existing events, find all in range given by offset & nframes,
324 MidiBuffer::second_simultaneous_midi_byte_is_first (uint8_t a, uint8_t b)
326 bool b_first = false;
328 /* two events at identical times. we need to determine
329 the order in which they should occur.
342 if ((a) >= 0xf0 || (b) >= 0xf0 || ((a & 0xf) != (b & 0xf))) {
344 /* if either message is not a channel message, or if the channels are
345 * different, we don't care about the type.
353 case MIDI_CMD_CONTROL:
357 case MIDI_CMD_PGM_CHANGE:
359 case MIDI_CMD_CONTROL:
361 case MIDI_CMD_PGM_CHANGE:
362 case MIDI_CMD_NOTE_OFF:
363 case MIDI_CMD_NOTE_ON:
364 case MIDI_CMD_NOTE_PRESSURE:
365 case MIDI_CMD_CHANNEL_PRESSURE:
366 case MIDI_CMD_BENDER:
371 case MIDI_CMD_NOTE_OFF:
373 case MIDI_CMD_CONTROL:
374 case MIDI_CMD_PGM_CHANGE:
376 case MIDI_CMD_NOTE_OFF:
377 case MIDI_CMD_NOTE_ON:
378 case MIDI_CMD_NOTE_PRESSURE:
379 case MIDI_CMD_CHANNEL_PRESSURE:
380 case MIDI_CMD_BENDER:
385 case MIDI_CMD_NOTE_ON:
387 case MIDI_CMD_CONTROL:
388 case MIDI_CMD_PGM_CHANGE:
389 case MIDI_CMD_NOTE_OFF:
391 case MIDI_CMD_NOTE_ON:
392 case MIDI_CMD_NOTE_PRESSURE:
393 case MIDI_CMD_CHANNEL_PRESSURE:
394 case MIDI_CMD_BENDER:
398 case MIDI_CMD_NOTE_PRESSURE:
400 case MIDI_CMD_CONTROL:
401 case MIDI_CMD_PGM_CHANGE:
402 case MIDI_CMD_NOTE_OFF:
403 case MIDI_CMD_NOTE_ON:
405 case MIDI_CMD_NOTE_PRESSURE:
406 case MIDI_CMD_CHANNEL_PRESSURE:
407 case MIDI_CMD_BENDER:
412 case MIDI_CMD_CHANNEL_PRESSURE:
414 case MIDI_CMD_CONTROL:
415 case MIDI_CMD_PGM_CHANGE:
416 case MIDI_CMD_NOTE_OFF:
417 case MIDI_CMD_NOTE_ON:
418 case MIDI_CMD_NOTE_PRESSURE:
420 case MIDI_CMD_CHANNEL_PRESSURE:
421 case MIDI_CMD_BENDER:
425 case MIDI_CMD_BENDER:
427 case MIDI_CMD_CONTROL:
428 case MIDI_CMD_PGM_CHANGE:
429 case MIDI_CMD_NOTE_OFF:
430 case MIDI_CMD_NOTE_ON:
431 case MIDI_CMD_NOTE_PRESSURE:
432 case MIDI_CMD_CHANNEL_PRESSURE:
434 case MIDI_CMD_BENDER:
444 /** Merge \a other into this buffer. Realtime safe. */
446 MidiBuffer::merge_in_place (const MidiBuffer &other)
448 if (other.size() && size()) {
449 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("merge in place, sizes %1/%2\n", size(), other.size()));
452 if (other.size() == 0) {
461 if (size() + other.size() > _capacity) {
465 const_iterator them = other.begin();
466 iterator us = begin();
468 while (them != other.end()) {
470 size_t bytes_to_merge;
471 ssize_t merge_offset;
473 /* gather up total size of events that are earlier than
474 the event referenced by "us"
480 while (them != other.end() && (*them).time() < (*us).time()) {
481 if (merge_offset == -1) {
482 merge_offset = them.offset;
484 bytes_to_merge += sizeof (TimeType) + (*them).size();
488 /* "them" now points to either:
490 * 1) an event that has the same or later timestamp than the
491 * event pointed to by "us"
495 * 2) the end of the "other" buffer
497 * if "sz" is non-zero, there is data to be merged from "other"
498 * into this buffer before we do anything else, corresponding
499 * to the events from "other" that we skipped while advancing
503 if (bytes_to_merge) {
504 assert(merge_offset >= 0);
506 memmove (_data + us.offset + bytes_to_merge, _data + us.offset, _size - us.offset);
508 _size += bytes_to_merge;
509 assert (_size <= _capacity);
510 /* insert new stuff */
511 memcpy (_data + us.offset, other._data + merge_offset, bytes_to_merge);
512 /* update iterator to our own events. this is a miserable hack */
513 us.offset += bytes_to_merge;
516 /* if we're at the end of the other buffer, we're done */
518 if (them == other.end()) {
522 /* if we have two messages messages with the same timestamp. we
523 * must order them correctly.
526 if ((*us).time() == (*them).time()) {
528 DEBUG_TRACE (DEBUG::MidiIO,
529 string_compose ("simultaneous MIDI events discovered during merge, times %1/%2 status %3/%4\n",
530 (*us).time(), (*them).time(),
531 (int) *(_data + us.offset + sizeof (TimeType)),
532 (int) *(other._data + them.offset + sizeof (TimeType))));
534 uint8_t our_midi_status_byte = *(_data + us.offset + sizeof (TimeType));
535 uint8_t their_midi_status_byte = *(other._data + them.offset + sizeof (TimeType));
536 bool them_first = second_simultaneous_midi_byte_is_first (our_midi_status_byte, their_midi_status_byte);
538 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("other message came first ? %1\n", them_first));
541 /* skip past our own event */
545 bytes_to_merge = sizeof (TimeType) + (*them).size();
547 /* move our remaining events later in the buffer by
548 * enough to fit the one message we're going to merge
551 memmove (_data + us.offset + bytes_to_merge, _data + us.offset, _size - us.offset);
553 _size += bytes_to_merge;
554 assert(_size <= _capacity);
555 /* insert new stuff */
556 memcpy (_data + us.offset, other._data + them.offset, bytes_to_merge);
557 /* update iterator to our own events. this is a miserable hack */
558 us.offset += bytes_to_merge;
559 /* 'us' is now an iterator to the event right after the
560 new ones that we merged
563 /* need to skip the event pointed to by 'us'
564 since its at the same time as 'them'
565 (still), and we'll enter
573 /* we merged one event from the other buffer, so
574 * advance the iterator there.
581 /* advance past our own events to get to the correct insertion
582 point for the next event(s) from "other"
585 while (us != end() && (*us).time() <= (*them).time()) {
590 /* check to see if we reached the end of this buffer while
591 * looking for the insertion point.
596 /* just append the rest of other and we're done*/
598 memcpy (_data + us.offset, other._data + them.offset, other._size - them.offset);
599 _size += other._size - them.offset;
600 assert(_size <= _capacity);