diff --git a/libs/ardour/disk_reader.cc b/libs/ardour/disk_reader.cc index 7039c84b1b..c5f984833e 100644 --- a/libs/ardour/disk_reader.cc +++ b/libs/ardour/disk_reader.cc @@ -1466,8 +1466,13 @@ DiskReader::get_midi_playback (MidiBuffer& dst, samplepos_t start_sample, sample Location* loc = _loop_location; if (loc) { - /* Evoral::Range has inclusive range semantics. Ugh. Hence the -1 */ - const Temporal::Range loop_range (loc->start (), loc->end ()); + /* squish() operates in the location's time-domain. When the location was created + * using music-time, and later converted to audio-time, it can happen that the + * corresponding super-clock is "between samples". e.g loop-end is at sample 1000.12. + * if start_sample = 1000; squish() does nothing because 1000 < 1000.12. + * This is solved by creating the range using (rounded) sample-times. + */ + const Temporal::Range loop_range (loc->start ().samples(), loc->end ().samples()); samplepos_t effective_start = start_sample; samplecnt_t cnt = nframes; sampleoffset_t offset = 0; diff --git a/libs/temporal/temporal/range.h b/libs/temporal/temporal/range.h index cce5dd7b73..d9873ccc9a 100644 --- a/libs/temporal/temporal/range.h +++ b/libs/temporal/temporal/range.h @@ -150,6 +150,7 @@ class LIBTEMPORAL_API Range { */ Range (timepos_t const & s, timepos_t const & e) : _start (s), _end (e) {} + Range (samplepos_t const s, samplepos_t const e) : _start (s), _end (e) {} bool empty() const { return _start == _end; } timecnt_t length() const { return _start.distance (_end); } @@ -165,6 +166,11 @@ class LIBTEMPORAL_API Range { return other._start == _start && other._end == _end; } + void force_to_samples () { + _start = timepos_t((samplepos_t)_start.samples ()); + _end = timepos_t((samplepos_t)_end.samples ()); + } + /** for a T, return a mapping of it into the range (used for * looping). If the argument is earlier than or equal to the end of * this range, do nothing.