summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2011-12-29 21:34:46 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2011-12-29 21:34:46 +0000
commit07750ccb324105a010784490266fdc7cbfa9cca3 (patch)
tree5993711eddebab6bef4ce4ade1c45a4843b56969 /libs
parentc19121459bb13cdd457d9c7d00aac7ce099ce79e (diff)
next iteration of tempo map stuff - fixes off-by-one issues with bar offset<->beat math
git-svn-id: svn://localhost/ardour2/branches/3.0@11109 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs')
-rw-r--r--libs/ardour/tempo.cc112
1 files changed, 75 insertions, 37 deletions
diff --git a/libs/ardour/tempo.cc b/libs/ardour/tempo.cc
index 43e83ecaab..1ec463dda2 100644
--- a/libs/ardour/tempo.cc
+++ b/libs/ardour/tempo.cc
@@ -157,7 +157,7 @@ void
TempoSection::update_bar_offset_from_bbt (const Meter& m)
{
_bar_offset = ((double) (start().beats - 1) + (start().ticks/Timecode::BBT_Time::ticks_per_bar_division)) /
- m.divisions_per_bar();
+ (m.divisions_per_bar() - 1);
DEBUG_TRACE (DEBUG::TempoMath, string_compose ("Tempo set bar offset to %1 from %2 w/%3\n", _bar_offset, start(), m.divisions_per_bar()));
}
@@ -173,13 +173,19 @@ TempoSection::update_bbt_time_from_bar_offset (const Meter& meter)
}
new_start.bars = start().bars;
- /* remember the 1-based counting properties of beats */
- new_start.beats = 1 + (uint32_t) floor (_bar_offset * meter.divisions_per_bar());
- new_start.ticks = (uint32_t) floor (BBT_Time::ticks_per_bar_division *
- ((_bar_offset * meter.divisions_per_bar()) - (new_start.beats-1)));
+
+ double ticks = BBT_Time::ticks_per_bar_division * (_bar_offset * (meter.divisions_per_bar() - 1));
+ new_start.beats = (uint32_t) floor(ticks/BBT_Time::ticks_per_bar_division);
+ new_start.ticks = (uint32_t) fmod (ticks, BBT_Time::ticks_per_bar_division);
- DEBUG_TRACE (DEBUG::TempoMath, string_compose ("tempo updated BBT time to %1 from bar offset %2\n", new_start, _bar_offset));
+ DEBUG_TRACE (DEBUG::TempoMath, string_compose ("from bar offset %1 and dpb %2, ticks = %3->%4 beats = %5\n",
+ _bar_offset, meter.divisions_per_bar(), ticks, new_start.ticks, new_start.beats));
+ /* remember the 1-based counting properties of beats */
+ new_start.beats += 1;
+
+ DEBUG_TRACE (DEBUG::TempoMath, string_compose ("tempo updated BBT time to %1 from bar offset %2 w/dpb = %3\n", new_start, _bar_offset, meter.divisions_per_bar()));
+
set_start (new_start);
}
@@ -1576,45 +1582,77 @@ TempoMap::get_points (framepos_t lower, framepos_t upper) const
this could be be because we hit "upper"
or a new metric section.
- meter sections are always at the start
- of a measure. put differently, if a meter
- indicates N divisions per bar, the next
- meter must be a multiple of N divisions
- after it.
-
- so, we've hit a tempo section, which may or
- may not be precisely on a beat.
*/
- if (next_metric != metrics->end() && limit == (*next_metric)->frame() && ((ts = dynamic_cast<TempoSection*> (*next_metric)) != 0) && ts->start().ticks != 0) {
-
- /* compute current at the *next* beat,
- using the tempo section we just
- bumped into.
+ if (next_metric != metrics->end() && limit == (*next_metric)->frame()) {
+
+ /* we bumped into a new metric
+ * section. meter sections are always
+ * at bar boundaries, but tempo
+ * sections can begin anywhere and need
+ * special handling if they are not on
+ * a beat boundary.
+ */
- also, avoid resetting it to position
- of the next metric section as we
- move to that below.
- */
+ DEBUG_TRACE (DEBUG::TempoMath, string_compose ("stopped at metric at %1 @ 2\n", (*next_metric)->start(), (*next_metric)->frame()));
- reset_current_to_metric_section = false;
+ if (((ts = dynamic_cast<TempoSection*> (*next_metric)) != 0) && ts->start().ticks != 0) {
+
+ /* compute current at the *next* beat,
+ using the tempo section we just
+ bumped into.
+ */
+
+ /* recompute how many frames per
+ * division using the tempo we've just
+ * found
+ */
+
+ double next_beat_frames = meter->frames_per_division (*ts,_frame_rate);
+
+ DEBUG_TRACE (DEBUG::TempoMath, string_compose ("bumped into non-beat-aligned tempo metric at %1 = %2, adjust next beat using %3\n",
+ (*next_metric)->start(), (*next_metric)->frame(), ts->bar_offset()));
+
+ current -= beat_frames;
+ current += (ts->bar_offset() * beat_frames) + ((1.0 - ts->bar_offset()) * next_beat_frames);
+
+ /* avoid resetting current to position
+ of the next metric section as we
+ iterate through "metrics"
+ further on below.
+ */
+
+ reset_current_to_metric_section = false;
+
+ } else if (dynamic_cast<MeterSection*> (*next_metric)) {
+
+ /* we hit a new meter section. bump the
+ * bar and return to beat 1
+ */
+
+ // bar++;
+ // beat = 1;
+ // bar_adjusted = true;
+
+ }
- /* recompute how many frames per
- * division using the tempo we've just
- * found
- */
-
- double next_beat_frames = meter->frames_per_division (*ts,_frame_rate);
+ } else {
- DEBUG_TRACE (DEBUG::TempoMath, string_compose ("bumped into non-beat-aligned tempo metric at %1 = %2, adjust next beat using %3\n",
- (*next_metric)->start(), (*next_metric)->frame(), ts->bar_offset()));
-
- current -= beat_frames;
- current += (ts->bar_offset() * beat_frames) + ((1.0 - ts->bar_offset()) * next_beat_frames);
+ /* we hit either:
+
+ - the end of the requested range
+ - a tempo mark that is precisely on beat
+
+ in the first case, we'll exit from
+ the outer loop soon.
+
+ in the second case, nothing special
+ is required.
+ */
}
-
- } else if ((beat > max_divs) || (next_metric != metrics->end() && dynamic_cast<MeterSection*>(*next_metric))) {
+ } else if ((beat > max_divs) || (next_metric != metrics->end() && dynamic_cast<MeterSection*>(*next_metric))) {
+
/* we've arrived at either the end of a bar or
a new **meter** marker (not tempo marker).