From 374283cc3f486839650f8dc09ff943697d97e116 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Fri, 22 Sep 2023 15:09:11 -0600 Subject: [PATCH] temporal: provide a new variant of ::get_tempo_and_meter() for BBT time This one is more complex than the Beats or superclock variants, because we cannot just start from the front of the map. Instead, we have to first iterate through the map so that we start the code in _get_tempo_and_meter<...> from the TempoPoint and MeterPoint in effect at the BBT_Argument's reference time. --- libs/temporal/temporal/tempo.h | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/libs/temporal/temporal/tempo.h b/libs/temporal/temporal/tempo.h index 3145423cf5..1f4bfc36a3 100644 --- a/libs/temporal/temporal/tempo.h +++ b/libs/temporal/temporal/tempo.h @@ -1108,7 +1108,37 @@ class /*LIBTEMPORAL_API*/ TempoMap : public PBD::StatefulDestructible if (_tempos.size() == 1 && _meters.size() == 1) { t = &_tempos.front(); m = &_meters.front(); return _points.end(); } return _get_tempo_and_meter > (t, m, &Point::beats, b, _points.begin(), _points.end(), &_tempos.front(), &_meters.front(), can_match, ret_iterator_after_not_at); } + Points::const_iterator get_tempo_and_meter (TempoPoint const *& t, MeterPoint const *& m, BBT_Argument const & bbt, bool can_match, bool ret_iterator_after_not_at) const { + + if (_tempos.size() == 1 && _meters.size() == 1) { t = &_tempos.front(); m = &_meters.front(); return _points.end(); } + + /* Skip through the tempo map to find the tempo and meter in + * effect at the bbt's "reference" time, and use them as the + * starting point for the normal operation of + * _get_tempo_and_meter () + */ + + Tempos::const_iterator tp = _tempos.begin(); + Meters::const_iterator mp = _meters.begin(); + superclock_t ref = bbt.reference(); + + if (ref != 0) { + while (tp != _tempos.end()) { + Tempos::const_iterator nxt = tp; ++nxt; + if (nxt == _tempos.end() || nxt->sclock() > ref) { + break; + } + tp = nxt; + } + while (mp != _meters.end()) { + Meters::const_iterator nxt = mp; ++nxt; + if (nxt == _meters.end() || mp->sclock() > ref) { + break; + } + } } + + return _get_tempo_and_meter > (t, m, &Point::bbt, bbt, _points.begin(), _points.end(), &(*tp), &(*mp), can_match, ret_iterator_after_not_at); } /* This is private, and should not be callable from outside the map