13
0

tempo map: use lookup tables to speed up time conversions

This commit is contained in:
Paul Davis 2023-02-14 10:07:42 -07:00
parent 6f095b91ce
commit 644ebe37a8

View File

@ -489,6 +489,13 @@ TempoPoint::superclock_at (Temporal::Beats const & qn) const
assert (qn >= _quarters); assert (qn >= _quarters);
} }
bool found;
superclock_t sc = _map->superclock_lookup (qn, found);
if (found) {
return sc;
}
if (!actually_ramped()) { if (!actually_ramped()) {
/* not ramped, use linear */ /* not ramped, use linear */
const Beats delta = qn - _quarters; const Beats delta = qn - _quarters;
@ -496,36 +503,36 @@ TempoPoint::superclock_at (Temporal::Beats const & qn) const
return _sclock + (spqn * delta.get_beats()) + int_div_round ((spqn * delta.get_ticks()), superclock_t (Temporal::ticks_per_beat)); return _sclock + (spqn * delta.get_beats()) + int_div_round ((spqn * delta.get_ticks()), superclock_t (Temporal::ticks_per_beat));
} }
superclock_t r;
const double log_expr = superclocks_per_quarter_note() * _omega * DoubleableBeats (qn - _quarters).to_double(); const double log_expr = superclocks_per_quarter_note() * _omega * DoubleableBeats (qn - _quarters).to_double();
if (log_expr < -1) { if (log_expr < -1) {
r = _sclock + llrint (log (-log_expr - 1.0) / -_omega); sc = _sclock + llrint (log (-log_expr - 1.0) / -_omega);
if (r < 0) { if (sc < 0) {
std::cerr << "CASE 1: " << *this << endl << " scpqn = " << superclocks_per_quarter_note() << std::endl; std::cerr << "CASE 1: " << *this << endl << " scpqn = " << superclocks_per_quarter_note() << std::endl;
std::cerr << " for " << qn << " @ " << _quarters << " | " << _sclock << " + log (" << log_expr << ") " std::cerr << " for " << qn << " @ " << _quarters << " | " << _sclock << " + log (" << log_expr << ") "
<< log (-log_expr - 1.0) << log (-log_expr - 1.0)
<< " - omega = " << -_omega << " - omega = " << -_omega
<< " => " << " => "
<< r << std::endl; << sc << std::endl;
abort (); abort ();
} }
} else { } else {
r = _sclock + llrint (log1p (log_expr) / _omega); sc = _sclock + llrint (log1p (log_expr) / _omega);
if (r < 0) { if (sc < 0) {
std::cerr << "CASE 2: scpqn = " << superclocks_per_quarter_note() << std::endl; std::cerr << "CASE 2: scpqn = " << superclocks_per_quarter_note() << std::endl;
std::cerr << " for " << qn << " @ " << _quarters << " | " << _sclock << " + log1p (" << superclocks_per_quarter_note() * _omega * DoubleableBeats (qn - _quarters).to_double() << " = " std::cerr << " for " << qn << " @ " << _quarters << " | " << _sclock << " + log1p (" << superclocks_per_quarter_note() * _omega * DoubleableBeats (qn - _quarters).to_double() << " = "
<< log1p (superclocks_per_quarter_note() * _omega * DoubleableBeats (qn - _quarters).to_double()) << log1p (superclocks_per_quarter_note() * _omega * DoubleableBeats (qn - _quarters).to_double())
<< " => " << " => "
<< r << std::endl; << sc << std::endl;
abort (); abort ();
} }
} }
return r; _map->beat_to_superclock_store (qn, sc);
return sc;
} }
superclock_t superclock_t
@ -557,6 +564,13 @@ TempoPoint::quarters_at_superclock (superclock_t sc) const
return std::numeric_limits<Beats>::max(); return std::numeric_limits<Beats>::max();
} }
bool found;
Beats beats = _map->beat_lookup (sc, found);
if (found) {
return beats;
}
if (!actually_ramped()) { if (!actually_ramped()) {
// assert (sc >= _sclock); // assert (sc >= _sclock);
@ -589,11 +603,16 @@ TempoPoint::quarters_at_superclock (superclock_t sc) const
return std::numeric_limits<Beats>::max(); return std::numeric_limits<Beats>::max();
} }
_map->superclock_to_beat_store (sc, ret);
return ret; return ret;
} }
const double b = (exp (_omega * (sc - _sclock)) - 1) / (superclocks_per_quarter_note() * _omega); const double b = (exp (_omega * (sc - _sclock)) - 1) / (superclocks_per_quarter_note() * _omega);
return _quarters + Beats::from_double (b); beats = _quarters + Beats::from_double (b);
_map->superclock_to_beat_store (sc, beats);
return beats;
} }
MeterPoint::MeterPoint (TempoMap const & map, XMLNode const & node) MeterPoint::MeterPoint (TempoMap const & map, XMLNode const & node)
@ -625,7 +644,9 @@ MeterPoint::quarters_at (Temporal::BBT_Time const & bbt) const
Temporal::BBT_Time Temporal::BBT_Time
MeterPoint::bbt_at (Temporal::Beats const & qn) const MeterPoint::bbt_at (Temporal::Beats const & qn) const
{ {
return bbt_add (_bbt, Temporal::BBT_Offset (0, 0, (qn - _quarters).to_ticks())); BBT_Time bbt (bbt_add (_bbt, Temporal::BBT_Offset (0, 0, (qn - _quarters).to_ticks())));
_map->beat_to_bbt_store (qn, bbt);
return bbt;
} }
XMLNode& XMLNode&
@ -675,6 +696,13 @@ TempoMetric::bbt_at (timepos_t const & pos) const
superclock_t sc = pos.superclocks(); superclock_t sc = pos.superclocks();
bool found;
BBT_Time bbt = _meter->map().bbt_lookup (sc, found);
if (found) {
return BBT_Argument (reftime(), bbt);
}
/* Use the later of the tempo or meter as the reference point to /* Use the later of the tempo or meter as the reference point to
* compute the BBT distance. All map points are fully defined by all 3 * compute the BBT distance. All map points are fully defined by all 3
* time types, but we need the latest one to avoid incorrect * time types, but we need the latest one to avoid incorrect
@ -705,9 +733,10 @@ TempoMetric::bbt_at (timepos_t const & pos) const
DEBUG_TRACE (DEBUG::TemporalMap, string_compose ("BBT offset from %3 @ %1: %2\n", (_tempo->beats() < _meter->beats() ? _meter->bbt() : _tempo->bbt()), bbt_offset, DEBUG_TRACE (DEBUG::TemporalMap, string_compose ("BBT offset from %3 @ %1: %2\n", (_tempo->beats() < _meter->beats() ? _meter->bbt() : _tempo->bbt()), bbt_offset,
(_tempo->beats() < _meter->beats() ? "meter" : "tempo"))); (_tempo->beats() < _meter->beats() ? "meter" : "tempo")));
timepos_t ref (std::min (_meter->sclock(), _tempo->sclock()));
return BBT_Argument (ref, _meter->bbt_add (reference_point->bbt(), bbt_offset)); bbt = _meter->bbt_add (reference_point->bbt(), bbt_offset);
_meter->map().superclock_to_bbt_store (sc, bbt);
return BBT_Argument (reftime(), bbt);
} }
superclock_t superclock_t
@ -868,6 +897,8 @@ TempoMap::set_tempo (Tempo const & t, timepos_t const & time)
DEBUG_TRACE (DEBUG::TemporalMap, string_compose ("Set tempo @ %1 to %2\n", time, t)); DEBUG_TRACE (DEBUG::TemporalMap, string_compose ("Set tempo @ %1 to %2\n", time, t));
drop_lookup_table ();
if (time.is_beats()) { if (time.is_beats()) {
@ -918,6 +949,8 @@ TempoMap::set_tempo (Tempo const & t, timepos_t const & time)
void void
TempoMap::core_add_point (Point* pp) TempoMap::core_add_point (Point* pp)
{ {
drop_lookup_table ();
Points::iterator p; Points::iterator p;
const Beats beats_limit = pp->beats(); const Beats beats_limit = pp->beats();
@ -928,6 +961,8 @@ TempoMap::core_add_point (Point* pp)
TempoPoint* TempoPoint*
TempoMap::core_add_tempo (TempoPoint* tp, bool& replaced) TempoMap::core_add_tempo (TempoPoint* tp, bool& replaced)
{ {
drop_lookup_table ();
Tempos::iterator t; Tempos::iterator t;
const superclock_t sclock_limit = tp->sclock(); const superclock_t sclock_limit = tp->sclock();
const Beats beats_limit = tp->beats (); const Beats beats_limit = tp->beats ();
@ -954,6 +989,8 @@ TempoMap::core_add_tempo (TempoPoint* tp, bool& replaced)
MeterPoint* MeterPoint*
TempoMap::core_add_meter (MeterPoint* mp, bool& replaced) TempoMap::core_add_meter (MeterPoint* mp, bool& replaced)
{ {
drop_lookup_table ();
Meters::iterator m; Meters::iterator m;
const superclock_t sclock_limit = mp->sclock(); const superclock_t sclock_limit = mp->sclock();
const Beats beats_limit = mp->beats (); const Beats beats_limit = mp->beats ();
@ -977,6 +1014,8 @@ TempoMap::core_add_meter (MeterPoint* mp, bool& replaced)
MusicTimePoint* MusicTimePoint*
TempoMap::core_add_bartime (MusicTimePoint* mtp, bool& replaced) TempoMap::core_add_bartime (MusicTimePoint* mtp, bool& replaced)
{ {
drop_lookup_table ();
MusicTimes::iterator m; MusicTimes::iterator m;
const superclock_t sclock_limit = mtp->sclock(); const superclock_t sclock_limit = mtp->sclock();
@ -1022,6 +1061,8 @@ TempoMap::remove_tempo (TempoPoint const & tp, bool with_reset)
return; return;
} }
drop_lookup_table ();
superclock_t sc (tp.sclock()); superclock_t sc (tp.sclock());
Tempos::iterator t; Tempos::iterator t;
@ -1139,6 +1180,8 @@ TempoMap::remove_bartime (MusicTimePoint const & tp, bool with_reset)
return; return;
} }
drop_lookup_table ();
_bartimes.erase (m); _bartimes.erase (m);
remove_point (*m); remove_point (*m);
if (with_reset) { if (with_reset) {
@ -1172,6 +1215,8 @@ TempoMap::remove_point (Point const & point)
void void
TempoMap::reset_starting_at (superclock_t sc) TempoMap::reset_starting_at (superclock_t sc)
{ {
drop_lookup_table ();
DEBUG_TRACE (DEBUG::MapReset, string_compose ("reset starting at %1\n", sc)); DEBUG_TRACE (DEBUG::MapReset, string_compose ("reset starting at %1\n", sc));
#ifndef NDEBUG #ifndef NDEBUG
if (DEBUG_ENABLED(DEBUG::MapReset)) { if (DEBUG_ENABLED(DEBUG::MapReset)) {
@ -1417,6 +1462,8 @@ TempoMap::move_meter (MeterPoint const & mp, timepos_t const & when, bool earlie
return false; return false;
} }
drop_lookup_table ();
const superclock_t old_sc = mp.sclock(); const superclock_t old_sc = mp.sclock();
/* reset position of this meter */ /* reset position of this meter */
@ -1519,6 +1566,8 @@ TempoMap::move_tempo (TempoPoint const & tp, timepos_t const & when, bool push)
return false; return false;
} }
drop_lookup_table ();
/* If the previous tempo is ramped, we need to recompute its omega /* If the previous tempo is ramped, we need to recompute its omega
* constant to cover the (new) duration of the ramp. * constant to cover the (new) duration of the ramp.
*/ */
@ -1706,11 +1755,13 @@ TempoMap::bbt_at (timepos_t const & pos) const
} }
Temporal::BBT_Argument Temporal::BBT_Argument
TempoMap::bbt_at (superclock_t s) const TempoMap::bbt_at (superclock_t sc) const
{ {
TempoMetric metric (metric_at (s)); TempoMetric metric (metric_at (sc));
timepos_t ref (std::min (metric.tempo().sclock(), metric.meter().sclock())); timepos_t ref (std::min (metric.tempo().sclock(), metric.meter().sclock()));
return BBT_Argument (ref, metric.bbt_at (timepos_t::from_superclock (s))); BBT_Time bbt (metric.bbt_at (timepos_t::from_superclock (sc)));
superclock_to_bbt_store (sc, bbt);
return BBT_Argument (ref, bbt);
} }
Temporal::BBT_Argument Temporal::BBT_Argument
@ -1718,7 +1769,9 @@ TempoMap::bbt_at (Temporal::Beats const & qn) const
{ {
TempoMetric metric (metric_at (qn)); TempoMetric metric (metric_at (qn));
timepos_t ref (std::min (metric.tempo().sclock(), metric.meter().sclock())); timepos_t ref (std::min (metric.tempo().sclock(), metric.meter().sclock()));
return BBT_Argument (ref, metric.bbt_at (qn)); BBT_Time bbt (metric.bbt_at (qn));
beat_to_bbt_store (qn, bbt);
return BBT_Argument (ref, bbt);
} }
#if 0 #if 0