From b47bb55226933ec591e3113de210816227220015 Mon Sep 17 00:00:00 2001 From: nick_m Date: Mon, 21 Mar 2016 23:47:57 +1100 Subject: [PATCH] Tempo ramps - improve music-locked meter drags, improve dump(). - dump now shows cross-calculation of tempo positions. --- gtk2_ardour/editor_drag.cc | 2 +- gtk2_ardour/editor_tempodisplay.cc | 3 +- libs/ardour/tempo.cc | 173 +++++++++++++++++------------ 3 files changed, 102 insertions(+), 76 deletions(-) diff --git a/gtk2_ardour/editor_drag.cc b/gtk2_ardour/editor_drag.cc index 54dcd25ac1..3e46a0a3fe 100644 --- a/gtk2_ardour/editor_drag.cc +++ b/gtk2_ardour/editor_drag.cc @@ -3185,7 +3185,7 @@ MeterMarkerDrag::motion (GdkEvent* event, bool first_move) framepos_t const pf = adjusted_current_frame (event); _marker->set_position (pf); if (_marker->meter().position_lock_style() == MusicTime) { - double const baf = _editor->session()->tempo_map().beat_at_frame (pf); + double const baf = _editor->session()->tempo_map().beat_at_frame (_editor->session()->tempo_map().round_to_bar (pf, (RoundMode) 0)); _editor->session()->tempo_map().gui_move_meter (_real_section, _marker->meter(), baf); } else { _editor->session()->tempo_map().gui_move_meter (_real_section, _marker->meter(), pf); diff --git a/gtk2_ardour/editor_tempodisplay.cc b/gtk2_ardour/editor_tempodisplay.cc index 3f19665760..d817c44013 100644 --- a/gtk2_ardour/editor_tempodisplay.cc +++ b/gtk2_ardour/editor_tempodisplay.cc @@ -336,8 +336,9 @@ Editor::edit_meter_section (MeterSection* section) meter_dialog.get_bbt_time(when); framepos_t const frame = _session->tempo_map().frame_at_beat (_session->tempo_map().bbt_to_beats (when)); - begin_reversible_command (_("replace tempo mark")); + begin_reversible_command (_("replace meter mark")); XMLNode &before = _session->tempo_map().get_state(); + section->set_position_lock_style (meter_dialog.get_lock_style()); if (meter_dialog.get_lock_style() == MusicTime) { _session->tempo_map().replace_meter (*section, Meter (bpb, note_type), when); } else { diff --git a/libs/ardour/tempo.cc b/libs/ardour/tempo.cc index 8af8424a63..2d77d18db4 100644 --- a/libs/ardour/tempo.cc +++ b/libs/ardour/tempo.cc @@ -770,6 +770,7 @@ TempoMap::do_insert (MetricSection* section) */ *(dynamic_cast(*i)) = *(dynamic_cast(insert_meter)); + (*i)->set_position_lock_style (insert_meter->position_lock_style()); need_add = false; } else { _metrics.erase (i); @@ -917,12 +918,14 @@ TempoMap::replace_meter (const MeterSection& ms, const Meter& meter, const BBT_T { Glib::Threads::RWLock::WriterLock lm (lock); MeterSection& first (first_meter()); + const PositionLockStyle pl = ms.position_lock_style(); if (ms.pulse() != first.pulse()) { remove_meter_locked (ms); add_meter_locked (meter, bbt_to_beats_locked (_metrics, where), where, true); } else { /* cannot move the first meter section */ *static_cast(&first) = meter; + first.set_position_lock_style (pl); recompute_map (_metrics); } } @@ -936,12 +939,14 @@ TempoMap::replace_meter (const MeterSection& ms, const Meter& meter, const frame { Glib::Threads::RWLock::WriterLock lm (lock); MeterSection& first (first_meter()); + const PositionLockStyle pl = ms.position_lock_style(); if (ms.pulse() != first.pulse()) { remove_meter_locked (ms); add_meter_locked (meter, frame, true); } else { /* cannot move the first meter section */ *static_cast(&first) = meter; + first.set_position_lock_style (pl); recompute_map (_metrics); } } @@ -1000,7 +1005,6 @@ TempoMap::add_meter_locked (const Meter& meter, double beat, BBT_Time where, boo where.beats = 1; where.bars++; } - /* new meters *always* start on a beat. */ where.ticks = 0; double pulse = pulse_at_beat (_metrics, beat); @@ -1285,7 +1289,7 @@ TempoMap::first_meter () const } } - fatal << _("programming error: no tempo section in tempo map!") << endmsg; + fatal << _("programming error: no meter section in tempo map!") << endmsg; abort(); /*NOTREACHED*/ return *m; } @@ -1373,21 +1377,25 @@ TempoMap::recompute_meters (Metrics& metrics) MeterSection* meter = 0; MeterSection* prev_m = 0; double accumulated_beats = 0.0; - + uint32_t accumulated_bars = 0; for (Metrics::const_iterator mi = metrics.begin(); mi != metrics.end(); ++mi) { if ((meter = dynamic_cast (*mi)) != 0) { if (prev_m) { - accumulated_beats += (meter->pulse() - prev_m->pulse()) * prev_m->note_divisor(); + const double beats_in_m = (meter->pulse() - prev_m->pulse()) * prev_m->note_divisor(); + accumulated_beats += beats_in_m; + accumulated_bars += (beats_in_m + 1) / prev_m->divisions_per_bar(); } + if (meter->position_lock_style() == AudioTime) { pair pr; - pr.first = ceil (pulse_at_frame_locked (metrics, meter->frame())); - BBT_Time const where = beats_to_bbt_locked (metrics, accumulated_beats); + pr.first = pulse_at_frame_locked (metrics, meter->frame()); + BBT_Time const where = BBT_Time (accumulated_bars + 1, 1, 0); pr.second = where; meter->set_pulse (pr); } else { meter->set_frame (frame_at_pulse_locked (metrics, meter->pulse())); } + meter->set_beat (accumulated_beats); prev_m = meter; } @@ -1706,51 +1714,6 @@ TempoMap::pulse_to_bbt (const double& pulse) return ret; } -double -TempoMap::beat_offset_at (const Metrics& metrics, const double& beat) 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 (prev_m) { - if (m->beat() > beat) { - break; - } - - if (m->position_lock_style() == AudioTime) { - beat_off += ((m->pulse() - prev_m->pulse()) / prev_m->note_divisor()) - floor ((m->pulse() - prev_m->pulse()) / prev_m->note_divisor()); - } - } - prev_m = m; - } - } - - return beat_off; -} - -frameoffset_t -TempoMap::frame_offset_at (const Metrics& metrics, const framepos_t& frame) const -{ - frameoffset_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_pulse_locked (metrics, m->pulse()) - m->frame(); - } - } - } - - return frame_off; -} - double TempoMap::beat_at_frame (const framecnt_t& frame) const { @@ -1841,6 +1804,51 @@ TempoMap::frame_at_pulse_locked (const Metrics& metrics, const double& pulse) co return ret; } +double +TempoMap::beat_offset_at (const Metrics& metrics, const double& beat) 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 (prev_m) { + if (m->beat() > beat) { + break; + } + + if (m->position_lock_style() == AudioTime) { + beat_off += ((m->pulse() - prev_m->pulse()) / prev_m->note_divisor()) - floor ((m->pulse() - prev_m->pulse()) / prev_m->note_divisor()); + } + } + prev_m = m; + } + } + + return beat_off; +} + +frameoffset_t +TempoMap::frame_offset_at (const Metrics& metrics, const framepos_t& frame) const +{ + frameoffset_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_pulse_locked (metrics, m->pulse()) - m->frame(); + } + } + } + + return frame_off; +} + framepos_t TempoMap::frame_time (const BBT_Time& bbt) { @@ -1883,7 +1891,6 @@ TempoMap::check_solved (Metrics& metrics, bool by_frame) if (by_frame && t->frame() != prev_ts->frame_at_tempo (t->pulses_per_minute(), t->pulse(), _frame_rate)) { return false; } - /* if (!by_frame && fabs (t->pulse() - prev_ts->pulse_at_tempo (t->pulses_per_minute(), t->frame(), _frame_rate)) > 0.00001) { std::cerr << "beat precision too low for bpm: " << t->beats_per_minute() << std::endl << " |error :" << t->pulse() - prev_ts->pulse_at_tempo (t->pulses_per_minute(), t->frame(), _frame_rate) << std::endl << @@ -1891,7 +1898,6 @@ TempoMap::check_solved (Metrics& metrics, bool by_frame) " |frame at tempo : " << prev_ts->frame_at_tempo (t->pulses_per_minute(), t->pulse(), _frame_rate) << std::endl; return false; } - */ } prev_ts = t; } @@ -2067,28 +2073,37 @@ TempoMap::solve_map (Metrics& imaginary, MeterSection* section, const Meter& mt, { MeterSection* prev_ms = 0; - pair b_bbt = make_pair (pulse, beats_to_bbt_locked (imaginary, pulse)); + pair b_bbt = make_pair (pulse, BBT_Time (1, 1, 0)); + double accumulated_beats = 0.0; + uint32_t accumulated_bars = 0; + section->set_pulse (b_bbt); - MetricSectionSorter cmp; - imaginary.sort (cmp); for (Metrics::iterator i = imaginary.begin(); i != imaginary.end(); ++i) { MeterSection* m; if ((m = dynamic_cast (*i)) != 0) { if (prev_ms) { - if (m == section){ - section->set_frame (frame_at_pulse_locked (imaginary, pulse_at_beat (imaginary, pulse))); - prev_ms = section; - continue; - } + double const beats_in_m = (m->pulse() - prev_ms->pulse()) * prev_ms->note_divisor(); + accumulated_beats += beats_in_m; + accumulated_bars += (beats_in_m + 1) / prev_ms->divisions_per_bar(); + } + if (m == section){ + section->set_frame (frame_at_pulse_locked (imaginary, pulse)); + b_bbt = make_pair (pulse, BBT_Time (accumulated_bars + 1, 1, 0)); + section->set_pulse (b_bbt); + m->set_beat (accumulated_beats); + prev_ms = section; + continue; + } + if (prev_ms) { if (m->position_lock_style() == MusicTime) { m->set_frame (frame_at_pulse_locked (imaginary, m->pulse())); } else { - pair b_bbt = make_pair (pulse_at_frame_locked (imaginary, m->frame()), BBT_Time (1, 1, 0)); - b_bbt.second = beats_to_bbt_locked (imaginary, beat_at_pulse (imaginary, b_bbt.first)); + pair b_bbt = make_pair (pulse_at_frame_locked (imaginary, m->frame()), BBT_Time (accumulated_bars + 1, 1, 0)); m->set_pulse (b_bbt); } } + m->set_beat (accumulated_beats); prev_ms = m; } } @@ -2107,33 +2122,43 @@ void TempoMap::solve_map (Metrics& imaginary, MeterSection* section, const Meter& mt, const framepos_t& frame) { MeterSection* prev_ms = 0; + double accumulated_beats = 0.0; + uint32_t accumulated_bars = 0; + section->set_frame (frame); for (Metrics::iterator i = imaginary.begin(); i != imaginary.end(); ++i) { MeterSection* m; if ((m = dynamic_cast (*i)) != 0) { if (prev_ms) { - if (m == section){ + const double beats_in_m = (m->pulse() - prev_ms->pulse()) * prev_ms->note_divisor(); + accumulated_beats += beats_in_m; + accumulated_bars += (beats_in_m + 1) / prev_ms->divisions_per_bar(); + } + if (m == section){ /* here we define the pulse 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 pulses to keep us sane) */ - double const pulse_at_f = ceil (pulse_at_frame_locked (imaginary, m->frame())); - pair b_bbt = make_pair (pulse_at_f, beats_to_bbt_locked (imaginary, beat_at_pulse (imaginary, pulse_at_f))); + double const pulse_at_f = pulse_at_frame_locked (imaginary, m->frame()); + pair b_bbt = make_pair (pulse_at_f, BBT_Time (accumulated_bars + 1, 1, 0)); m->set_pulse (b_bbt); + m->set_beat (accumulated_beats); prev_ms = m; continue; - } + } + if (prev_ms) { if (m->position_lock_style() == MusicTime) { m->set_frame (frame_at_pulse_locked (imaginary, m->pulse())); } else { double const pulse_at_f = ceil (pulse_at_frame_locked (imaginary, frame)); - pair b_bbt = make_pair (pulse_at_f, beats_to_bbt_locked (imaginary, beat_at_pulse (imaginary, pulse_at_f))); + pair b_bbt = make_pair (pulse_at_f, BBT_Time (accumulated_bars + 1, 1, 0)); m->set_pulse (b_bbt); } } + m->set_beat (accumulated_beats); prev_ms = m; } } @@ -2619,19 +2644,19 @@ TempoMap::dump (Metrics& metrics, std::ostream& o) const 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->pulse() << " frame= " << t->frame() << " (movable? " - << t->movable() << ')' << endl; + << t->movable() << ')' << " pos lock: " << enum_2_string (t->position_lock_style()) << std::endl; + o << "current : " << t->beats_per_minute() << " | " << t->pulse() << " | " << t->frame() << std::endl; if (prev_ts) { - o << "current : " << t->beats_per_minute() << " | " << t->pulse() << " | " << t->frame() << std::endl; o << "previous : " << prev_ts->beats_per_minute() << " | " << prev_ts->pulse() << " | " << prev_ts->frame() << std::endl; - o << "calculated : " << prev_ts->tempo_at_pulse (t->pulse()) << " | " << prev_ts->pulse_at_tempo (t->pulses_per_minute(), t->frame(), _frame_rate) << " | " << prev_ts->frame_at_tempo (t->pulses_per_minute(), t->pulse(), _frame_rate) << std::endl; - o << "------" << std::endl; + o << "calculated : " << prev_ts->tempo_at_pulse (t->pulse()) * prev_ts->note_type() << " | " << prev_ts->pulse_at_tempo (t->pulses_per_minute(), t->frame(), _frame_rate) << " | " << prev_ts->frame_at_tempo (t->pulses_per_minute(), t->pulse(), _frame_rate) << std::endl; } + prev_ts = t; } 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; + << " pulse: " << m->pulse() << " pos lock: " << enum_2_string (m->position_lock_style()) << " (movable? " << m->movable() << ')' << endl; } - prev_ts = t; } + o << "------" << std::endl; } int -- 2.30.2