From 55755d5453dbd632f44dabfcdd3ac459f52810e0 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Mon, 2 May 2022 16:44:15 -0600 Subject: [PATCH] temporal: fix TempoMap::reset_starting_at() We were using a given tempo or meter point as part of the metric used when recomputing its position. In fact, the metric should be only use the tempo/meter immediately preceding the given point. --- libs/temporal/tempo.cc | 83 +++++++++++++++++++++++++--------- libs/temporal/temporal/tempo.h | 4 +- 2 files changed, 65 insertions(+), 22 deletions(-) diff --git a/libs/temporal/tempo.cc b/libs/temporal/tempo.cc index 49f24e32db..90f3ea01ab 100644 --- a/libs/temporal/tempo.cc +++ b/libs/temporal/tempo.cc @@ -452,10 +452,8 @@ TempoPoint::TempoPoint (TempoMap const & map, XMLNode const & node) */ void -TempoPoint::compute_omega (TempoPoint const & next) +TempoPoint::compute_omega_from_next_tempo (TempoPoint const & next) { - cerr << "********* COMPUTING OMEGA for " << *this << " next = " << next << endl; - superclock_t end_scpqn; if (_clamped) { @@ -464,17 +462,28 @@ TempoPoint::compute_omega (TempoPoint const & next) end_scpqn = next.superclocks_per_quarter_note (); } - const DoubleableBeats quarter_duration = next.beats() - beats(); - if ((_type == Constant) || (superclocks_per_quarter_note () == end_scpqn)) { - cerr << " no ramp, my start == " << superclocks_per_quarter_note() << " next end " << end_scpqn << " type " << enum_2_string (_type) << " clamped ? " << _clamped << endl; _omega = 0.0; return; } - _omega = ((1.0/end_scpqn) - (1.0/superclocks_per_quarter_note())) / quarter_duration.to_double(); + compute_omega_from_quarter_duration (next.beats() - beats(), end_scpqn); + // compute_omega_from_audio_duration (superclock_to_samples (next.sclock() - sclock(), TEMPORAL_SAMPLE_RATE), end_scpqn); +} - DEBUG_TRACE (DEBUG::TemporalMap, string_compose ("computed omega = %1%2 dur was %3\n", std::setprecision(12),_omega, DoubleableBeats (quarter_duration).to_double())); +void +TempoPoint::compute_omega_from_quarter_duration (Beats const & quarter_duration, superclock_t end_scpqn) +{ + _omega = ((1.0/end_scpqn) - (1.0/superclocks_per_quarter_note())) / DoubleableBeats (quarter_duration).to_double(); + DEBUG_TRACE (DEBUG::TemporalMap, string_compose ("computed omega from qtr duration = %1%2 dur was %3\n", std::setprecision(12),_omega, quarter_duration)); + double es = superclocks_per_note_type() / (1 + (superclocks_per_note_type() * _omega * DoubleableBeats (quarter_duration).to_double())); +} +void +TempoPoint::compute_omega_from_audio_duration (samplecnt_t audio_duration, superclock_t end_scpqn) +{ + _omega = (1.0 / (samples_to_superclock (audio_duration, TEMPORAL_SAMPLE_RATE))) * log ((double) superclocks_per_note_type() / end_scpqn); + DEBUG_TRACE (DEBUG::TemporalMap, string_compose ("computed omega from audio duration= %1%2 dur was %3\n", std::setprecision(12),_omega, audio_duration)); + double es = superclocks_per_note_type() * exp (-_omega * samples_to_superclock (audio_duration, TEMPORAL_SAMPLE_RATE)); } superclock_t @@ -1129,12 +1138,16 @@ TempoMap::reset_starting_at (superclock_t sc) for (p = _points.begin(); p != _points.end(); ++p) { - bool reset_metric = false; - bool reset_point = false; - bool is_tempo = false; - cerr << "Now looking at " << *p << endl; + if (p->sclock() >= sc) { + break; + } + + mtp = 0; + tp = 0; + mp = 0; + if ((mtp = dynamic_cast (&*p)) != 0) { /* nothing to do here. We do not reset music time (bar @@ -1147,21 +1160,30 @@ TempoMap::reset_starting_at (superclock_t sc) cerr << "Bartime! " << metric << endl; } else if ((tp = dynamic_cast (&*p)) != 0) { - reset_point = true; - is_tempo = true; metric = TempoMetric (*tp, metric.meter()); cerr << "Tempo! " << metric << endl; } else if ((mp = dynamic_cast (&*p)) != 0) { - reset_point = true; metric = TempoMetric (metric.tempo(), *mp); cerr << "Meter! " << metric << endl; } + } - if (p->sclock() < sc) { - continue; + for ( ; p != _points.end(); ++p) { + + + mtp = 0; + tp = 0; + mp = 0; + + if ((mtp = dynamic_cast (&*p)) != 0) { + if ((tp = dynamic_cast (&*p)) != 0) { + mp = dynamic_cast (&*p); + } } - if (is_tempo) { + cerr << "====> working on it!\n"; + + if (tp) { Points::iterator pp = p; nxt_tempo = 0; @@ -1177,18 +1199,32 @@ TempoMap::reset_starting_at (superclock_t sc) } if (tp->ramped() && nxt_tempo) { - tp->compute_omega (*nxt_tempo); + tp->compute_omega_from_next_tempo (*nxt_tempo); } } - if (reset_point) { + if (!mtp) { + cerr << "recompute " << p->bbt() << " using " << metric << endl; superclock_t sc = metric.superclock_at (p->bbt()); DEBUG_TRACE (DEBUG::TemporalMap, string_compose ("\tbased on %1 move to %2,%3\n", p->bbt(), sc, p->beats())); p->set (sc, p->beats(), p->bbt()); + } else { + cerr << "not resetting this\n"; + } + + /* Now ensure that metric is correct moving forward */ + + if ((mtp = dynamic_cast (&*p)) != 0) { + metric = TempoMetric (*mtp, *mtp); + } else if ((tp = dynamic_cast (&*p)) != 0) { + metric = TempoMetric (*tp, metric.meter()); + } else if ((mp = dynamic_cast (&*p)) != 0) { + metric = TempoMetric (metric.tempo(), *mp); } } cerr << "RESET DONE\n\n\n"; + dump (cerr); } bool @@ -2974,6 +3010,10 @@ TempoMap::set_ramped (TempoPoint & tp, bool yn) } } + if (nxt == _tempos.end()) { + return; + } + if (yn) { r.set_end (nxt->end_super_note_type_per_second(), nxt->end_superclocks_per_note_type()); } else { @@ -2981,8 +3021,9 @@ TempoMap::set_ramped (TempoPoint & tp, bool yn) } r.set_ramped (yn); + tp.compute_omega_from_next_tempo (*nxt); - reset_starting_at (tp.sclock()); + reset_starting_at (tp.sclock() + 1); } #if 0 diff --git a/libs/temporal/temporal/tempo.h b/libs/temporal/temporal/tempo.h index 5af534c898..2e9dabb950 100644 --- a/libs/temporal/temporal/tempo.h +++ b/libs/temporal/temporal/tempo.h @@ -421,7 +421,9 @@ class /*LIBTEMPORAL_API*/ TempoPoint : public Tempo, public tempo_hook, public v } LIBTEMPORAL_API double omega() const { return _omega; } - LIBTEMPORAL_API void compute_omega (TempoPoint const & next); + LIBTEMPORAL_API void compute_omega_from_next_tempo (TempoPoint const & next_tempo); + LIBTEMPORAL_API void compute_omega_from_quarter_duration (Beats const & quarter_duration, superclock_t end_scpqn); + LIBTEMPORAL_API void compute_omega_from_audio_duration (samplecnt_t audio_duration, superclock_t end_scpqn); LIBTEMPORAL_API bool actually_ramped () const { return Tempo::ramped() && (_omega != 0); } LIBTEMPORAL_API XMLNode& get_state () const;