using std::endl;
/* overloaded operator* that avoids floating point math when multiplying a superclock position by a number of quarter notes */
-superclock_t operator*(superclock_t sc, Evoral::Beats const & b) { return (sc * ((b.get_beats() * Evoral::Beats::PPQN) + b.get_ticks())) / Evoral::Beats::PPQN; }
+superclock_t operator*(superclock_t sc, Temporal::Beats const & b) { return (sc * ((b.get_beats() * Temporal::Beats::PPQN) + b.get_ticks())) / Temporal::Beats::PPQN; }
Timecode::BBT_Time
Meter::bbt_add (Timecode::BBT_Time const & bbt, Timecode::BBT_Offset const & add) const
Timecode::BBT_Offset r (bars + add.bars, beats + add.beats, ticks + add.ticks);
- if (r.ticks >= Evoral::Beats::PPQN) {
- r.beats += r.ticks / Evoral::Beats::PPQN;
- r.ticks %= Evoral::Beats::PPQN;
+ if (r.ticks >= Temporal::Beats::PPQN) {
+ r.beats += r.ticks / Temporal::Beats::PPQN;
+ r.ticks %= Temporal::Beats::PPQN;
}
if (r.beats > _divisions_per_bar) {
Timecode::BBT_Offset r (bars - sub.bars, beats - sub.beats, ticks - sub.ticks);
if (r.ticks < 0) {
- r.beats -= 1 - (r.ticks / Evoral::Beats::PPQN);
- r.ticks = Evoral::Beats::PPQN + (r.ticks % Evoral::Beats::PPQN);
+ r.beats -= 1 - (r.ticks / Temporal::Beats::PPQN);
+ r.ticks = Temporal::Beats::PPQN + (r.ticks % Temporal::Beats::PPQN);
}
if (r.beats <= 0) {
return b;
}
-Evoral::Beats
+Temporal::Beats
Meter::to_quarters (Timecode::BBT_Offset const & offset) const
{
- Evoral::Beats b;
+ Temporal::Beats b;
b += (offset.bars * _divisions_per_bar * 4) / _note_value;
- cerr << offset.bars << " bars as quarters : " << b << " nv = " << (int) _note_value << endl;
b += (offset.beats * 4) / _note_value;
- cerr << offset.beats << " beats as quarters : " << (offset.beats * 4) / _note_value << " nv = " << (int) _note_value << endl;
- b += Evoral::Beats::ticks (offset.ticks);
+ b += Temporal::Beats::ticks (offset.ticks);
return b;
}
}
superclock_t
-TempoMetric::superclocks_per_grid (framecnt_t sr) const
+TempoMetric::superclocks_per_grid (samplecnt_t sr) const
{
return (superclock_ticks_per_second * Meter::note_value()) / (note_types_per_minute() / Tempo::note_type());
}
superclock_t
-TempoMetric::superclocks_per_bar (framecnt_t sr) const
+TempoMetric::superclocks_per_bar (samplecnt_t sr) const
{
return superclocks_per_grid (sr) * _divisions_per_bar;
}
*/
void
-TempoMetric::compute_c_superclock (framecnt_t sr, superclock_t end_scpqn, superclock_t superclock_duration)
+TempoMetric::compute_c_superclock (samplecnt_t sr, superclock_t end_scpqn, superclock_t superclock_duration)
{
if ((superclocks_per_quarter_note() == end_scpqn) || !ramped()) {
_c_per_superclock = 0.0;
_c_per_superclock = log ((double) superclocks_per_quarter_note () / end_scpqn) / superclock_duration;
}
void
-TempoMetric::compute_c_quarters (framecnt_t sr, superclock_t end_scpqn, Evoral::Beats const & quarter_duration)
+TempoMetric::compute_c_quarters (samplecnt_t sr, superclock_t end_scpqn, Temporal::Beats const & quarter_duration)
{
if ((superclocks_per_quarter_note () == end_scpqn) || !ramped()) {
_c_per_quarter = 0.0;
}
superclock_t
-TempoMetric::superclock_at_qn (Evoral::Beats const & qn) const
+TempoMetric::superclock_at_qn (Temporal::Beats const & qn) const
{
if (_c_per_quarter == 0.0) {
/* not ramped, use linear */
return llrint (superclocks_per_quarter_note() * (log1p (_c_per_quarter * qn.to_double()) / _c_per_quarter));
}
-Evoral::Beats
+void
+TempoMapPoint::set_map (TempoMap* m)
+{
+ _map = m;
+}
+
+void
+TempoMapPoint::set_dirty (bool yn)
+{
+ if (yn != _dirty) {
+ _dirty = yn;
+ if (yn && _map) {
+ _map->set_dirty (true);
+ }
+ }
+}
+
+Temporal::Beats
TempoMapPoint::quarters_at (superclock_t sc) const
{
/* This TempoMapPoint must already have a fully computed metric and position */
if (!ramped()) {
- return _quarters + Evoral::Beats ((sc - _sclock) / (double) (metric().superclocks_per_quarter_note ()));
+ return _quarters + Temporal::Beats ((sc - _sclock) / (double) (metric().superclocks_per_quarter_note ()));
}
- return _quarters + Evoral::Beats (expm1 (metric().c_per_superclock() * (sc - _sclock)) / (metric().c_per_superclock() * metric().superclocks_per_quarter_note ()));
+ return _quarters + Temporal::Beats (expm1 (metric().c_per_superclock() * (sc - _sclock)) / (metric().c_per_superclock() * metric().superclocks_per_quarter_note ()));
}
-Evoral::Beats
+Temporal::Beats
TempoMapPoint::quarters_at (Timecode::BBT_Time const & bbt) const
{
/* This TempoMapPoint must already have a fully computed metric and position */
Timecode::BBT_Offset offset = metric().bbt_delta (bbt, _bbt);
- cerr << "QA BBT DELTA between " << bbt << " and " << _bbt << " = " << offset << " as quarters for " << static_cast<Meter> (metric()) << " = " << metric().to_quarters (offset) << endl;
return _quarters + metric().to_quarters (offset);
}
Timecode::BBT_Time
-TempoMapPoint::bbt_at (Evoral::Beats const & qn) const
+TempoMapPoint::bbt_at (Temporal::Beats const & qn) const
{
/* This TempoMapPoint must already have a fully computed metric and position */
- Evoral::Beats quarters_delta = qn - _quarters;
- int32_t ticks_delta = quarters_delta.to_ticks (Evoral::Beats::PPQN);
+ Temporal::Beats quarters_delta = qn - _quarters;
+ int32_t ticks_delta = quarters_delta.to_ticks (Temporal::Beats::PPQN);
return metric().bbt_add (_bbt, Timecode::BBT_Offset (0, 0, ticks_delta));
}
-TempoMap::TempoMap (Tempo const & initial_tempo, Meter const & initial_meter, framecnt_t sr)
+TempoMap::TempoMap (Tempo const & initial_tempo, Meter const & initial_meter, samplecnt_t sr)
: _sample_rate (sr)
+ , _dirty (false)
{
- TempoMapPoint tmp (TempoMapPoint::Flag (TempoMapPoint::ExplicitMeter|TempoMapPoint::ExplicitTempo), initial_tempo, initial_meter, 0, Evoral::Beats(), Timecode::BBT_Time(), AudioTime);
+ TempoMapPoint tmp (TempoMapPoint::Flag (TempoMapPoint::ExplicitMeter|TempoMapPoint::ExplicitTempo), initial_tempo, initial_meter, 0, Temporal::Beats(), Timecode::BBT_Time(), AudioTime);
_points.push_back (tmp);
}
+void
+TempoMap::set_dirty (bool yn)
+{
+ _dirty = yn;
+}
+
Meter const &
TempoMap::meter_at (superclock_t sc) const
{
}
Meter const &
-TempoMap::meter_at (Evoral::Beats const & b) const
+TempoMap::meter_at (Temporal::Beats const & b) const
{
Glib::Threads::RWLock::ReaderLock lm (_lock);
return meter_at_locked (b);
}
Tempo const &
-TempoMap::tempo_at (Evoral::Beats const &b) const
+TempoMap::tempo_at (Temporal::Beats const &b) const
{
Glib::Threads::RWLock::ReaderLock lm (_lock);
return tempo_at_locked (b);
TempoMap::rebuild (superclock_t limit)
{
Glib::Threads::RWLock::WriterLock lm (_lock);
- rebuild_locked (limit);
-}
-void
-TempoMap::rebuild_locked (superclock_t limit)
-{
/* step one: remove all implicit points after a dirty explicit point */
restart:
first_explicit_dirty = tmp;
+ if (first_explicit_dirty == _points.end()) {
+ /* nothing is dirty */
+ return;
+ }
+
/* remove all implicit points, because we're going to recalculate them all */
while (tmp != _points.end()) {
tmp = next;
}
- /* compute C for all ramped sections */
+ /* compute C-by-quarters for all ramped sections, because we need it shortly */
for (tmp = first_explicit_dirty; tmp != _points.end(); ) {
TempoMapPoints::iterator nxt = tmp;
if ((tmp->lock_style() == MusicTime)) {
/* determine superclock and quarter note time for this (music-time) locked point */
- cerr << "MT-lock, prev = " << *prev << endl;
-
- Evoral::Beats qn = prev->quarters_at (tmp->bbt());
- cerr << "MT-lock @ " << tmp->bbt() << " => " << qn << endl;
+ Temporal::Beats qn = prev->quarters_at (tmp->bbt());
superclock_t sc = prev->sclock() + prev->metric().superclock_at_qn (qn - prev->quarters());
- cerr << "MT-lock sc is " << prev->metric().superclock_at_qn (qn - prev->quarters()) << " after " << prev->sclock() << " = " << sc
- << " secs = " << prev->metric().superclock_at_qn (qn - prev->quarters()) / (double) superclock_ticks_per_second
- << endl;
if (qn != tmp->quarters() || tmp->sclock() != sc) {
- cerr << "Ned to move " << *tmp << endl;
tmp->set_quarters (qn);
tmp->set_sclock (sc);
- cerr << "using " << *prev << " moved music-time-locked @ " << tmp->bbt() << " to " << sc << " aka " << qn << endl;
_points.sort (TempoMapPoint::SuperClockComparator());
- cerr << "Restart\n";
goto restart;
}
}
* of music-time locked points.
*/
- cerr << "POST-SORT\n";
- dump_locked (cerr);
-
prev = _points.end();
/* step two: add new implicit points between each pair of explicit
* points, after the dirty explicit point
*/
+ bool hit_dirty = false;
+ superclock_t first_dirty = 0;
+
for (tmp = _points.begin(); tmp != _points.end(); ) {
- if (!tmp->dirty()) {
- ++tmp;
- continue;
+ if (!hit_dirty) {
+ if (!tmp->dirty()) {
+ ++tmp;
+ continue;
+ }
+ hit_dirty = true;
+ first_dirty = tmp->sclock();
}
TempoMapPoints::iterator next = tmp;
++next;
+
if (prev != _points.end()) {
if ((tmp->lock_style() == AudioTime)) {
- cerr << "AT: check " << *tmp << endl
- << "\t\tusing " << *prev << endl;
/* audio-locked explicit point: recompute it's BBT and quarter-note position since this may have changed */
tmp->set_quarters (prev->quarters_at (tmp->sclock()));
- cerr << "AT - recompute quarters at " << tmp->quarters () << endl;
if (static_cast<Meter>(tmp->metric()) != static_cast<Meter>(prev->metric())) {
/* new meter, must be on bar/measure start */
tmp->set_bbt (prev->metric().round_up_to_bar (prev->bbt_at (tmp->quarters())));
/* no meter change, tempo change required to be on beat */
tmp->set_bbt (prev->bbt_at (tmp->quarters()).round_up_to_beat());
}
- cerr << "AT - recompute bbt at " << tmp->bbt () << endl;
}
}
superclock_t sc = tmp->sclock();
- Evoral::Beats qn (tmp->quarters ());
+ Temporal::Beats qn (tmp->quarters ());
Timecode::BBT_Time bbt (tmp->bbt());
const bool ramped = tmp->ramped () && next != _points.end();
- /* Evoral::Beats are really quarter notes. This counts how many quarter notes
+ /* Temporal::Beats are really quarter notes. This counts how many quarter notes
there are between grid points in this section of the tempo map.
*/
- const Evoral::Beats qn_step = (Evoral::Beats (1) * 4) / tmp->metric().note_value();
+ const Temporal::Beats qn_step = (Temporal::Beats (1) * 4) / tmp->metric().note_value();
/* compute implicit points as far as the next explicit point, or limit,
whichever comes first.
_points.insert (next, TempoMapPoint (*tmp, sc, qn, bbt));
}
- (*tmp).set_dirty (false);
+ tmp->set_dirty (false);
prev = tmp;
tmp = next;
}
+
+ Changed (first_dirty, _points.back().sclock()); /* EMIT SIGNAL */
}
bool
fractional.
*/
- Evoral::Beats b = _points.front().quarters_at (sc).round_to_beat();
+ Temporal::Beats b = _points.front().quarters_at (sc).round_to_beat();
Timecode::BBT_Time bbt = _points.front().bbt_at (b).round_to_beat ();
_points.insert (_points.begin(), TempoMapPoint (TempoMapPoint::ExplicitTempo, tempo, meter, sc, b, bbt, AudioTime, ramp));
fractional.
*/
- Evoral::Beats qn = i->quarters_at (sc).round_to_beat();
+ Temporal::Beats qn = i->quarters_at (sc).round_to_beat();
/* rule: all Tempo changes must be on-beat. So determine the nearest later beat to "sc"
*/
++i;
}
- cerr << "Insert at " << i->sclock() / superclock_ticks_per_second << endl;
_points.insert (i, TempoMapPoint (TempoMapPoint::ExplicitTempo, tempo, meter, sc, qn, bbt, AudioTime, ramp));
return true;
}
fractional.
*/
- Evoral::Beats b = _points.front().quarters_at (sc).round_to_beat();
+ Temporal::Beats b = _points.front().quarters_at (sc).round_to_beat();
Timecode::BBT_Time bbt = _points.front().bbt_at (b).round_to_beat ();
_points.insert (_points.begin(), TempoMapPoint (TempoMapPoint::ExplicitTempo, t, _points.front().metric(), sc, b, bbt, AudioTime, ramp));
fractional.
*/
- Evoral::Beats qn = i->quarters_at (sc).round_to_beat();
+ Temporal::Beats qn = i->quarters_at (sc).round_to_beat();
/* rule: all Tempo changes must be on-beat. So determine the nearest later beat to "sc"
*/
Timecode::BBT_Time on_beat = bbt.round_up_to_beat();
- cerr << "Try to set tempo @ " << on_beat << " to " << t << endl;
-
assert (!_points.empty());
if (_points.front().bbt() > on_beat) {
++i;
/* stick a prototype music-locked point up front and let ::rebuild figure out the superclock and quarter time */
- _points.insert (i, TempoMapPoint (TempoMapPoint::ExplicitTempo, t, meter, 0, Evoral::Beats(), on_beat, MusicTime, ramp));
+ _points.insert (i, TempoMapPoint (TempoMapPoint::ExplicitTempo, t, meter, 0, Temporal::Beats(), on_beat, MusicTime, ramp));
return true;
}
Glib::Threads::RWLock::WriterLock lm (_lock);
Timecode::BBT_Time measure_start (m.round_up_to_bar (bbt));
- cerr << "Try to set meter @ " << measure_start << " to " << m << endl;
-
assert (!_points.empty());
if (_points.front().bbt() > measure_start) {
if (_points.size() == 1 && _points.front().bbt() == measure_start) {
/* change Meter */
- cerr << "Found the single point\n";
*((Meter*) &_points.front().metric()) = m;
- cerr << "Updated meter to " << m << endl;
_points.front().make_explicit (TempoMapPoint::ExplicitMeter);
return true;
}
if (i->bbt() == measure_start) {
*((Meter*) &i->metric()) = m;
- cerr << "Updated meter to " << m << endl;
i->make_explicit (TempoMapPoint::ExplicitMeter);
return true;
}
- Evoral::Beats qn = i->quarters_at (measure_start);
+ Temporal::Beats qn = i->quarters_at (measure_start);
superclock_t sc = i->sclock() + i->metric().superclock_at_qn (qn);
Tempo const & tempo (i->metric());
++i;
- cerr << "NEW METER, provisionally @ "
- << TempoMapPoint (TempoMapPoint::ExplicitMeter, tempo, m, sc, qn, measure_start, MusicTime)
- << endl;
-
_points.insert (i, TempoMapPoint (TempoMapPoint::ExplicitMeter, tempo, m, sc, qn, measure_start, MusicTime));
return true;
}
fractional.
*/
- Evoral::Beats b = _points.front().quarters_at (sc).round_to_beat();
+ Temporal::Beats b = _points.front().quarters_at (sc).round_to_beat();
Timecode::BBT_Time bbt = _points.front().bbt_at (b).round_to_beat ();
_points.insert (_points.begin(), TempoMapPoint (TempoMapPoint::ExplicitMeter, _points.front().metric(), m, sc, b, bbt, AudioTime));
fractional.
*/
- Evoral::Beats b = i->quarters_at (sc).round_to_beat();
+ Temporal::Beats b = i->quarters_at (sc).round_to_beat();
/* rule: all Meter changes must start a new measure. So determine the nearest, lower beat to "sc". If this is not
the first division of the measure, move to the next measure.
*/
TempoMetric const & metric (_points.front().metric());
- const TempoMapPoint tp (TempoMapPoint::Flag (0), metric, metric, sc, Evoral::Beats(), Timecode::BBT_Time(), AudioTime);
+ const TempoMapPoint tp (TempoMapPoint::Flag (0), metric, metric, sc, Temporal::Beats(), Timecode::BBT_Time(), AudioTime);
TempoMapPoint::SuperClockComparator scmp;
TempoMapPoints::iterator tmp = upper_bound (_points.begin(), _points.end(), tp, scmp);
}
TempoMapPoints::iterator
-TempoMap::iterator_at (Evoral::Beats const & qn)
+TempoMap::iterator_at (Temporal::Beats const & qn)
{
/* CALLER MUST HOLD LOCK */
*/
TempoMetric const & metric (_points.front().metric());
- const TempoMapPoint tp (TempoMapPoint::Flag(0), metric, metric, 0, Evoral::Beats(), bbt, MusicTime);
+ const TempoMapPoint tp (TempoMapPoint::Flag(0), metric, metric, 0, Temporal::Beats(), bbt, MusicTime);
TempoMapPoint::BBTComparator bcmp;
TempoMapPoints::iterator tmp = upper_bound (_points.begin(), _points.end(), tp, bcmp);
TempoMap::bbt_at_locked (superclock_t sc) const
{
TempoMapPoint point (const_point_at (sc));
- Evoral::Beats b ((sc - point.sclock()) / (double) point.metric().superclocks_per_quarter_note());
+ Temporal::Beats b ((sc - point.sclock()) / (double) point.metric().superclocks_per_quarter_note());
return point.metric().bbt_add (point.bbt(), Timecode::BBT_Offset (0, b.get_beats(), b.get_ticks()));
}
Timecode::BBT_Time
-TempoMap::bbt_at (Evoral::Beats const & qn) const
+TempoMap::bbt_at (Temporal::Beats const & qn) const
{
Glib::Threads::RWLock::ReaderLock lm (_lock);
return bbt_at_locked (qn);
}
Timecode::BBT_Time
-TempoMap::bbt_at_locked (Evoral::Beats const & qn) const
+TempoMap::bbt_at_locked (Temporal::Beats const & qn) const
{
//Glib::Threads::RWLock::ReaderLock lm (_lock);
TempoMapPoint const & point (const_point_at (qn));
- Evoral::Beats delta (qn - point.quarters());
+ Temporal::Beats delta (qn - point.quarters());
return point.metric().bbt_add (point.bbt(), Timecode::BBT_Offset (0, delta.get_beats(), delta.get_ticks()));
}
-Evoral::Beats
-TempoMap::quarter_note_at (superclock_t sc) const
-{
- Glib::Threads::RWLock::ReaderLock lm (_lock);
- return quarter_note_at_locked (sc);
-}
-
-Evoral::Beats
-TempoMap::quarter_note_at_locked (superclock_t sc) const
-{
- return const_point_at (sc).quarters_at (sc);
-}
-
-Evoral::Beats
-TempoMap::quarter_note_at (Timecode::BBT_Time const & bbt) const
-{
- Glib::Threads::RWLock::ReaderLock lm (_lock);
- return quarter_note_at_locked (bbt);
-}
-
-Evoral::Beats
-TempoMap::quarter_note_at_locked (Timecode::BBT_Time const & bbt) const
-{
- //Glib::Threads::RWLock::ReaderLock lm (_lock);
- TempoMapPoint const & point (const_point_at (bbt));
-
- Timecode::BBT_Time bbt_delta (point.metric().bbt_subtract (bbt, point.bbt()));
- /* XXX need to convert the metric division to quarters to match Evoral::Beats == Evoral::Quarters */
- return point.quarters() + Evoral::Beats ((point.metric().divisions_per_bar() * bbt_delta.bars) + bbt_delta.beats, bbt_delta.ticks);
-}
-
superclock_t
-TempoMap::superclock_at (Evoral::Beats const & qn) const
+TempoMap::superclock_at (Temporal::Beats const & qn) const
{
Glib::Threads::RWLock::ReaderLock lm (_lock);
return superclock_at_locked (qn);
}
superclock_t
-TempoMap::superclock_at_locked (Evoral::Beats const & qn) const
+TempoMap::superclock_at_locked (Temporal::Beats const & qn) const
{
assert (!_points.empty());
--i;
}
- /* compute distance from reference point to b. Remember that Evoral::Beats is always interpreted as quarter notes */
+ /* compute distance from reference point to b. Remember that Temporal::Beats is always interpreted as quarter notes */
- const Evoral::Beats q_delta = qn - i->quarters();
- superclock_t sclock_delta = i->metric().superclocks_per_quarter_note () * q_delta;
+ const Temporal::Beats q_delta = qn - i->quarters();
+ superclock_t sclock_delta = i->metric().superclock_at_qn (q_delta);
return i->sclock() + sclock_delta;
}
assert (!_points.empty());
/* only the bbt property matters, since we're just using it to compare */
- const TempoMapPoint tmp (TempoMapPoint::Flag (0), Tempo (120), Meter (4, 4), 0, Evoral::Beats(), bbt, MusicTime);
+ const TempoMapPoint tmp (TempoMapPoint::Flag (0), Tempo (120), Meter (4, 4), 0, Temporal::Beats(), bbt, MusicTime);
TempoMapPoint::BBTComparator bcmp;
TempoMapPoints::const_iterator i = upper_bound (_points.begin(), _points.end(), tmp, bcmp);
--i;
}
- /* compute distance from reference point to b. Remember that Evoral::Beats is always interpreted as quarter notes */
+ /* this computes the distance from the point, in beats whose size is
+ determined by the meter.
+ */
- //const Evoral::Beats delta = b - i->beats();
- //return i->sclock() + samples_to_superclock ((delta / i->metric().quarter_notes_per_minute ()).to_double() * _sample_rate, _sample_rate);
- return 0;
+ const Timecode::BBT_Offset delta = i->metric().bbt_delta (bbt, i->bbt());
+
+ /* convert to quarter notes */
+ const int32_t ticks = delta.ticks + (Temporal::Beats::PPQN * delta.beats * 4) / i->metric().note_value();
+
+ /* get distance in superclocks */
+ return i->sclock() + i->metric().superclock_at_qn (Temporal::Beats::ticks (ticks));
}
void
-TempoMap::set_sample_rate (framecnt_t new_sr)
+TempoMap::set_sample_rate (samplecnt_t new_sr)
{
//Glib::Threads::RWLock::ReaderLock lm (_lock);
double ratio = new_sr / (double) _sample_rate;
return false;
}
- const Meter meter (p->metric());
- const Tempo tempo (p->metric());
- const bool ramp = p->ramped();
+ /* put a "dirty" flag in at the nearest explicit point to the removal point
+ */
+
+ if (p != _points.begin()) {
+ TempoMapPoints::iterator prev (p);
+ --prev;
+ while (prev != _points.begin() && !prev->is_explicit()) {
+ --prev;
+ }
+ prev->set_dirty (true);
+ } else {
+ TempoMapPoints::iterator nxt (p);
+ ++nxt;
+ while (nxt != _points.end() && !nxt->is_explicit()) {
+ ++nxt;
+ }
+ if (nxt != _points.end()) {
+ nxt->set_dirty (true);
+ }
+ }
+
+ if (!set_tempo_and_meter (p->metric(), p->metric(), destination, p->ramped(), true)) {
+ return false;
+ }
+
+ if (push) {
+
+ p = iterator_at (destination);
+ ++p;
+
+ const superclock_t delta = destination - current;
+
+ while (p != _points.end()) {
+ p->set_sclock (p->sclock() + delta);
+ ++p;
+ }
+ }
_points.erase (p);
- return set_tempo_and_meter (tempo, meter, destination, ramp, true);
+ return true;
}
void
-TempoMap::get_grid (TempoMapPoints& ret, superclock_t start, superclock_t end)
+TempoMap::get_grid (TempoMapPoints& ret, superclock_t start, superclock_t end, Temporal::Beats const & resolution)
{
Glib::Threads::RWLock::ReaderLock lm (_lock);
TempoMapPoints::iterator p = iterator_at (start);
++p;
}
- while (p != _points.end() && p->sclock() < end) {
- ret.push_back (*p);
- ++p;
+ if (resolution == Temporal::Beats()) {
+ /* just hand over the points as-is */
+ while (p != _points.end() && p->sclock() < end) {
+ ret.push_back (*p);
+ ++p;
+ }
+ return;
+ }
+
+ superclock_t pos = p->sclock();
+ Temporal::Beats qpos;
+ TempoMapPoints::iterator nxt = p;
+ ++nxt;
+
+ while ((p != _points.end()) && (pos < end)) {
+ /* recompute grid down to @param resolution level
+ */
+
+ superclock_t sclock_delta = p->metric().superclock_at_qn (qpos);
+
+ ret.push_back (TempoMapPoint (TempoMapPoint::Flag (TempoMapPoint::ExplicitMeter|TempoMapPoint::ExplicitTempo),
+ p->metric(), p->metric(),
+ p->sclock() + sclock_delta,
+ p->quarters() + qpos,
+ p->metric().bbt_add (p->bbt(), Timecode::BBT_Offset (0, qpos.get_beats(), qpos.get_ticks())),
+ AudioTime,
+ p->ramped()));
+
+ qpos += resolution;
+ pos += sclock_delta;
+
+ if (pos >= nxt->sclock()) {
+ p = nxt;
+ ++nxt;
+ }
+ }
+}
+
+
+void
+TempoMap::get_bar_grid (TempoMapPoints& ret, superclock_t start, superclock_t end, int32_t bar_gap)
+{
+ Glib::Threads::RWLock::ReaderLock lm (_lock);
+
+ for (TempoMapPoints::iterator p = iterator_at (start); (p != _points.end()) && (p->sclock() < end); ++p) {
+
+ if ((p->sclock() >= start) && (p->bbt().beats == 1) && ((p->bbt().bars == 1) || (p->bbt().bars % bar_gap == 0))) {
+ ret.push_back (TempoMapPoint (TempoMapPoint::Flag (TempoMapPoint::ExplicitMeter|TempoMapPoint::ExplicitTempo),
+ p->metric(), p->metric(),
+ p->sclock(),
+ p->quarters(),
+ p->bbt(),
+ AudioTime,
+ p->ramped()));
+ }
}
}
for (int b = 1; b < 13; ++b) {
PRINT_RESULT((*m), "+", bbt_add, a, B, b, 0);
PRINT_RESULT((*m), "+", bbt_add, a, B, b, 1);
- PRINT_RESULT((*m), "+", bbt_add, a, B, b, Evoral::Beats::PPQN/2);
- PRINT_RESULT((*m), "+", bbt_add, a, B, b, Evoral::Beats::PPQN);
- PRINT_RESULT((*m), "+", bbt_add, a, B, b, Evoral::Beats::PPQN - 1);
- PRINT_RESULT((*m), "+", bbt_add, a, B, b, Evoral::Beats::PPQN - 2);
+ PRINT_RESULT((*m), "+", bbt_add, a, B, b, Temporal::Beats::PPQN/2);
+ PRINT_RESULT((*m), "+", bbt_add, a, B, b, Temporal::Beats::PPQN);
+ PRINT_RESULT((*m), "+", bbt_add, a, B, b, Temporal::Beats::PPQN - 1);
+ PRINT_RESULT((*m), "+", bbt_add, a, B, b, Temporal::Beats::PPQN - 2);
PRINT_RESULT((*m), "+", bbt_add, b1, B, b, 0);
PRINT_RESULT((*m), "+", bbt_add, b1, B, b, 1);
- PRINT_RESULT((*m), "+", bbt_add, b1, B, b, Evoral::Beats::PPQN/2);
- PRINT_RESULT((*m), "+", bbt_add, b1, B, b, Evoral::Beats::PPQN);
- PRINT_RESULT((*m), "+", bbt_add, b1, B, b, Evoral::Beats::PPQN - 1);
- PRINT_RESULT((*m), "+", bbt_add, b1, B, b, Evoral::Beats::PPQN - 2);
+ PRINT_RESULT((*m), "+", bbt_add, b1, B, b, Temporal::Beats::PPQN/2);
+ PRINT_RESULT((*m), "+", bbt_add, b1, B, b, Temporal::Beats::PPQN);
+ PRINT_RESULT((*m), "+", bbt_add, b1, B, b, Temporal::Beats::PPQN - 1);
+ PRINT_RESULT((*m), "+", bbt_add, b1, B, b, Temporal::Beats::PPQN - 2);
PRINT_RESULT((*m), "+", bbt_add, n1, B, b, 0);
PRINT_RESULT((*m), "+", bbt_add, n1, B, b, 1);
- PRINT_RESULT((*m), "+", bbt_add, n1, B, b, Evoral::Beats::PPQN/2);
- PRINT_RESULT((*m), "+", bbt_add, n1, B, b, Evoral::Beats::PPQN);
- PRINT_RESULT((*m), "+", bbt_add, n1, B, b, Evoral::Beats::PPQN - 1);
- PRINT_RESULT((*m), "+", bbt_add, n1, B, b, Evoral::Beats::PPQN - 2);
+ PRINT_RESULT((*m), "+", bbt_add, n1, B, b, Temporal::Beats::PPQN/2);
+ PRINT_RESULT((*m), "+", bbt_add, n1, B, b, Temporal::Beats::PPQN);
+ PRINT_RESULT((*m), "+", bbt_add, n1, B, b, Temporal::Beats::PPQN - 1);
+ PRINT_RESULT((*m), "+", bbt_add, n1, B, b, Temporal::Beats::PPQN - 2);
}
}
for (int b = 1; b < 13; ++b) {
PRINT_RESULT ((*m), "-", bbt_subtract, a, B, b, 0);
PRINT_RESULT ((*m), "-", bbt_subtract, a, B, b, 1);
- PRINT_RESULT ((*m), "-", bbt_subtract, a, B, b, Evoral::Beats::PPQN/2);
- PRINT_RESULT ((*m), "-", bbt_subtract, a, B, b, Evoral::Beats::PPQN);
- PRINT_RESULT ((*m), "-", bbt_subtract, a, B, b, Evoral::Beats::PPQN - 1);
- PRINT_RESULT ((*m), "-", bbt_subtract, a, B, b, Evoral::Beats::PPQN - 2);
+ PRINT_RESULT ((*m), "-", bbt_subtract, a, B, b, Temporal::Beats::PPQN/2);
+ PRINT_RESULT ((*m), "-", bbt_subtract, a, B, b, Temporal::Beats::PPQN);
+ PRINT_RESULT ((*m), "-", bbt_subtract, a, B, b, Temporal::Beats::PPQN - 1);
+ PRINT_RESULT ((*m), "-", bbt_subtract, a, B, b, Temporal::Beats::PPQN - 2);
}
}
}
}
TempoMapPoints grid;
- tmap.get_grid (grid, SECONDS_TO_SUPERCLOCK (12), SECONDS_TO_SUPERCLOCK (44));
+ tmap.get_grid (grid, SECONDS_TO_SUPERCLOCK (12.3), SECONDS_TO_SUPERCLOCK (44), Temporal::Beats::ticks ((Temporal::Beats::PPQN * 4) / 12));
cout << "grid contains " << grid.size() << endl;
for (TempoMapPoints::iterator p = grid.begin(); p != grid.end(); ++p) {
cout << *p << endl;
}
+ TempoMapPoints bbt_grid;
+ tmap.get_bar_grid (bbt_grid, SECONDS_TO_SUPERCLOCK (0), SECONDS_TO_SUPERCLOCK (100), 4);
+ cout << "bbt_grid contains " << bbt_grid.size() << endl;
+ for (TempoMapPoints::iterator p = bbt_grid.begin(); p != bbt_grid.end(); ++p) {
+ cout << *p << endl;
+ }
+
return 0;
}