summaryrefslogtreecommitdiff
path: root/libs/ardour/smf_source.cc
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2014-11-14 21:19:09 -0500
committerDavid Robillard <d@drobilla.net>2014-11-14 21:19:09 -0500
commit94954f852ead97bcda7afa548d543222733228ef (patch)
treedd11c9056d84bc5987d2ff8f5efa08314db6cbb1 /libs/ardour/smf_source.cc
parent31acd96384b930de928aa8c7969336ba3401bbed (diff)
Fix out of order event errors on save with overlapping notes.
Another consequence of fuzzy Sequence timing, but if the difference is less than a tick this should handle things correctly. If the difference is more than a tick, something's wrong, and it might be okay to just bump forward anyway, but I can't reproduce this and it could lead to corruption so I'm leaving that case noisy.
Diffstat (limited to 'libs/ardour/smf_source.cc')
-rw-r--r--libs/ardour/smf_source.cc29
1 files changed, 21 insertions, 8 deletions
diff --git a/libs/ardour/smf_source.cc b/libs/ardour/smf_source.cc
index c7cd7160f3..8a865c3957 100644
--- a/libs/ardour/smf_source.cc
+++ b/libs/ardour/smf_source.cc
@@ -389,10 +389,22 @@ SMFSource::append_event_unlocked_beats (const Evoral::Event<double>& ev)
name().c_str(), ev.id(), ev.time(), ev.size());
for (size_t i = 0; i < ev.size(); ++i) printf("%X ", ev.buffer()[i]); printf("\n");*/
- if (ev.time() < _last_ev_time_beats) {
- warning << string_compose(_("Skipping event with unordered time %1"), ev.time())
- << endmsg;
- return;
+ double time = ev.time();
+ if (time < _last_ev_time_beats) {
+ const double difference = _last_ev_time_beats - time;
+ if (difference / (double)ppqn() < 1.0) {
+ /* Close enough. This problem occurs because Sequence is not
+ actually ordered due to fuzzy time comparison. I'm pretty sure
+ this is inherently a bad idea which causes problems all over the
+ place, but tolerate it here for now anyway. */
+ time = _last_ev_time_beats;
+ } else {
+ /* Out of order by more than a tick. */
+ warning << string_compose(_("Skipping event with unordered beat time %1 < %2 (off by %3 beats, %4 ticks)"),
+ ev.time(), _last_ev_time_beats, difference, difference / (double)ppqn())
+ << endmsg;
+ return;
+ }
}
Evoral::event_id_t event_id;
@@ -407,13 +419,13 @@ SMFSource::append_event_unlocked_beats (const Evoral::Event<double>& ev)
_model->append (ev, event_id);
}
- _length_beats = max(_length_beats, ev.time());
+ _length_beats = max(_length_beats, time);
- const double delta_time_beats = ev.time() - _last_ev_time_beats;
+ const double delta_time_beats = time - _last_ev_time_beats;
const uint32_t delta_time_ticks = (uint32_t)lrint(delta_time_beats * (double)ppqn());
Evoral::SMF::append_event_delta(delta_time_ticks, ev.size(), ev.buffer(), event_id);
- _last_ev_time_beats = ev.time();
+ _last_ev_time_beats = time;
_flags = Source::Flag (_flags & ~Empty);
}
@@ -430,7 +442,8 @@ SMFSource::append_event_unlocked_frames (const Evoral::Event<framepos_t>& ev, fr
// for (size_t i=0; i < ev.size(); ++i) printf("%X ", ev.buffer()[i]); printf("\n");
if (ev.time() < _last_ev_time_frames) {
- warning << string_compose(_("Skipping event with unordered time %1"), ev.time())
+ warning << string_compose(_("Skipping event with unordered frame time %1 < %2"),
+ ev.time(), _last_ev_time_frames)
<< endmsg;
return;
}