diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2012-01-04 03:27:55 +0000 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2012-01-04 03:27:55 +0000 |
commit | 365a8f7f14bdc653bb012b10be8938a8eaaa69ce (patch) | |
tree | 05bad4a94d70807cda2e8fdc02b79f1e8aab8d8d | |
parent | b1a33855ce4254ebbee4f273bb74ceb50628ed05 (diff) |
implement TempoMap::framepos_minus_beats() using new bar|beat map structure, and fix accuracy of TempoMap::framepos_plus_bbt()
git-svn-id: svn://localhost/ardour2/branches/3.0@11155 d708f5d6-7413-0410-9779-e7cbd77b26cf
-rw-r--r-- | libs/ardour/ardour/tempo.h | 1 | ||||
-rw-r--r-- | libs/ardour/tempo.cc | 120 |
2 files changed, 46 insertions, 75 deletions
diff --git a/libs/ardour/ardour/tempo.h b/libs/ardour/ardour/tempo.h index b8b64fa37f..3f4b783de7 100644 --- a/libs/ardour/ardour/tempo.h +++ b/libs/ardour/ardour/tempo.h @@ -271,6 +271,7 @@ class TempoMap : public PBD::StatefulDestructible framepos_t framepos_plus_bbt (framepos_t pos, Timecode::BBT_Time b); framepos_t framepos_plus_beats (framepos_t, Evoral::MusicalTime); + framepos_t framepos_minus_bbt (framepos_t pos, Timecode::BBT_Time b); framepos_t framepos_minus_beats (framepos_t, Evoral::MusicalTime); Evoral::MusicalTime framewalk_to_beats (framepos_t pos, framecnt_t distance); diff --git a/libs/ardour/tempo.cc b/libs/ardour/tempo.cc index 3ca314a0da..54bb23d517 100644 --- a/libs/ardour/tempo.cc +++ b/libs/ardour/tempo.cc @@ -1632,83 +1632,51 @@ TempoMap::framepos_plus_beats (framepos_t pos, Evoral::MusicalTime beats) framepos_t TempoMap::framepos_minus_beats (framepos_t pos, Evoral::MusicalTime beats) { - Metrics::const_iterator i; - const TempoSection* tempo = 0; - const TempoSection* t; - - /* Find the starting tempo */ - - for (i = metrics->begin(); i != metrics->end(); ++i) { - - /* This is a bit of a hack, but pos could be -ve, and if it is, - we consider the initial metric changes (at time 0) to actually - be in effect at pos. - */ - framepos_t f = (*i)->frame (); - if (pos < 0 && f == 0) { - f = pos; - } - - if ((*i)->frame() > pos) { - break; - } - - if ((t = dynamic_cast<const TempoSection*>(*i)) != 0) { - tempo = t; - } - } - - bool no_more_tempos = false; - - /* Move i back to the tempo before "pos" */ - if (i != metrics->begin ()) { - while (i != metrics->begin ()) { - --i; - t = dynamic_cast<TempoSection*> (*i); - if (t) { - break; - } - } - } else { - no_more_tempos = true; - } - - /* We now have: - - tempo -> the Tempo for "pos" - i -> the first metric before "pos", unless no_more_tempos is true - */ - - while (beats) { - - /* Distance to the end of this section in frames */ - framecnt_t distance_frames = no_more_tempos ? max_framepos : (pos - (*i)->frame()); + return framepos_minus_bbt (pos, BBT_Time (beats)); +} - /* Distance to the end in beats */ - Evoral::MusicalTime distance_beats = distance_frames / tempo->frames_per_beat (_frame_rate); +framepos_t +TempoMap::framepos_minus_bbt (framepos_t pos, BBT_Time op) +{ + BBTPointList::const_iterator i; + framecnt_t extra_frames = 0; - /* Amount to subtract this time */ - double const sub = min (distance_beats, beats); + /* start from the bar|beat right before (or at) pos */ - /* Update */ - beats -= sub; - pos -= sub * tempo->frames_per_beat (_frame_rate); + i = bbt_before_or_at (pos); + + /* we know that (*i).frame is less than or equal to pos */ + extra_frames = pos - (*i).frame; + + /* walk backwards */ - /* Move i and tempo back, if there's anything to move to */ - if (i != metrics->begin ()) { - while (i != metrics->begin ()) { - --i; - if ((t = dynamic_cast<const TempoSection*>(*i)) != 0) { - tempo = t; - break; - } + while (i != _map.begin() && (op.bars || op.beats)) { + --i; + if ((*i).is_bar()) { + if (op.bars) { + op.bars--; } } else { - no_more_tempos = true; + if (op.beats) { + op.beats--; + } } } + + /* handle ticks (assumed to be less than + * BBT_Time::ticks_per_bar_division, as always. + */ - return pos; + if (op.ticks) { + frameoffset_t tick_frames = llrint ((*i).meter->frames_per_division (*(*i).tempo, _frame_rate) * (op.ticks/BBT_Time::ticks_per_bar_division)); + framepos_t pre_tick_frames = (*i).frame + extra_frames; + if (tick_frames < pre_tick_frames) { + return pre_tick_frames - tick_frames; + } + return 0; + } else { + return (*i).frame + extra_frames; + } } /** Add the BBT interval op to pos and return the result */ @@ -1718,6 +1686,7 @@ TempoMap::framepos_plus_bbt (framepos_t pos, BBT_Time op) BBT_Time op_copy (op); int additional_minutes = 1; BBTPointList::const_iterator i; + framecnt_t backup_frames = 0; while (true) { @@ -1725,10 +1694,8 @@ TempoMap::framepos_plus_bbt (framepos_t pos, BBT_Time op) op = op_copy; - if ((*i).frame != pos) { - /* we know that (*i).frame is before pos */ - cerr << "Need to account for offset of " << (pos - (*i).frame) << endl; - } + /* we know that (*i).frame is before or equal to pos */ + backup_frames = pos - (*i).frame; while (i != _map.end() && (op.bars || op.beats)) { ++i; @@ -1754,14 +1721,17 @@ TempoMap::framepos_plus_bbt (framepos_t pos, BBT_Time op) additional_minutes *= 2; /* go back and try again */ - cerr << "reached end of map with op now at " << op << " end = " << _map.back().frame << ' ' << _map.back().bar << '|' << _map.back().beat << ", trying to walk " << op_copy << " ... retry\n"; + warning << "reached end of map with op now at " << op << " end = " + << _map.back().frame << ' ' << _map.back().bar << '|' << _map.back().beat << ", trying to walk " + << op_copy << " ... retry" + << endmsg; } if (op.ticks) { - return (*i).frame + + return (*i).frame - backup_frames + llrint ((*i).meter->frames_per_division (*(*i).tempo, _frame_rate) * (op.ticks/BBT_Time::ticks_per_bar_division)); } else { - return (*i).frame; + return (*i).frame - backup_frames; } } |