tempo map: use lookup tables to speed up time conversions
This commit is contained in:
parent
6f095b91ce
commit
644ebe37a8
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user