From cc741bdea5792c04334f71e76d94021ec4eaf345 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Wed, 6 Nov 2019 08:58:09 -0700 Subject: [PATCH] fix DiskReader::get_midi_playback() when looping Although at the Session level we never run "through" the loop end, latency compensation means that that start/end sample values passed to Processor::run() may cross the loop end. Fix how we handle this so that we do not read data from after the end of the loop --- libs/ardour/disk_reader.cc | 47 +++++++++++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/libs/ardour/disk_reader.cc b/libs/ardour/disk_reader.cc index c5e2256aa6..ae7bd59082 100644 --- a/libs/ardour/disk_reader.cc +++ b/libs/ardour/disk_reader.cc @@ -1089,20 +1089,51 @@ DiskReader::get_midi_playback (MidiBuffer& dst, samplepos_t start_sample, sample if (!pending_overwrite() && !_no_disk_output && (end_sample >= start_sample)) { - const samplepos_t nframes = ::llabs (end_sample - start_sample); + const samplecnt_t nframes = end_sample - start_sample; if (ms & MonitoringDisk) { /* disk data needed - * - * NOTE: we will never be asked to read across loop location - * boundaries - the session splits processing at the - * loop end. */ - DEBUG_TRACE (DEBUG::MidiDiskIO, string_compose ("playback buffer read, from %1 to %2 (%3)\n", start_sample, end_sample, nframes)); - size_t events_read = rtmb->read (*target, start_sample, end_sample, _tracker); - DEBUG_TRACE (DEBUG::MidiDiskIO, string_compose ("%1 MDS events read %2 range %3 .. %4\n", _name, events_read, playback_sample, playback_sample + nframes)); + Location* loc = _loop_location; + + if (loc) { + /* Evoral::Range has inclusive range semantics. Ugh. Hence the -1 */ + const Evoral::Range loop_range (loc->start(), loc->end() - 1); + samplepos_t effective_start = start_sample; + samplecnt_t cnt = nframes; + + DEBUG_TRACE (DEBUG::MidiDiskIO, string_compose ("LOOP read, loop is %1..%2 range is %3..%4\n", loc->start(), loc->end(), start_sample, end_sample)); + + do { + + samplepos_t effective_end; + + effective_start = loop_range.squish (effective_start); + effective_end = min (effective_start + cnt, loc->end()); + + DEBUG_TRACE (DEBUG::MidiDiskIO, string_compose ("playback buffer LOOP read, from %1 to %2 (%3)\n", effective_start, effective_end, (effective_end - effective_start))); + + size_t events_read = rtmb->read (*target, effective_start, effective_end, _tracker); + cnt -= (effective_end - effective_start); + + DEBUG_TRACE (DEBUG::MidiDiskIO, string_compose ("%1 MDS events LOOP read %2 range %3 .. %4 cnt now %5\n", _name, events_read, effective_start, effective_end, cnt)); + + + if (cnt) { + /* We re going to have to read across the loop end. Resolve any notes the extend across the loop end + */ + _tracker.resolve_notes (*target, loc->end() - 1); + } + + } while (cnt); + + } else { + DEBUG_TRACE (DEBUG::MidiDiskIO, string_compose ("playback buffer read, from %1 to %2 (%3)\n", start_sample, end_sample, nframes)); + size_t events_read = rtmb->read (*target, start_sample, end_sample, _tracker); + DEBUG_TRACE (DEBUG::MidiDiskIO, string_compose ("%1 MDS events read %2 range %3 .. %4\n", _name, events_read, playback_sample, playback_sample + nframes)); + } } if (ms & MonitoringInput) {