Remove ambiguous API implementation
[ardour.git] / libs / ardour / midi_buffer.cc
1 /*
2     Copyright (C) 2006-2007 Paul Davis
3     Author: David Robillard
4
5     This program is free software; you can redistribute it and/or modify it
6     under the terms of the GNU General Public License as published by the Free
7     Software Foundation; either version 2 of the License, or (at your option)
8     any later version.
9
10     This program is distributed in the hope that it will be useful, but WITHOUT
11     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13     for more details.
14
15     You should have received a copy of the GNU General Public License along
16     with this program; if not, write to the Free Software Foundation, Inc.,
17     675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20 #include <iostream>
21
22 #include "pbd/malign.h"
23 #include "pbd/compose.h"
24 #include "pbd/debug.h"
25 #include "pbd/stacktrace.h"
26
27 #include "ardour/debug.h"
28 #include "ardour/midi_buffer.h"
29 #include "ardour/port.h"
30
31 using namespace std;
32 using namespace ARDOUR;
33 using namespace PBD;
34
35 // FIXME: mirroring for MIDI buffers?
36 MidiBuffer::MidiBuffer(size_t capacity)
37         : Buffer (DataType::MIDI)
38         , _data (0)
39         , _size (0)
40 {
41         if (capacity) {
42                 resize (capacity);
43                 silence (capacity);
44         }
45 }
46
47 MidiBuffer::~MidiBuffer()
48 {
49         cache_aligned_free(_data);
50 }
51
52 void
53 MidiBuffer::resize(size_t size)
54 {
55         if (_data && size < _capacity) {
56
57                 if (_size < size) {
58                         /* truncate */
59                         _size = size;
60                 }
61
62                 return;
63         }
64
65         cache_aligned_free (_data);
66
67         cache_aligned_malloc ((void**) &_data, size);
68
69         _size = 0;
70         _capacity = size;
71
72         assert(_data);
73 }
74
75 void
76 MidiBuffer::copy(const MidiBuffer& copy)
77 {
78         assert(_capacity >= copy._size);
79         _size = copy._size;
80         memcpy(_data, copy._data, copy._size);
81 }
82
83 void
84 MidiBuffer::copy(MidiBuffer const * const copy)
85 {
86         assert(_capacity >= copy->size ());
87         _size = copy->size ();
88         memcpy(_data, copy->_data, _size);
89 }
90
91
92 /** Read events from @a src starting at time @a offset into the START of this buffer, for
93  * time duration @a nframes.  Relative time, where 0 = start of buffer.
94  *
95  * Note that offset and nframes refer to sample time, NOT buffer offsets or event counts.
96  */
97 void
98 MidiBuffer::read_from (const Buffer& src, samplecnt_t nframes, sampleoffset_t dst_offset, sampleoffset_t /* src_offset*/)
99 {
100         assert (src.type() == DataType::MIDI);
101         assert (&src != this);
102
103         const MidiBuffer& msrc = (const MidiBuffer&) src;
104
105         assert (_capacity >= msrc.size());
106
107         if (dst_offset == 0) {
108                 clear ();
109                 assert (_size == 0);
110         }
111
112         for (MidiBuffer::const_iterator i = msrc.begin(); i != msrc.end(); ++i) {
113                 const Evoral::Event<TimeType> ev(*i, false);
114
115                 if (dst_offset >= 0) {
116                         /* Positive offset: shifting events from internal
117                            buffer view of time (always relative to to start of
118                            current possibly split cycle) to from global/port
119                            view of time (always relative to start of process
120                            cycle).
121
122                            Check it is within range of this (split) cycle, then shift.
123                         */
124                         if (ev.time() >= 0 && ev.time() < nframes) {
125                                 push_back (ev.time() + dst_offset, ev.size(), ev.buffer());
126                         } else {
127                                 cerr << "\t!!!! MIDI event @ " <<  ev.time() << " skipped, not within range 0 .. " << nframes << ": ";
128                         }
129                 } else {
130                         /* Negative offset: shifting events from global/port
131                            view of time (always relative to start of process
132                            cycle) back to internal buffer view of time (always
133                            relative to to start of current possibly split
134                            cycle.
135
136                            Shift first, then check it is within range of this
137                            (split) cycle.
138                         */
139                         const samplepos_t evtime = ev.time() + dst_offset;
140
141                         if (evtime >= 0 && evtime < nframes) {
142                                 push_back (evtime, ev.size(), ev.buffer());
143                         } else {
144                                 cerr << "\t!!!! MIDI event @ " <<  evtime << " (based on " << ev.time() << " + " << dst_offset << ") skipped, not within range 0 .. " << nframes << ": ";
145                         }
146                 }
147         }
148
149         _silent = src.silent();
150 }
151
152 void
153 MidiBuffer::merge_from (const Buffer& src, samplecnt_t /*nframes*/, sampleoffset_t /*dst_offset*/, sampleoffset_t /*src_offset*/)
154 {
155         const MidiBuffer* mbuf = dynamic_cast<const MidiBuffer*>(&src);
156         assert (mbuf);
157         assert (mbuf != this);
158
159         /* XXX use nframes, and possible offsets */
160         merge_in_place (*mbuf);
161 }
162
163 /** Push an event into the buffer.
164  *
165  * Note that the raw MIDI pointed to by ev will be COPIED and unmodified.
166  * That is, the caller still owns it, if it needs freeing it's Not My Problem(TM).
167  * Realtime safe.
168  * @return false if operation failed (not enough room)
169  */
170 bool
171 MidiBuffer::push_back(const Evoral::Event<TimeType>& ev)
172 {
173         return push_back (ev.time(), ev.size(), ev.buffer());
174 }
175
176
177 /** Push MIDI data into the buffer.
178  *
179  * Note that the raw MIDI pointed to by @param data will be COPIED and unmodified.
180  * That is, the caller still owns it, if it needs freeing it's Not My Problem(TM).
181  * Realtime safe.
182  * @return false if operation failed (not enough room)
183  */
184 bool
185 MidiBuffer::push_back(TimeType time, size_t size, const uint8_t* data)
186 {
187         const size_t stamp_size = sizeof(TimeType);
188
189 #ifndef NDEBUG
190         if (DEBUG_ENABLED(DEBUG::MidiIO)) {
191                 DEBUG_STR_DECL(a);
192                 DEBUG_STR_APPEND(a, string_compose ("midibuffer %1 push event @ %2 sz %3 ", this, time, size));
193                 for (size_t i=0; i < size; ++i) {
194                         DEBUG_STR_APPEND(a,hex);
195                         DEBUG_STR_APPEND(a,"0x");
196                         DEBUG_STR_APPEND(a,(int)data[i]);
197                         DEBUG_STR_APPEND(a,' ');
198                 }
199                 DEBUG_STR_APPEND(a,'\n');
200                 DEBUG_TRACE (DEBUG::MidiIO, DEBUG_STR(a).str());
201         }
202 #endif
203
204         if (_size + stamp_size + size >= _capacity) {
205                 return false;
206         }
207
208         if (!Evoral::midi_event_is_valid(data, size)) {
209                 return false;
210         }
211
212         uint8_t* const write_loc = _data + _size;
213         *(reinterpret_cast<TimeType*>((uintptr_t)write_loc)) = time;
214         memcpy(write_loc + stamp_size, data, size);
215
216         _size += stamp_size + size;
217         _silent = false;
218
219         return true;
220 }
221
222 bool
223 MidiBuffer::insert_event(const Evoral::Event<TimeType>& ev)
224 {
225         if (size() == 0) {
226                 return push_back(ev);
227         }
228
229         const size_t stamp_size = sizeof(TimeType);
230         const size_t bytes_to_merge = stamp_size + ev.size();
231
232         if (_size + bytes_to_merge >= _capacity) {
233                 cerr << "MidiBuffer::push_back failed (buffer is full)" << endl;
234                 PBD::stacktrace (cerr, 20);
235                 return false;
236         }
237
238         TimeType t = ev.time();
239
240         ssize_t insert_offset = -1;
241         for (MidiBuffer::iterator m = begin(); m != end(); ++m) {
242                 if ((*m).time() < t) {
243                         continue;
244                 }
245                 if ((*m).time() == t) {
246                         const uint8_t our_midi_status_byte = *(_data + m.offset + sizeof (TimeType));
247                         if (second_simultaneous_midi_byte_is_first (ev.type(), our_midi_status_byte)) {
248                                 continue;
249                         }
250                 }
251                 insert_offset = m.offset;
252                 break;
253         }
254         if (insert_offset == -1) {
255                 return push_back(ev);
256         }
257
258         // don't use memmove - it may use malloc(!)
259         // memmove (_data + insert_offset + bytes_to_merge, _data + insert_offset, _size - insert_offset);
260         for (ssize_t a = _size + bytes_to_merge - 1, b = _size - 1; b >= insert_offset; --b, --a) {
261                 _data[a] = _data[b];
262         }
263
264         uint8_t* const write_loc = _data + insert_offset;
265         *(reinterpret_cast<TimeType*>((uintptr_t)write_loc)) = t;
266         memcpy(write_loc + stamp_size, ev.buffer(), ev.size());
267
268         _size += bytes_to_merge;
269
270         return true;
271 }
272
273 uint32_t
274 MidiBuffer::write(TimeType time, Evoral::EventType type, uint32_t size, const uint8_t* buf)
275 {
276         insert_event(Evoral::Event<TimeType>(type, time, size, const_cast<uint8_t*>(buf)));
277         return size;
278 }
279
280 /** Reserve space for a new event in the buffer.
281  *
282  * This call is for copying MIDI directly into the buffer, the data location
283  * (of sufficient size to write \a size bytes) is returned, or 0 on failure.
284  * This call MUST be immediately followed by a write to the returned data
285  * location, or the buffer will be corrupted and very nasty things will happen.
286  */
287 uint8_t*
288 MidiBuffer::reserve(TimeType time, size_t size)
289 {
290         const size_t stamp_size = sizeof(TimeType);
291         if (_size + stamp_size + size >= _capacity) {
292                 return 0;
293         }
294
295         // write timestamp
296         uint8_t* write_loc = _data + _size;
297         *(reinterpret_cast<TimeType*>((uintptr_t)write_loc)) = time;
298
299         // move write_loc to begin of MIDI buffer data to write to
300         write_loc += stamp_size;
301
302         _size += stamp_size + size;
303         _silent = false;
304
305         return write_loc;
306 }
307
308
309 void
310 MidiBuffer::silence (samplecnt_t /*nframes*/, samplecnt_t /*offset*/)
311 {
312         /* XXX iterate over existing events, find all in range given by offset & nframes,
313            and delete them.
314         */
315
316         _size = 0;
317         _silent = true;
318 }
319
320 bool
321 MidiBuffer::second_simultaneous_midi_byte_is_first (uint8_t a, uint8_t b)
322 {
323         bool b_first = false;
324
325         /* two events at identical times. we need to determine
326            the order in which they should occur.
327
328            the rule is:
329
330            Controller messages
331            Program Change
332            Note Off
333            Note On
334            Note Pressure
335            Channel Pressure
336            Pitch Bend
337         */
338
339         if ((a) >= 0xf0 || (b) >= 0xf0 || ((a & 0xf) != (b & 0xf))) {
340
341                 /* if either message is not a channel message, or if the channels are
342                  * different, we don't care about the type.
343                  */
344
345                 b_first = true;
346
347         } else {
348
349                 switch (b & 0xf0) {
350                 case MIDI_CMD_CONTROL:
351                         b_first = true;
352                         break;
353
354                 case MIDI_CMD_PGM_CHANGE:
355                         switch (a & 0xf0) {
356                         case MIDI_CMD_CONTROL:
357                                 break;
358                         case MIDI_CMD_PGM_CHANGE:
359                         case MIDI_CMD_NOTE_OFF:
360                         case MIDI_CMD_NOTE_ON:
361                         case MIDI_CMD_NOTE_PRESSURE:
362                         case MIDI_CMD_CHANNEL_PRESSURE:
363                         case MIDI_CMD_BENDER:
364                                 b_first = true;
365                         }
366                         break;
367
368                 case MIDI_CMD_NOTE_OFF:
369                         switch (a & 0xf0) {
370                         case MIDI_CMD_CONTROL:
371                         case MIDI_CMD_PGM_CHANGE:
372                                 break;
373                         case MIDI_CMD_NOTE_OFF:
374                         case MIDI_CMD_NOTE_ON:
375                         case MIDI_CMD_NOTE_PRESSURE:
376                         case MIDI_CMD_CHANNEL_PRESSURE:
377                         case MIDI_CMD_BENDER:
378                                 b_first = true;
379                         }
380                         break;
381
382                 case MIDI_CMD_NOTE_ON:
383                         switch (a & 0xf0) {
384                         case MIDI_CMD_CONTROL:
385                         case MIDI_CMD_PGM_CHANGE:
386                         case MIDI_CMD_NOTE_OFF:
387                                 break;
388                         case MIDI_CMD_NOTE_ON:
389                         case MIDI_CMD_NOTE_PRESSURE:
390                         case MIDI_CMD_CHANNEL_PRESSURE:
391                         case MIDI_CMD_BENDER:
392                                 b_first = true;
393                         }
394                         break;
395                 case MIDI_CMD_NOTE_PRESSURE:
396                         switch (a & 0xf0) {
397                         case MIDI_CMD_CONTROL:
398                         case MIDI_CMD_PGM_CHANGE:
399                         case MIDI_CMD_NOTE_OFF:
400                         case MIDI_CMD_NOTE_ON:
401                                 break;
402                         case MIDI_CMD_NOTE_PRESSURE:
403                         case MIDI_CMD_CHANNEL_PRESSURE:
404                         case MIDI_CMD_BENDER:
405                                 b_first = true;
406                         }
407                         break;
408
409                 case MIDI_CMD_CHANNEL_PRESSURE:
410                         switch (a & 0xf0) {
411                         case MIDI_CMD_CONTROL:
412                         case MIDI_CMD_PGM_CHANGE:
413                         case MIDI_CMD_NOTE_OFF:
414                         case MIDI_CMD_NOTE_ON:
415                         case MIDI_CMD_NOTE_PRESSURE:
416                                 break;
417                         case MIDI_CMD_CHANNEL_PRESSURE:
418                         case MIDI_CMD_BENDER:
419                                 b_first = true;
420                         }
421                         break;
422                 case MIDI_CMD_BENDER:
423                         switch (a & 0xf0) {
424                         case MIDI_CMD_CONTROL:
425                         case MIDI_CMD_PGM_CHANGE:
426                         case MIDI_CMD_NOTE_OFF:
427                         case MIDI_CMD_NOTE_ON:
428                         case MIDI_CMD_NOTE_PRESSURE:
429                         case MIDI_CMD_CHANNEL_PRESSURE:
430                                 break;
431                         case MIDI_CMD_BENDER:
432                                 b_first = true;
433                         }
434                         break;
435                 }
436         }
437
438         return b_first;
439 }
440
441 /** Merge \a other into this buffer.  Realtime safe. */
442 bool
443 MidiBuffer::merge_in_place (const MidiBuffer &other)
444 {
445         if (other.size() && size()) {
446                 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("merge in place, sizes %1/%2\n", size(), other.size()));
447         }
448
449         if (other.size() == 0) {
450                 return true;
451         }
452
453         if (size() == 0) {
454                 copy (other);
455                 return true;
456         }
457
458         if (size() + other.size() > _capacity) {
459                 return false;
460         }
461
462         const_iterator them = other.begin();
463         iterator us = begin();
464
465         while (them != other.end()) {
466
467                 size_t bytes_to_merge;
468                 ssize_t merge_offset;
469
470                 /* gather up total size of events that are earlier than
471                    the event referenced by "us"
472                 */
473
474                 merge_offset = -1;
475                 bytes_to_merge = 0;
476
477                 while (them != other.end() && (*them).time() < (*us).time()) {
478                         if (merge_offset == -1) {
479                                 merge_offset = them.offset;
480                         }
481                         bytes_to_merge += sizeof (TimeType) + (*them).size();
482                         ++them;
483                 }
484
485                 /* "them" now points to either:
486                  *
487                  * 1) an event that has the same or later timestamp than the
488                  *        event pointed to by "us"
489                  *
490                  * OR
491                  *
492                  * 2) the end of the "other" buffer
493                  *
494                  * if "sz" is non-zero, there is data to be merged from "other"
495                  * into this buffer before we do anything else, corresponding
496                  * to the events from "other" that we skipped while advancing
497                  * "them".
498                  */
499
500                 if (bytes_to_merge) {
501                         assert(merge_offset >= 0);
502                         /* move existing */
503                         memmove (_data + us.offset + bytes_to_merge, _data + us.offset, _size - us.offset);
504                         /* increase _size */
505                         _size += bytes_to_merge;
506                         assert (_size <= _capacity);
507                         /* insert new stuff */
508                         memcpy  (_data + us.offset, other._data + merge_offset, bytes_to_merge);
509                         /* update iterator to our own events. this is a miserable hack */
510                         us.offset += bytes_to_merge;
511                 }
512
513                 /* if we're at the end of the other buffer, we're done */
514
515                 if (them == other.end()) {
516                         break;
517                 }
518
519                 /* if we have two messages messages with the same timestamp. we
520                  * must order them correctly.
521                  */
522
523                 if ((*us).time() == (*them).time()) {
524
525                         DEBUG_TRACE (DEBUG::MidiIO,
526                                      string_compose ("simultaneous MIDI events discovered during merge, times %1/%2 status %3/%4\n",
527                                                      (*us).time(), (*them).time(),
528                                                      (int) *(_data + us.offset + sizeof (TimeType)),
529                                                      (int) *(other._data + them.offset + sizeof (TimeType))));
530
531                         uint8_t our_midi_status_byte = *(_data + us.offset + sizeof (TimeType));
532                         uint8_t their_midi_status_byte = *(other._data + them.offset + sizeof (TimeType));
533                         bool them_first = second_simultaneous_midi_byte_is_first (our_midi_status_byte, their_midi_status_byte);
534
535                         DEBUG_TRACE (DEBUG::MidiIO, string_compose ("other message came first ? %1\n", them_first));
536
537                         if (!them_first) {
538                                 /* skip past our own event */
539                                 ++us;
540                         }
541
542                         bytes_to_merge = sizeof (TimeType) + (*them).size();
543
544                         /* move our remaining events later in the buffer by
545                          * enough to fit the one message we're going to merge
546                          */
547
548                         memmove (_data + us.offset + bytes_to_merge, _data + us.offset, _size - us.offset);
549                         /* increase _size */
550                         _size += bytes_to_merge;
551                         assert(_size <= _capacity);
552                         /* insert new stuff */
553                         memcpy  (_data + us.offset, other._data + them.offset, bytes_to_merge);
554                         /* update iterator to our own events. this is a miserable hack */
555                         us.offset += bytes_to_merge;
556                         /* 'us' is now an iterator to the event right after the
557                            new ones that we merged
558                         */
559                         if (them_first) {
560                                 /* need to skip the event pointed to by 'us'
561                                    since its at the same time as 'them'
562                                    (still), and we'll enter
563                                 */
564
565                                 if (us != end()) {
566                                         ++us;
567                                 }
568                         }
569
570                         /* we merged one event from the other buffer, so
571                          * advance the iterator there.
572                          */
573
574                         ++them;
575
576                 } else {
577
578                         /* advance past our own events to get to the correct insertion
579                            point for the next event(s) from "other"
580                         */
581
582                         while (us != end() && (*us).time() <= (*them).time()) {
583                                 ++us;
584                         }
585                 }
586
587                 /* check to see if we reached the end of this buffer while
588                  * looking for the insertion point.
589                  */
590
591                 if (us == end()) {
592
593                         /* just append the rest of other and we're done*/
594
595                         memcpy (_data + us.offset, other._data + them.offset, other._size - them.offset);
596                         _size += other._size - them.offset;
597                         assert(_size <= _capacity);
598                         break;
599                 }
600         }
601
602         return true;
603 }