Fix potential infinite loop when iterating over ControlLists

If you have the "wrong" kind of MIDI CC, the interpolation for the list is set
to Linear, which causes interpolation to return audio time stamps instead of
beat time.  Because of the asymmetrical transforms, this causes iterators over
the Sequence to go haywire and create an infinite loop.

This fix changes ControlList behavior to always return times in the time domain
of the list.
This commit is contained in:
Paul Davis 2025-08-07 12:26:12 -06:00
parent 3320e7d5f9
commit b5f1c5b0dd

View file

@ -1883,20 +1883,33 @@ ControlList::rt_safe_earliest_event_linear_unlocked (Temporal::timepos_t const&
}
/* This method is ONLY used for interpolating to generate value/time
* duples not present in the actual ControlList, and because of this,
* the desired time domain is always audio time.
* duples not present in the actual ControlList
*/
double a = first->when.superclocks ();
double b = next->when.superclocks ();
const double slope = (b - a) / (next->value - first->value);
assert (slope != 0);
double slope;
if (time_domain() == Temporal::AudioTime) {
double a = first->when.superclocks ();
double b = next->when.superclocks ();
slope = (b - a) / (next->value - first->value);
assert (slope != 0);
double t = start_time.superclocks ();
double dt = fmod (t, fabs (slope));
t += fabs (slope) - dt;
x = timecnt_t::from_superclock (t + 1);
y = rint (first->value + (t - a) / slope);
} else {
double a = first->when.beats().to_ticks();
double b = next->when.beats().to_ticks();
slope = (b - a) / (next->value - first->value);
assert (slope != 0);
double t = start_time.beats ().to_ticks();
double dt = fmod (t, fabs (slope));
t += fabs (slope) - dt;
x = timecnt_t::from_ticks (t + 1);
y = rint (first->value + (t - a) / slope);
}
double t = start_time.superclocks ();
double dt = fmod (t, fabs (slope));
t += fabs (slope) - dt;
x = timecnt_t::from_superclock (t + 1);
y = rint (first->value + (t - a) / slope);
if (slope > 0) {
y = std::max (first->value, std::min (next->value, y));
} else {