From 5b5ca546e0c8706ef158f5eb387c90e684e2c1af Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Fri, 12 Nov 2021 14:19:38 -0700 Subject: [PATCH] temporal: fix incorrect implementation of TempoMap::tempo_map() std::lower_bound() is not appropriate here. We need to find the first TempoPoint after the given time, then return the one before that. --- libs/temporal/tempo.cc | 51 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 7 deletions(-) diff --git a/libs/temporal/tempo.cc b/libs/temporal/tempo.cc index 1079ec5a2e..e945c89ff6 100644 --- a/libs/temporal/tempo.cc +++ b/libs/temporal/tempo.cc @@ -2795,9 +2795,19 @@ TempoMap::tempo_at (superclock_t sc) const { assert (!_tempos.empty()); Point::sclock_comparator cmp; - Tempos::const_iterator t = std::lower_bound (_tempos.begin(), _tempos.end(), sc, cmp); - assert (t != _tempos.end()); - return *t; + + Tempos::const_iterator prev = _tempos.end(); + for (Tempos::const_iterator t = _tempos.begin(); t != _tempos.end(); ++t) { + if (cmp (*t, sc)) { + prev = t; + } else { + break; + } + } + if (prev == _tempos.end()) { + return _tempos.front(); + } + return *prev; } @@ -2806,8 +2816,25 @@ TempoMap::tempo_at (Beats const & b) const { assert (!_tempos.empty()); Point::beat_comparator cmp; + + Tempos::const_iterator prev = _tempos.end(); + for (Tempos::const_iterator t = _tempos.begin(); t != _tempos.end(); ++t) { + if (cmp (*t, b)) { + prev = t; + } else { + break; + } + } + if (prev == _tempos.end()) { + return _tempos.front(); + } + return *prev; + + Tempos::const_iterator t = std::lower_bound (_tempos.begin(), _tempos.end(), b, cmp); - assert (t != _tempos.end()); + if (t == _tempos.end()) { + return _tempos.front(); + } return *t; } @@ -2816,9 +2843,19 @@ TempoMap::tempo_at (BBT_Time const & bbt) const { assert (!_tempos.empty()); Point::bbt_comparator cmp; - Tempos::const_iterator t = std::lower_bound (_tempos.begin(), _tempos.end(), bbt, cmp); - assert (t != _tempos.end()); - return *t; + + Tempos::const_iterator prev = _tempos.end(); + for (Tempos::const_iterator t = _tempos.begin(); t != _tempos.end(); ++t) { + if (cmp (*t, bbt)) { + prev = t; + } else { + break; + } + } + if (prev == _tempos.end()) { + return _tempos.front(); + } + return *prev; } TempoMetric