diff --git a/gtk2_ardour/audio_clock.cc b/gtk2_ardour/audio_clock.cc index a44c32a10a..4afe4a418d 100644 --- a/gtk2_ardour/audio_clock.cc +++ b/gtk2_ardour/audio_clock.cc @@ -1281,7 +1281,7 @@ AudioClock::set_bbt (framepos_t when, bool /*force*/) TempoMetric m (_session->tempo_map().metric_at (pos)); - sprintf (buf, "%-5.1f", m.tempo().beats_per_minute()); + sprintf (buf, "%-5.1f", _session->tempo_map().tempo_at (pos)); _left_layout->set_markup (string_compose ("" TXTSPAN "%3 %2", INFO_FONT_SIZE, buf, _("Tempo"))); diff --git a/gtk2_ardour/editor_drag.cc b/gtk2_ardour/editor_drag.cc index ea8af8cfd6..e955b35586 100644 --- a/gtk2_ardour/editor_drag.cc +++ b/gtk2_ardour/editor_drag.cc @@ -3231,9 +3231,9 @@ MeterMarkerDrag::finished (GdkEvent* event, bool movement_occurred) } else { /* we removed it before, so add it back now */ if (_marker->meter().position_lock_style() == AudioTime) { - map.add_meter (_marker->meter(), _marker->position()); + map.replace_meter (*_real_section, _marker->meter(), _marker->position()); } else { - map.add_meter (_marker->meter(), map.beat_at_frame (_marker->position()), when); + map.replace_meter (*_real_section, _marker->meter(), when); } XMLNode &after = map.get_state(); @@ -3331,7 +3331,14 @@ TempoMarkerDrag::motion (GdkEvent* event, bool first_move) framepos_t const pf = adjusted_current_frame (event, false); Tempo const tp = _marker->tempo(); _marker->set_position (pf); - _editor->session()->tempo_map().gui_move_tempo (_real_section, tp, pf); + /* just here for a check/laugh + if (_real_section->position_lock_style() == MusicTime) { + const double baf = _editor->session()->tempo_map().beat_at_frame (pf); + _editor->session()->tempo_map().gui_move_tempo_beat (_real_section, tp, baf); + } else { + */ + _editor->session()->tempo_map().gui_move_tempo_frame (_real_section, tp, pf); + //} show_verbose_cursor_time (pf); } diff --git a/libs/ardour/ardour/tempo.h b/libs/ardour/ardour/tempo.h index f6eb722c01..4a193f1240 100644 --- a/libs/ardour/ardour/tempo.h +++ b/libs/ardour/ardour/tempo.h @@ -401,7 +401,7 @@ class LIBARDOUR_API TempoMap : public PBD::StatefulDestructible XMLNode& get_state (void); int set_state (const XMLNode&, int version); - void dump (std::ostream&) const; + void dump (Metrics& metrics, std::ostream&) const; void clear (); TempoMetric metric_at (Timecode::BBT_Time bbt) const; @@ -430,13 +430,16 @@ class LIBARDOUR_API TempoMap : public PBD::StatefulDestructible PBD::Signal0 MetricPositionChanged; private: - double bbt_to_beats_locked (Metrics& metrics, Timecode::BBT_Time bbt); + double bbt_to_beats_locked (const Metrics& metrics, Timecode::BBT_Time bbt); Timecode::BBT_Time beats_to_bbt_locked (Metrics& metrics, double beats); double beat_at_frame_locked (Metrics& metrics, framecnt_t frame) const; - framecnt_t frame_at_beat_locked (Metrics& metrics, double beat) const; + framecnt_t frame_at_beat_locked (const Metrics& metrics, double beat) const; double tick_at_frame_locked (const Metrics& metrics, framecnt_t frame) const; + double tick_offset_at (const Metrics& metrics, double tick) const; + framecnt_t frame_offset_at (const Metrics& metrics, framepos_t frame) const; + framecnt_t frame_at_tick_locked (const Metrics& metrics, double tick) const; - framepos_t frame_time_locked (Metrics& metrics, const Timecode::BBT_Time&); + framepos_t frame_time_locked (const Metrics& metrics, const Timecode::BBT_Time&); bool check_solved (Metrics& metrics, bool by_frame); bool solve_map (Metrics& metrics, TempoSection* section, const Tempo& bpm, const framepos_t& frame); diff --git a/libs/ardour/tempo.cc b/libs/ardour/tempo.cc index 55b16b444a..7d6e4060e3 100644 --- a/libs/ardour/tempo.cc +++ b/libs/ardour/tempo.cc @@ -68,7 +68,6 @@ Meter::frames_per_bar (const Tempo& tempo, framecnt_t sr) const return frames_per_grid (tempo, sr) * _divisions_per_bar; } - /***********************************************************************/ const string TempoSection::xml_state_node_name = "Tempo"; @@ -447,7 +446,7 @@ TempoSection::tick_tempo_at_tick (double tick) const double TempoSection::tick_at_time (double time) const { - return ((exp (_c_func * time)) - 1) * ticks_per_minute() / _c_func; + return ((exp (_c_func * time)) - 1) * (ticks_per_minute() / _c_func); } /* time in minutes at tick */ @@ -746,15 +745,14 @@ void TempoMap::do_insert (MetricSection* section) { bool need_add = true; - /* we only allow new meters to be inserted on beat 1 of an existing * measure. */ MeterSection* m = 0; if ((m = dynamic_cast(section)) != 0) { - assert (m->bbt().ticks == 0); + //assert (m->bbt().ticks == 0); - if (m->position_lock_style() == MusicTime && ((m->bbt().beats != 1) || (m->bbt().ticks != 0))) { + if ((m->bbt().beats != 1) || (m->bbt().ticks != 0)) { pair corrected = make_pair (m->beat(), m->bbt()); corrected.second.beats = 1; @@ -777,6 +775,8 @@ TempoMap::do_insert (MetricSection* section) TempoSection* const tempo = dynamic_cast (*i); TempoSection* const insert_tempo = dynamic_cast (section); + MeterSection* const meter = dynamic_cast (*i); + MeterSection* const insert_meter = dynamic_cast (section); if (tempo && insert_tempo) { @@ -799,11 +799,10 @@ TempoMap::do_insert (MetricSection* section) break; } - } else if (!tempo && !insert_tempo) { + } else if (meter && insert_meter) { /* Meter Sections */ - MeterSection* const meter = dynamic_cast (*i); - MeterSection* const insert_meter = dynamic_cast (section); + bool const ipm = insert_meter->position_lock_style() == MusicTime; if ((ipm && meter->beat() == insert_meter->beat()) || (!ipm && meter->frame() == insert_meter->frame())) { @@ -836,7 +835,6 @@ TempoMap::do_insert (MetricSection* section) if (need_add) { MeterSection* const insert_meter = dynamic_cast (section); TempoSection* const insert_tempo = dynamic_cast (section); - Metrics::iterator i; if (insert_meter) { for (i = _metrics.begin(); i != _metrics.end(); ++i) { @@ -863,7 +861,7 @@ TempoMap::do_insert (MetricSection* section) } _metrics.insert (i, section); - //dump (std::cerr); + //dump (_metrics, std::cerr); } } @@ -941,7 +939,7 @@ TempoMap::add_tempo_locked (const Tempo& tempo, double where, bool recompute, AR do_insert (ts); if (recompute) { - solve_map (_metrics, ts, ts->beats_per_minute(), ts->beat()); + solve_map (_metrics, ts, Tempo (ts->beats_per_minute(), ts->note_type()), ts->beat()); } } @@ -953,7 +951,7 @@ TempoMap::add_tempo_locked (const Tempo& tempo, framepos_t frame, bool recompute do_insert (ts); if (recompute) { - solve_map (_metrics, ts, ts->beats_per_minute(), ts->frame()); + solve_map (_metrics, ts, Tempo (ts->beats_per_minute(), ts->note_type()), ts->frame()); } } @@ -1007,7 +1005,7 @@ TempoMap::add_meter (const Meter& meter, double beat, BBT_Time where) #ifndef NDEBUG if (DEBUG_ENABLED(DEBUG::TempoMap)) { - dump (std::cerr); + dump (_metrics, std::cerr); } #endif @@ -1025,7 +1023,7 @@ TempoMap::add_meter (const Meter& meter, framepos_t frame) #ifndef NDEBUG if (DEBUG_ENABLED(DEBUG::TempoMap)) { - dump (std::cerr); + dump (_metrics, std::cerr); } #endif @@ -1049,11 +1047,11 @@ TempoMap::add_meter_locked (const Meter& meter, double beat, BBT_Time where, boo /* new meters *always* start on a beat. */ where.ticks = 0; - - do_insert (new MeterSection (beat, where, meter.divisions_per_bar(), meter.note_divisor())); + MeterSection* new_meter = new MeterSection (beat, where, meter.divisions_per_bar(), meter.note_divisor()); + do_insert (new_meter); if (recompute) { - recompute_map (_metrics); + solve_map (_metrics, new_meter, Meter (meter.divisions_per_bar(), meter.note_divisor()), beat); } } @@ -1062,11 +1060,14 @@ void TempoMap::add_meter_locked (const Meter& meter, framepos_t frame, bool recompute) { - /* MusicTime meters always start on 1|1|0. */ - do_insert (new MeterSection (frame, meter.divisions_per_bar(), meter.note_divisor())); + MeterSection* new_meter = new MeterSection (frame, meter.divisions_per_bar(), meter.note_divisor()); + double baf = beat_at_frame_locked (_metrics, frame); + pair beat = make_pair (baf, beats_to_bbt_locked (_metrics, baf)); + new_meter->set_beat (beat); + do_insert (new_meter); if (recompute) { - recompute_map (_metrics); + solve_map (_metrics, new_meter, Meter (new_meter->divisions_per_bar(), new_meter->note_divisor()), frame); } } @@ -1396,9 +1397,10 @@ TempoMap::recompute_meters (Metrics& metrics) if (meter->position_lock_style() == AudioTime) { /* a frame based meter has to have a 1|1|0 bbt */ pair pr; - BBT_Time const where (1, 1, 0); - pr.first = beat_at_frame_locked (metrics, meter->frame()); + pr.first = ceil (beat_at_frame_locked (metrics, meter->frame())); + BBT_Time const where = beats_to_bbt_locked (metrics, pr.first); + pr.second = where; meter->set_beat (pr); } else { @@ -1496,7 +1498,6 @@ TempoMap::metric_at (BBT_Time bbt) const void TempoMap::bbt_time (framepos_t frame, BBT_Time& bbt) { - Glib::Threads::RWLock::ReaderLock lm (lock); if (frame < 0) { bbt.bars = 1; @@ -1505,24 +1506,30 @@ TempoMap::bbt_time (framepos_t frame, BBT_Time& bbt) warning << string_compose (_("tempo map asked for BBT time at frame %1\n"), frame) << endmsg; return; } - bbt = beats_to_bbt_locked (_metrics, beat_at_frame_locked (_metrics, frame)); + Glib::Threads::RWLock::ReaderLock lm (lock); + framepos_t const frame_off = frame_offset_at (_metrics, frame); + double const beats = beat_at_frame_locked (_metrics, frame + frame_off); + + bbt = beats_to_bbt_locked (_metrics, beats); } double TempoMap::bbt_to_beats (Timecode::BBT_Time bbt) { Glib::Threads::RWLock::ReaderLock lm (lock); - return bbt_to_beats_locked (_metrics, bbt); + double const ticks = bbt_to_beats_locked (_metrics, bbt) * BBT_Time::ticks_per_beat; + double const tick_off = tick_offset_at (_metrics, ticks); + + return (ticks + tick_off) / BBT_Time::ticks_per_beat; } double -TempoMap::bbt_to_beats_locked (Metrics& metrics, Timecode::BBT_Time bbt) +TempoMap::bbt_to_beats_locked (const Metrics& metrics, Timecode::BBT_Time bbt) { /* CALLER HOLDS READ LOCK */ double accumulated_beats = 0.0; double accumulated_bars = 0.0; - double bars_offset = 0.0; MeterSection* prev_ms = 0; for (Metrics::const_iterator i = metrics.begin(); i != metrics.end(); ++i) { @@ -1536,20 +1543,14 @@ TempoMap::bbt_to_beats_locked (Metrics& metrics, Timecode::BBT_Time bbt) break; } if (prev_ms) { - if (m->position_lock_style() == AudioTime) { - accumulated_beats = 0.0; - accumulated_bars = 0; - bars_offset += bars_to_m; - } else { - accumulated_beats += m->beat() - prev_ms->beat(); - accumulated_bars += bars_to_m; - } + accumulated_beats += m->beat() - prev_ms->beat(); + accumulated_bars += bars_to_m; } prev_ms = m; } } - double const remaining_bars = ((bbt.bars - bars_offset) - 1) - accumulated_bars; + double const remaining_bars = (bbt.bars - 1) - accumulated_bars; double const remaining_bars_in_beats = remaining_bars * prev_ms->divisions_per_bar(); double const ret = remaining_bars_in_beats + accumulated_beats + (bbt.beats - 1) + (bbt.ticks / BBT_Time::ticks_per_beat); @@ -1560,7 +1561,9 @@ Timecode::BBT_Time TempoMap::beats_to_bbt (double beats) { Glib::Threads::RWLock::ReaderLock lm (lock); - return beats_to_bbt_locked (_metrics, beats); + double const ticks = beats * BBT_Time::ticks_per_beat; + double const tick_off = tick_offset_at (_metrics, ticks); + return beats_to_bbt_locked (_metrics, (ticks + tick_off) / BBT_Time::ticks_per_beat); } Timecode::BBT_Time @@ -1577,16 +1580,15 @@ TempoMap::beats_to_bbt_locked (Metrics& metrics, double beats) if ((m = dynamic_cast (*i)) != 0) { if (prev_ms) { + if (m->beat() > beats) { /* this is the meter after the one our beat is on*/ break; } - if(m->position_lock_style() == AudioTime) { - accumulated_bars = 0; - } else { - /* we need a whole number of bars. */ - accumulated_bars += ((m->beat() - prev_ms->beat()) + 1) / prev_ms->divisions_per_bar(); - } + + /* we need a whole number of bars. */ + double const beats_dur = m->beat() - prev_ms->beat(); + accumulated_bars += (beats_dur + 1) / prev_ms->divisions_per_bar(); } prev_ms = m; @@ -1614,7 +1616,7 @@ TempoMap::beats_to_bbt_locked (Metrics& metrics, double beats) ret.ticks -= BBT_Time::ticks_per_beat; } - if (ret.beats > prev_ms->divisions_per_bar()) { + if (ret.beats >= prev_ms->divisions_per_bar() + 1) { ++ret.bars; ret.beats = 1; } @@ -1633,9 +1635,11 @@ TempoMap::tick_at_frame_locked (const Metrics& metrics, framecnt_t frame) const for (Metrics::const_iterator i = metrics.begin(); i != metrics.end(); ++i) { TempoSection* t; if ((t = dynamic_cast (*i)) != 0) { - if ((prev_ts) && frame < t->frame()) { + + if ((prev_ts) && t->frame() > frame) { /*the previous ts is the one containing the frame */ - return prev_ts->tick_at_frame (frame, _frame_rate); + double const ret = prev_ts->tick_at_frame (frame, _frame_rate); + return ret; } accumulated_ticks = t->tick(); @@ -1644,12 +1648,56 @@ TempoMap::tick_at_frame_locked (const Metrics& metrics, framecnt_t frame) const } /* treated as constant for this ts */ - double const ticks_in_section = ((frame - prev_ts->frame()) / prev_ts->frames_per_beat (_frame_rate)) * Timecode::BBT_Time::ticks_per_beat; + double const ticks_in_section = (((frame - prev_ts->frame()) / prev_ts->frames_per_beat (_frame_rate)) * Timecode::BBT_Time::ticks_per_beat); return ticks_in_section + accumulated_ticks; } +double +TempoMap::tick_offset_at (const Metrics& metrics, double tick) const +{ + MeterSection* prev_m = 0; + double beat_off = 0.0; + + for (Metrics::const_iterator i = metrics.begin(); i != metrics.end(); ++i) { + MeterSection* m = 0; + if ((m = dynamic_cast (*i)) != 0) { + if (m->tick() > tick) { + break; + } + + if (prev_m && m->position_lock_style() == AudioTime) { + beat_off += ((m->beat() - prev_m->beat()) / prev_m->note_divisor()) - floor ((m->beat() - prev_m->beat()) / prev_m->note_divisor()); + } + + prev_m = m; + } + } + + return beat_off; +} + +framecnt_t +TempoMap::frame_offset_at (const Metrics& metrics, framepos_t frame) const +{ + framecnt_t frame_off = 0; + + for (Metrics::const_iterator i = metrics.begin(); i != metrics.end(); ++i) { + MeterSection* m = 0; + if ((m = dynamic_cast (*i)) != 0) { + if (m->frame() > frame) { + break; + } + if (m->position_lock_style() == AudioTime) { + frame_off = frame_at_beat_locked (metrics, m->beat()) - m->frame(); + } + } + } + + return frame_off; +} + framecnt_t TempoMap::frame_at_tick_locked (const Metrics& metrics, double tick) const { @@ -1660,8 +1708,9 @@ TempoMap::frame_at_tick_locked (const Metrics& metrics, double tick) const for (Metrics::const_iterator i = metrics.begin(); i != metrics.end(); ++i) { TempoSection* t; + if ((t = dynamic_cast (*i)) != 0) { - if (prev_ts && tick < t->tick()) { + if (prev_ts && t->tick() > tick) { /* prev_ts is the one affecting us. */ return prev_ts->frame_at_tick (tick, _frame_rate); } @@ -1674,7 +1723,7 @@ TempoMap::frame_at_tick_locked (const Metrics& metrics, double tick) const double const ticks_in_section = tick - accumulated_ticks; double const dtime = (ticks_in_section / BBT_Time::ticks_per_beat) * prev_ts->frames_per_beat (_frame_rate); - framecnt_t const ret = ((framecnt_t) floor (dtime)) + prev_ts->frame(); + framecnt_t const ret = (((framecnt_t) floor (dtime)) + prev_ts->frame()); return ret; } @@ -1683,7 +1732,9 @@ double TempoMap::beat_at_frame (framecnt_t frame) const { Glib::Threads::RWLock::ReaderLock lm (lock); - return tick_at_frame_locked (_metrics, frame) / BBT_Time::ticks_per_beat; + double const tick = tick_at_frame_locked (_metrics, frame); + framecnt_t const tick_off = tick_offset_at (_metrics, tick); + return (tick + tick_off) / BBT_Time::ticks_per_beat; } double @@ -1696,11 +1747,13 @@ framecnt_t TempoMap::frame_at_beat (double beat) const { Glib::Threads::RWLock::ReaderLock lm (lock); - return frame_at_tick_locked (_metrics, beat * BBT_Time::ticks_per_beat); + framecnt_t const frame = frame_at_tick_locked (_metrics, beat * BBT_Time::ticks_per_beat); + framecnt_t const frame_off = frame_offset_at (_metrics, frame); + return frame - frame_off; } framecnt_t -TempoMap::frame_at_beat_locked (Metrics& metrics, double beat) const +TempoMap::frame_at_beat_locked (const Metrics& metrics, double beat) const { return frame_at_tick_locked (metrics, beat * BBT_Time::ticks_per_beat); @@ -1719,11 +1772,13 @@ TempoMap::frame_time (const BBT_Time& bbt) } Glib::Threads::RWLock::ReaderLock lm (lock); - return frame_time_locked (_metrics, bbt);; + framecnt_t const frame = frame_at_beat_locked (_metrics, bbt_to_beats_locked (_metrics, bbt)); + framecnt_t const frame_off = frame_offset_at (_metrics, frame); + return frame - frame_off; } framepos_t -TempoMap::frame_time_locked (Metrics& metrics, const BBT_Time& bbt) +TempoMap::frame_time_locked (const Metrics& metrics, const BBT_Time& bbt) { /* HOLD THE READER LOCK */ @@ -1838,27 +1893,7 @@ TempoMap::solve_map (Metrics& imaginary, TempoSection* section, const Tempo& bpm return true; } - /* - prev_ts = 0; - std::cerr << "dumping frame order ------" << std::endl;; - for (Metrics::iterator i = imaginary.begin(); i != imaginary.end(); ++i) { - TempoSection* t; - - if ((t = dynamic_cast (*i)) != 0) { - if (prev_ts) { - - std::cerr << "current : " << t->beats_per_minute() << " | " << t->beat() << " | " << t->frame() << std::endl; - std::cerr << "previous : " << prev_ts->beats_per_minute() << " | " << prev_ts->beat() << " | " << prev_ts->frame() << std::endl; - std::cerr << "calculated : " << prev_ts->tempo_at_beat(t->beat()) << " | " << prev_ts->beat_at_tempo (t->beats_per_minute(), t->frame(), _frame_rate) << " | " << prev_ts->frame_at_tempo(t->beats_per_minute(), t->beat(), _frame_rate) << std::endl; - std::cerr << "------" << std::endl; - - } - prev_ts = t; - } - } - std::cerr << "end dump ------" << std::endl; - */ - + //dump (imaginary, std::cerr); return false; } @@ -1940,29 +1975,7 @@ TempoMap::solve_map (Metrics& imaginary, TempoSection* section, const Tempo& bpm return true; } - /* - prev_ts = 0; - std::cerr << "dumping beat order ------" << std::endl; - std::cerr << "section : " << section->beats_per_minute() << " | " << section->beat() << " | " << section->frame() << std::endl; - std::cerr << "------------------------------------" << std::endl; - - for (Metrics::iterator i = imaginary.begin(); i != imaginary.end(); ++i) { - TempoSection* t; - if ((t = dynamic_cast (*i)) != 0) { - if (prev_ts) { - - std::cerr << "current : " << t->beats_per_minute() << " | " << t->beat() << " | " << t->frame() << std::endl; - std::cerr << "prev : " << prev_ts->beats_per_minute() << " | " << prev_ts->beat() << " | " << prev_ts->frame() << std::endl; - std::cerr << "calculated : " << prev_ts->tempo_at_beat(t->beat()) << " | " << prev_ts->beat_at_tempo (t->beats_per_minute(), t->frame(), _frame_rate) << " | " << prev_ts->frame_at_tempo(t->beats_per_minute(), t->beat(), _frame_rate) << std::endl; - std::cerr << " ------" << std::endl;; - - } - prev_ts = t; - } - } - std::cerr << "end dump ------"; - prev_ts = 0; - */ + //dump (imaginary, std::cerr); return false; } @@ -1972,7 +1985,7 @@ TempoMap::solve_map (Metrics& imaginary, MeterSection* section, const Meter& mt, { MeterSection* prev_ms = 0; - pair b_bbt = make_pair (beat, BBT_Time (1, 1, 0)); + pair b_bbt = make_pair (beat, beats_to_bbt_locked (imaginary, beat)); section->set_beat (b_bbt); MetricSectionSorter cmp; imaginary.sort (cmp); @@ -1981,7 +1994,7 @@ TempoMap::solve_map (Metrics& imaginary, MeterSection* section, const Meter& mt, MeterSection* m; if ((m = dynamic_cast (*i)) != 0) { if (prev_ms) { - if (m->beat() > beat){ + if (m == section){ section->set_frame (frame_at_beat_locked (imaginary, beat)); prev_ms = section; continue; @@ -1990,6 +2003,7 @@ TempoMap::solve_map (Metrics& imaginary, MeterSection* section, const Meter& mt, m->set_frame (frame_at_beat_locked (imaginary, m->beat())); } else { pair b_bbt = make_pair (beat_at_frame_locked (imaginary, m->frame()), BBT_Time (1, 1, 0)); + b_bbt.second = beats_to_bbt_locked (imaginary, b_bbt.first); m->set_beat (b_bbt); } } @@ -1997,9 +2011,6 @@ TempoMap::solve_map (Metrics& imaginary, MeterSection* section, const Meter& mt, } } - MetricSectionFrameSorter fcmp; - //imaginary.sort (fcmp); - if (section->position_lock_style() == AudioTime) { /* we're setting the beat */ section->set_position_lock_style (MusicTime); @@ -2008,32 +2019,36 @@ TempoMap::solve_map (Metrics& imaginary, MeterSection* section, const Meter& mt, } else { recompute_meters (imaginary); } - } void TempoMap::solve_map (Metrics& imaginary, MeterSection* section, const Meter& mt, const framepos_t& frame) { MeterSection* prev_ms = 0; - section->set_frame (frame); - MetricSectionFrameSorter fcmp; - imaginary.sort (fcmp); for (Metrics::iterator i = imaginary.begin(); i != imaginary.end(); ++i) { MeterSection* m; if ((m = dynamic_cast (*i)) != 0) { if (prev_ms) { - if (m->frame() > frame){ - pair b_bbt = make_pair (beat_at_frame_locked (imaginary, frame), BBT_Time (1, 1, 0)); - section->set_beat (b_bbt); - prev_ms = section; + if (m == section){ + /* + here we define the beat for this frame. + we're going to set it 'incorrectly' to the next integer and use this 'error' + as an offset to the map as far as users of the public methods are concerned. + (meters should go on absolute beats to keep us sane) + */ + double const beat_at_f = ceil (beat_at_frame_locked (imaginary, m->frame())); + pair b_bbt = make_pair (beat_at_f, beats_to_bbt_locked (imaginary, beat_at_f)); + m->set_beat (b_bbt); + prev_ms = m; continue; } if (m->position_lock_style() == MusicTime) { m->set_frame (frame_at_beat_locked (imaginary, m->beat())); } else { - pair b_bbt = make_pair (beat_at_frame_locked (imaginary, m->frame()), BBT_Time (1, 1, 0)); + double const beat_at_f = ceil (beat_at_frame_locked (imaginary, frame)); + pair b_bbt = make_pair (beat_at_f, beats_to_bbt_locked (imaginary, beat_at_f)); m->set_beat (b_bbt); } } @@ -2041,16 +2056,13 @@ TempoMap::solve_map (Metrics& imaginary, MeterSection* section, const Meter& mt, } } - MetricSectionSorter cmp; - imaginary.sort (cmp); - if (section->position_lock_style() == MusicTime) { /* we're setting the frame */ section->set_position_lock_style (AudioTime); - recompute_map (imaginary); + recompute_meters (imaginary); section->set_position_lock_style (MusicTime); } else { - recompute_map (imaginary); + recompute_meters (imaginary); } } @@ -2199,7 +2211,7 @@ TempoMap::round_to_type (framepos_t frame, RoundMode dir, BBTPointType type) { Glib::Threads::RWLock::ReaderLock lm (lock); - double const beat_at_framepos = beat_at_frame_locked (_metrics, frame); + double const beat_at_framepos = beat_at_frame_locked (_metrics, frame) + tick_offset_at (_metrics, frame); BBT_Time bbt (beats_to_bbt_locked (_metrics, beat_at_framepos)); @@ -2237,11 +2249,11 @@ TempoMap::round_to_type (framepos_t frame, RoundMode dir, BBTPointType type) case Beat: if (dir < 0) { - return frame_at_beat_locked (_metrics, floor (beat_at_framepos)); + return frame_at_beat_locked (_metrics, floor (beat_at_framepos)) - frame_offset_at (_metrics, frame); } else if (dir > 0) { - return frame_at_beat_locked (_metrics, ceil (beat_at_framepos)); + return frame_at_beat_locked (_metrics, ceil (beat_at_framepos)) - frame_offset_at (_metrics, frame); } else { - return frame_at_beat_locked (_metrics, floor (beat_at_framepos + 0.5)); + return frame_at_beat_locked (_metrics, floor (beat_at_framepos + 0.5)) - frame_offset_at (_metrics, frame); } break; } @@ -2255,17 +2267,19 @@ TempoMap::get_grid (vector& points, { Glib::Threads::RWLock::ReaderLock lm (lock); uint32_t const upper_beat = (uint32_t) floor (beat_at_frame_locked (_metrics, upper)); - uint32_t cnt = (uint32_t) ceil (beat_at_frame_locked (_metrics, lower)); + double cnt = ceil (beat_at_frame_locked (_metrics, lower)); while (cnt <= upper_beat) { - framecnt_t const pos = frame_at_beat_locked (_metrics, cnt); + framecnt_t pos = frame_at_beat_locked (_metrics, cnt); + framecnt_t const frame_offset = frame_offset_at (_metrics, pos); + pos -= frame_offset; MeterSection const meter = meter_section_at (pos); Tempo const tempo = tempo_at (pos); BBT_Time const bbt = beats_to_bbt_locked (_metrics, (double) cnt); points.push_back (BBTPoint (meter, tempo, pos, bbt.bars, bbt.beats)); - ++cnt; + cnt += 1.0; } } @@ -2334,7 +2348,6 @@ TempoMap::tempo_at (framepos_t frame) const { Glib::Threads::RWLock::ReaderLock lm (lock); - TempoMetric m (metric_at (frame)); TempoSection* prev_ts = 0; Metrics::const_iterator i; @@ -2345,14 +2358,17 @@ TempoMap::tempo_at (framepos_t frame) const if ((prev_ts) && t->frame() > frame) { /* this is the one past frame */ double const ret = prev_ts->tempo_at_frame (frame, _frame_rate); - Tempo const ret_tempo (ret, m.tempo().note_type ()); + Tempo const ret_tempo (ret, prev_ts->note_type()); return ret_tempo; } prev_ts = t; } } - return m.tempo(); + double const ret = prev_ts->beats_per_minute(); + Tempo const ret_tempo (ret, prev_ts->note_type ()); + + return ret_tempo; } const MeterSection& @@ -2547,21 +2563,29 @@ TempoMap::set_state (const XMLNode& node, int /*version*/) } void -TempoMap::dump (std::ostream& o) const +TempoMap::dump (Metrics& metrics, std::ostream& o) const { Glib::Threads::RWLock::ReaderLock lm (lock, Glib::Threads::TRY_LOCK); const MeterSection* m; const TempoSection* t; + const TempoSection* prev_ts = 0; - for (Metrics::const_iterator i = _metrics.begin(); i != _metrics.end(); ++i) { + for (Metrics::const_iterator i = metrics.begin(); i != metrics.end(); ++i) { if ((t = dynamic_cast(*i)) != 0) { o << "Tempo @ " << *i << " (Bar-offset: " << t->bar_offset() << ") " << t->beats_per_minute() << " BPM (pulse = 1/" << t->note_type() << ") at " << t->beat() << " frame= " << t->frame() << " (movable? " << t->movable() << ')' << endl; + if (prev_ts) { + o << "current : " << t->beats_per_minute() << " | " << t->beat() << " | " << t->frame() << std::endl; + o << "previous : " << prev_ts->beats_per_minute() << " | " << prev_ts->beat() << " | " << prev_ts->frame() << std::endl; + o << "calculated : " << prev_ts->tempo_at_beat (t->beat()) << " | " << prev_ts->beat_at_tempo (t->beats_per_minute(), t->frame(), _frame_rate) << " | " << prev_ts->frame_at_tempo (t->beats_per_minute(), t->beat(), _frame_rate) << std::endl; + o << "------" << std::endl; + } } else if ((m = dynamic_cast(*i)) != 0) { o << "Meter @ " << *i << ' ' << m->divisions_per_bar() << '/' << m->note_divisor() << " at " << m->bbt() << " frame= " << m->frame() << " (movable? " << m->movable() << ')' << endl; } + prev_ts = t; } }