*/
#include <iostream>
+
#include "pbd/malign.h"
+#include "pbd/compose.h"
+#include "pbd/debug.h"
+
+#include "ardour/debug.h"
#include "ardour/midi_buffer.h"
using namespace std;
using namespace ARDOUR;
+using namespace PBD;
// FIXME: mirroring for MIDI buffers?
MidiBuffer::MidiBuffer(size_t capacity)
const Evoral::MIDIEvent<TimeType> ev(*i, false);
if (ev.time() >= src_offset && ev.time() < (nframes+src_offset)) {
push_back (ev);
- }
+ } else {
+ cerr << "MIDI event @ " << ev.time() << " skipped, not within range " << src_offset << " .. "
+ << (nframes + src_offset) << endl;
+ }
}
_silent = src.silent();
cerr << "MidiBuffer::push_back failed (buffer is full)" << endl;
return false;
}
-
+
if (!Evoral::midi_event_is_valid(ev.buffer(), ev.size())) {
cerr << "WARNING: MidiBuffer ignoring illegal MIDI event" << endl;
return false;
MidiBuffer::push_back(TimeType time, size_t size, const uint8_t* data)
{
const size_t stamp_size = sizeof(TimeType);
- /*cerr << "MidiBuffer: pushing event @ " << ev.time()
- << " size = " << ev.size() << endl;*/
+
+#ifndef NDEBUG
+ DEBUG_STR_DECL(a);
+ DEBUG_STR_APPEND(a, string_compose ("midibuffer %1 push event @ %2 sz %3 ", this, time, size));
+ for (size_t i=0; i < size; ++i) {
+ DEBUG_STR_APPEND(a,hex);
+ DEBUG_STR_APPEND(a,"0x");
+ DEBUG_STR_APPEND(a,(int)data[i]);
+ DEBUG_STR_APPEND(a,' ');
+ }
+ DEBUG_STR_APPEND(a,'\n');
+ DEBUG_TRACE (DEBUG::MidiIO, DEBUG_STR(a).str());
+#endif
+
+ // cerr << "MidiBuffer: pushing event @ " << time
+ // << " size = " << size << endl;
if (_size + stamp_size + size >= _capacity) {
cerr << "MidiBuffer::push_back failed (buffer is full)" << endl;
return false;
}
+#ifndef NDEBUG
+ size_t test_orig_us_size = _size;
+ size_t test_orig_them_size = other._size;
+ TimeType test_time = 0;
+ size_t test_us_count = 0;
+ size_t test_them_count = 0;
+ for (iterator i = begin(); i != end(); ++i) {
+ assert(Evoral::midi_event_is_valid((*i).buffer(), (*i).size()));
+ assert((*i).time() >= test_time);
+ test_time = (*i).time();
+ ++test_us_count;
+ }
+ test_time = 0;
+ for (const_iterator i = other.begin(); i != other.end(); ++i) {
+ assert(Evoral::midi_event_is_valid((*i).buffer(), (*i).size()));
+ assert((*i).time() >= test_time);
+ test_time = (*i).time();
+ ++test_them_count;
+ }
+#endif
+
const_iterator them = other.begin();
iterator us = begin();
while (them != other.end()) {
- Evoral::MIDIEvent<TimeType> ev_other (*them);
size_t sz = 0;
- size_t src;
+ ssize_t src = -1;
/* gather up total size of events that are earlier than
the event referenced by "us"
*/
- src = 0;
-
- while (them != other.end() && ev_other.time() < (*us).time()) {
- if (!src) {
+ while (them != other.end() && (*them).time() <= (*us).time()) {
+ if (src == -1) {
src = them.offset;
}
- sz += sizeof (TimeType) + ev_other.size();
+ sz += sizeof (TimeType) + (*them).size();
++them;
}
+#if 0
+ if (us != end())
+ cerr << "us @ " << (*us).time() << endl;
+ if (them != other.end())
+ cerr << "them @ " << (*them).time() << endl;
+#endif
+
if (sz) {
+ assert(src >= 0);
/* move existing */
- memmove (_data + us.offset + sz, _data + us.offset , _size - us.offset);
+ memmove (_data + us.offset + sz, _data + us.offset, _size - us.offset);
/* increase _size */
_size += sz;
+ assert(_size <= _capacity);
/* insert new stuff */
memcpy (_data + us.offset, other._data + src, sz);
/* update iterator to our own events. this is a miserable hack */
point for the next event(s) from "other"
*/
- while (us != end() && (*us).time() < ev_other.time()) {
+ while (us != end() && (*us).time() < (*them).time()) {
++us;
}
}
if (!(us != end())) {
/* just append the rest of other */
memcpy (_data + us.offset, other._data + them.offset, other._size - them.offset);
+ _size += other._size - them.offset;
break;
}
}
+#ifndef NDEBUG
+ assert(_size == test_orig_us_size + test_orig_them_size);
+ size_t test_final_count = 0;
+ test_time = 0;
+ for (iterator i = begin(); i != end(); ++i) {
+ // cerr << "CHECK " << test_final_count << " / " << test_us_count + test_them_count << endl;
+ assert(Evoral::midi_event_is_valid((*i).buffer(), (*i).size()));
+ assert((*i).time() >= test_time);
+ test_time = (*i).time();
+ ++test_final_count;
+ }
+ assert(test_final_count = test_us_count + test_them_count);
+#endif
+
return true;
}
_size = 0;
if (this == &a) {
- merge_in_place(b);
+ return merge_in_place(b);
+ } else if (this == &b) {
+ return merge_in_place(a);
+ }
+
+ const_iterator ai = a.begin();
+ const_iterator bi = b.begin();
+
+ resize(a.size() + b.size());
+ while (ai != a.end() && bi != b.end()) {
+ if ((*ai).time() < (*bi).time()) {
+ memcpy(_data + _size, (*ai).buffer(), (*ai).size());
+ _size += (*ai).size();
+ ++ai;
+ } else {
+ memcpy(_data + _size, (*bi).buffer(), (*bi).size());
+ _size += (*bi).size();
+ ++bi;
+ }
+ }
+
+ while (ai != a.end()) {
+ memcpy(_data + _size, (*ai).buffer(), (*ai).size());
+ _size += (*ai).size();
+ ++ai;
}
- if (this == &b) {
- merge_in_place(a);
+ while (bi != b.end()) {
+ memcpy(_data + _size, (*bi).buffer(), (*bi).size());
+ _size += (*bi).size();
+ ++bi;
}
- cerr << "FIXME: MIDI BUFFER MERGE" << endl;
return true;
}