Fix Temporal::Range::squish reduced to samples
Loop Location start="a1665678660" end="b145920" Loop-end (at 122BPM) is a2109859636 at 48kHz this is sample 1794098.32 Now play the loop and play sample 1794098 = a2109859248 Range::squish start: a1665678660 end: a2109859636 squish: a2109859248 squish() does nothing, since there are still 388 superclock-ticks until the end of the loop. However, DiskReader::get_midi_playback convertes the value back to samples(), this leads to effective_start == loop_end; resulting in an endless loop. Thanks to MikeLupe to provide a session to reproduce this issue.
This commit is contained in:
parent
419f934ecd
commit
2de84c97d0
@ -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;
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user