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