From 58d4889ad359d43f12c7ce7a0a0e9355b936f30a Mon Sep 17 00:00:00 2001 From: nick_m Date: Wed, 23 Mar 2016 01:11:00 +1100 Subject: Tempo ramps - music-locked meters now use beats rather than pulses as their reference. - fixes many problems with a non-zero audio-locked first meter. --- gtk2_ardour/editor_drag.cc | 11 +++-- gtk2_ardour/editor_ops.cc | 2 +- gtk2_ardour/editor_tempodisplay.cc | 4 +- libs/ardour/ardour/tempo.h | 26 +++++++----- libs/ardour/tempo.cc | 86 ++++++++++++++++++++++---------------- 5 files changed, 72 insertions(+), 57 deletions(-) diff --git a/gtk2_ardour/editor_drag.cc b/gtk2_ardour/editor_drag.cc index 3e46a0a3fe..fdb0f695fd 100644 --- a/gtk2_ardour/editor_drag.cc +++ b/gtk2_ardour/editor_drag.cc @@ -3182,7 +3182,7 @@ MeterMarkerDrag::motion (GdkEvent* event, bool first_move) _marker->hide(); } - framepos_t const pf = adjusted_current_frame (event); + framepos_t const pf = adjusted_current_frame (event, false); _marker->set_position (pf); if (_marker->meter().position_lock_style() == MusicTime) { double const baf = _editor->session()->tempo_map().beat_at_frame (_editor->session()->tempo_map().round_to_bar (pf, (RoundMode) 0)); @@ -3366,8 +3366,8 @@ TempoMarkerDrag::finished (GdkEvent* event, bool movement_occurred) XMLNode &before = map.get_state(); if (_marker->tempo().position_lock_style() == MusicTime) { - double const beat = map.predict_tempo_beat (_real_section, _marker->tempo(), _real_section->frame()); - map.add_tempo (_marker->tempo(), beat, _marker->tempo().type()); + double const pulse = map.predict_tempo_pulse (_real_section, _marker->tempo(), _real_section->frame()); + map.add_tempo (_marker->tempo(), pulse, _marker->tempo().type()); } else { map.add_tempo (_marker->tempo(), _real_section->frame(), _marker->tempo().type()); } @@ -3377,11 +3377,10 @@ TempoMarkerDrag::finished (GdkEvent* event, bool movement_occurred) _editor->commit_reversible_command (); } else { - /* we removed it before, so add it back now */ if (_marker->tempo().position_lock_style() == MusicTime) { - double const beat = map.predict_tempo_beat (_real_section, _marker->tempo(), _real_section->frame()); + double const pulse = map.predict_tempo_pulse (_real_section, _marker->tempo(), _real_section->frame()); map.replace_tempo (*_real_section, Tempo (_marker->tempo().beats_per_minute(), _marker->tempo().note_type()) - , beat, _marker->tempo().type()); + , pulse, _marker->tempo().type()); } else { map.replace_tempo (*_real_section, Tempo (_marker->tempo().beats_per_minute(), _marker->tempo().note_type()) , _real_section->frame(), _marker->tempo().type()); diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc index 1cc9d54cb6..960b7b3123 100644 --- a/gtk2_ardour/editor_ops.cc +++ b/gtk2_ardour/editor_ops.cc @@ -6552,7 +6552,7 @@ Editor::define_one_bar (framepos_t start, framepos_t end) } else if (t.frame() == start) { _session->tempo_map().change_existing_tempo_at (start, beats_per_minute, t.note_type()); } else { - _session->tempo_map().add_tempo (Tempo (beats_per_minute, t.note_type()), _session->tempo_map().beat_at_frame (start), TempoSection::Constant); + _session->tempo_map().add_tempo (Tempo (beats_per_minute, t.note_type()), start, TempoSection::Constant); } XMLNode& after (_session->tempo_map().get_state()); diff --git a/gtk2_ardour/editor_tempodisplay.cc b/gtk2_ardour/editor_tempodisplay.cc index d817c44013..e1201579a6 100644 --- a/gtk2_ardour/editor_tempodisplay.cc +++ b/gtk2_ardour/editor_tempodisplay.cc @@ -242,7 +242,7 @@ Editor::mouse_add_new_tempo_event (framepos_t frame) begin_reversible_command (_("add tempo mark")); XMLNode &before = map.get_state(); if (tempo_dialog.get_lock_style() == MusicTime) { - map.add_tempo (Tempo (bpm,nt), map.bbt_to_beats (requested), tempo_dialog.get_tempo_type()); + map.add_tempo (Tempo (bpm,nt), map.pulse_at_beat (map.bbt_to_beats (requested)), tempo_dialog.get_tempo_type()); } else { map.add_tempo (Tempo (bpm,nt), frame, tempo_dialog.get_tempo_type()); } @@ -373,7 +373,7 @@ Editor::edit_tempo_section (TempoSection* section) begin_reversible_command (_("replace tempo mark")); XMLNode &before = _session->tempo_map().get_state(); if (tempo_dialog.get_lock_style() == MusicTime) { - _session->tempo_map().replace_tempo (*section, Tempo (bpm, nt), beat, tempo_dialog.get_tempo_type()); + _session->tempo_map().replace_tempo (*section, Tempo (bpm, nt), _session->tempo_map().pulse_at_beat (beat), tempo_dialog.get_tempo_type()); } else { framepos_t const f = _session->tempo_map().predict_tempo_frame (section, Tempo (bpm, nt), when); _session->tempo_map().replace_tempo (*section, Tempo (bpm, nt), f, tempo_dialog.get_tempo_type()); diff --git a/libs/ardour/ardour/tempo.h b/libs/ardour/ardour/tempo.h index 5351d4fa94..737c288abe 100644 --- a/libs/ardour/ardour/tempo.h +++ b/libs/ardour/ardour/tempo.h @@ -365,7 +365,7 @@ class LIBARDOUR_API TempoMap : public PBD::StatefulDestructible const TempoSection& tempo_section_at (framepos_t frame) const; const MeterSection& meter_section_at (framepos_t frame) const; - void add_tempo (const Tempo&, const double& beat, TempoSection::Type type); + void add_tempo (const Tempo&, const double& pulse, TempoSection::Type type); void add_tempo (const Tempo&, const framepos_t& frame, TempoSection::Type type); void add_meter (const Meter&, const double& beat, const Timecode::BBT_Time& where); @@ -375,7 +375,7 @@ class LIBARDOUR_API TempoMap : public PBD::StatefulDestructible void remove_meter (const MeterSection&, bool send_signal); framepos_t predict_tempo_frame (TempoSection* section, const Tempo& bpm, const Timecode::BBT_Time& bbt); - double predict_tempo_beat (TempoSection* section, const Tempo& bpm, const framepos_t& beat); + double predict_tempo_pulse (TempoSection* section, const Tempo& bpm, const framepos_t& frame); void replace_tempo (const TempoSection&, const Tempo&, const double& where, TempoSection::Type type); void replace_tempo (const TempoSection&, const Tempo&, const framepos_t& frame, TempoSection::Type type); @@ -399,7 +399,7 @@ class LIBARDOUR_API TempoMap : public PBD::StatefulDestructible XMLNode& get_state (void); int set_state (const XMLNode&, int version); - void dump (Metrics& metrics, std::ostream&) const; + void dump (const Metrics& metrics, std::ostream&) const; void clear (); TempoMetric metric_at (Timecode::BBT_Time bbt) const; @@ -426,21 +426,25 @@ class LIBARDOUR_API TempoMap : public PBD::StatefulDestructible Timecode::BBT_Time beats_to_bbt (const double& beats); Timecode::BBT_Time pulse_to_bbt (const double& pulse); + double pulse_at_beat (const double& beat) const; + double beat_at_pulse (const double& pulse) const; + PBD::Signal0 MetricPositionChanged; private: - double pulse_at_beat (const Metrics& metrics, const double& beat) const; - double beat_at_pulse (const Metrics& metrics, const double& pulse) const; - double beat_at_frame_locked (const Metrics& metrics, const framecnt_t& frame) const; - framecnt_t frame_at_beat_locked (const Metrics& metrics, const double& beat) const; - double bbt_to_beats_locked (const Metrics& metrics, const Timecode::BBT_Time& bbt) const ; - Timecode::BBT_Time beats_to_bbt_locked (const Metrics& metrics, const double& beats) const; + double pulse_at_beat_locked (const Metrics& metrics, const double& beat) const; + double beat_at_pulse_locked (const Metrics& metrics, const double& pulse) const; double pulse_at_frame_locked (const Metrics& metrics, const framecnt_t& frame) const; framecnt_t frame_at_pulse_locked (const Metrics& metrics, const double& beat) const; - double beat_offset_at (const Metrics& metrics, const double& beat) const; + double pulse_offset_at (const Metrics& metrics, const double& pulse) const; frameoffset_t frame_offset_at (const Metrics& metrics, const framepos_t& frame) const; + double beat_at_frame_locked (const Metrics& metrics, const framecnt_t& frame) const; + framecnt_t frame_at_beat_locked (const Metrics& metrics, const double& beat) const; + double bbt_to_beats_locked (const Metrics& metrics, const Timecode::BBT_Time& bbt) const ; + Timecode::BBT_Time beats_to_bbt_locked (const Metrics& metrics, const double& beats) const; + framepos_t frame_time_locked (const Metrics& metrics, const Timecode::BBT_Time&) const; const MeterSection& meter_section_at_locked (framepos_t frame) const; @@ -476,7 +480,7 @@ private: void do_insert (MetricSection* section); - void add_tempo_locked (const Tempo&, double where, bool recompute, TempoSection::Type type); + void add_tempo_locked (const Tempo&, double pulse, bool recompute, TempoSection::Type type); void add_tempo_locked (const Tempo&, framepos_t frame, bool recompute, TempoSection::Type type); void add_meter_locked (const Meter&, double beat, Timecode::BBT_Time where, bool recompute); diff --git a/libs/ardour/tempo.cc b/libs/ardour/tempo.cc index ee66f4015d..e6c9a829b9 100644 --- a/libs/ardour/tempo.cc +++ b/libs/ardour/tempo.cc @@ -715,7 +715,7 @@ TempoMap::do_insert (MetricSection* section) corrected.first = bbt_to_beats_locked (_metrics, corrected.second); warning << string_compose (_("Meter changes can only be positioned on the first beat of a bar. Moving from %1 to %2"), m->bbt(), corrected.second) << endmsg; - m->set_pulse (corrected); + //m->set_pulse (corrected); } } @@ -822,14 +822,14 @@ TempoMap::do_insert (MetricSection* section) } void -TempoMap::replace_tempo (const TempoSection& ts, const Tempo& tempo, const double& where, TempoSection::Type type) +TempoMap::replace_tempo (const TempoSection& ts, const Tempo& tempo, const double& pulse, TempoSection::Type type) { { Glib::Threads::RWLock::WriterLock lm (lock); TempoSection& first (first_tempo()); if (ts.pulse() != first.pulse()) { remove_tempo_locked (ts); - add_tempo_locked (tempo, where, true, type); + add_tempo_locked (tempo, pulse, true, type); } else { first.set_type (type); { @@ -865,11 +865,11 @@ TempoMap::replace_tempo (const TempoSection& ts, const Tempo& tempo, const frame } void -TempoMap::add_tempo (const Tempo& tempo, const double& where, ARDOUR::TempoSection::Type type) +TempoMap::add_tempo (const Tempo& tempo, const double& pulse, ARDOUR::TempoSection::Type type) { { Glib::Threads::RWLock::WriterLock lm (lock); - add_tempo_locked (tempo, where, true, type); + add_tempo_locked (tempo, pulse, true, type); } PropertyChanged (PropertyChange ()); @@ -888,9 +888,8 @@ TempoMap::add_tempo (const Tempo& tempo, const framepos_t& frame, ARDOUR::TempoS } void -TempoMap::add_tempo_locked (const Tempo& tempo, double where, bool recompute, ARDOUR::TempoSection::Type type) +TempoMap::add_tempo_locked (const Tempo& tempo, double pulse, bool recompute, ARDOUR::TempoSection::Type type) { - double pulse = pulse_at_beat (_metrics, where); TempoSection* ts = new TempoSection (pulse, tempo.beats_per_minute(), tempo.note_type(), type); do_insert (ts); @@ -1007,7 +1006,7 @@ TempoMap::add_meter_locked (const Meter& meter, double beat, BBT_Time where, boo } /* new meters *always* start on a beat. */ where.ticks = 0; - double pulse = pulse_at_beat (_metrics, beat); + double pulse = pulse_at_beat_locked (_metrics, beat); MeterSection* new_meter = new MeterSection (pulse, where, meter.divisions_per_bar(), meter.note_divisor()); do_insert (new_meter); @@ -1024,7 +1023,7 @@ TempoMap::add_meter_locked (const Meter& meter, framepos_t frame, bool recompute MeterSection* new_meter = new MeterSection (frame, meter.divisions_per_bar(), meter.note_divisor()); double paf = pulse_at_frame_locked (_metrics, frame); - pair beat = make_pair (paf, beats_to_bbt_locked (_metrics, beat_at_pulse (_metrics, paf))); + pair beat = make_pair (paf, beats_to_bbt_locked (_metrics, beat_at_pulse_locked (_metrics, paf))); new_meter->set_pulse (beat); do_insert (new_meter); @@ -1050,7 +1049,7 @@ TempoMap::predict_tempo_frame (TempoSection* section, const Tempo& bpm, const BB framepos_t ret = 0; TempoSection* new_section = copy_metrics_and_point (future_map, section); double const beat = bbt_to_beats_locked (future_map, bbt); - if (solve_map (future_map, new_section, bpm, pulse_at_beat (future_map, beat))) { + if (solve_map (future_map, new_section, bpm, pulse_at_beat_locked (future_map, beat))) { ret = new_section->frame(); } else { ret = frame_at_beat_locked (_metrics, beat); @@ -1065,7 +1064,7 @@ TempoMap::predict_tempo_frame (TempoSection* section, const Tempo& bpm, const BB } double -TempoMap::predict_tempo_beat (TempoSection* section, const Tempo& bpm, const framepos_t& frame) +TempoMap::predict_tempo_pulse (TempoSection* section, const Tempo& bpm, const framepos_t& frame) { Glib::Threads::RWLock::ReaderLock lm (lock); Metrics future_map; @@ -1073,9 +1072,9 @@ TempoMap::predict_tempo_beat (TempoSection* section, const Tempo& bpm, const fra TempoSection* new_section = copy_metrics_and_point (future_map, section); if (solve_map (future_map, new_section, bpm, frame)) { - ret = beat_at_pulse (future_map, new_section->pulse()); + ret = new_section->pulse(); } else { - ret = beat_at_frame_locked (_metrics, frame); + ret = pulse_at_frame_locked (_metrics, frame); } Metrics::const_iterator d = future_map.begin(); @@ -1114,7 +1113,7 @@ TempoMap::gui_move_tempo_beat (TempoSection* ts, const Tempo& bpm, const double { Glib::Threads::RWLock::WriterLock lm (lock); TempoSection* new_section = copy_metrics_and_point (future_map, ts); - if (solve_map (future_map, new_section, bpm, pulse_at_beat (future_map, beat))) { + if (solve_map (future_map, new_section, bpm, pulse_at_beat_locked (future_map, beat))) { solve_map (_metrics, ts, bpm, beat); } } @@ -1144,7 +1143,7 @@ TempoMap::gui_move_meter (MeterSection* ms, const Meter& mt, const double& beat { { Glib::Threads::RWLock::WriterLock lm (lock); - solve_map (_metrics, ms, mt, pulse_at_beat (_metrics, beat)); + solve_map (_metrics, ms, mt, pulse_at_beat_locked (_metrics, beat)); } MetricPositionChanged (); // Emit Signal @@ -1388,7 +1387,7 @@ TempoMap::recompute_meters (Metrics& metrics) if (meter->position_lock_style() == AudioTime) { pair pr; - pr.first = pulse_at_frame_locked (metrics, meter->frame()); + 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); @@ -1429,7 +1428,14 @@ TempoMap::recompute_map (Metrics& metrics, framepos_t end) } double -TempoMap::pulse_at_beat (const Metrics& metrics, const double& beat) const +TempoMap::pulse_at_beat (const double& beat) const +{ + Glib::Threads::RWLock::ReaderLock lm (lock); + return pulse_at_beat_locked (_metrics, beat); +} + +double +TempoMap::pulse_at_beat_locked (const Metrics& metrics, const double& beat) const { MeterSection* prev_ms = 0; double accumulated_beats = 0.0; @@ -1450,11 +1456,17 @@ TempoMap::pulse_at_beat (const Metrics& metrics, const double& beat) const } double -TempoMap::beat_at_pulse (const Metrics& metrics, const double& pulse) const +TempoMap::beat_at_pulse (const double& pulse) const +{ + Glib::Threads::RWLock::ReaderLock lm (lock); + return beat_at_pulse_locked (_metrics, pulse); +} + +double +TempoMap::beat_at_pulse_locked (const Metrics& metrics, const double& pulse) const { MeterSection* prev_ms = 0; double accumulated_beats = 0.0; - for (Metrics::const_iterator i = metrics.begin(); i != metrics.end(); ++i) { MeterSection* m; if ((m = dynamic_cast (*i)) != 0) { @@ -1543,7 +1555,7 @@ TempoMap::bbt_time (framepos_t frame, BBT_Time& bbt) } Glib::Threads::RWLock::ReaderLock lm (lock); frameoffset_t const frame_off = frame_offset_at (_metrics, frame); - double const beat = beat_at_pulse (_metrics, pulse_at_frame_locked (_metrics, frame + frame_off)); + double const beat = beat_at_pulse_locked (_metrics, pulse_at_frame_locked (_metrics, frame + frame_off)); bbt = beats_to_bbt_locked (_metrics, beat); } @@ -1727,7 +1739,7 @@ TempoMap::beat_at_frame_locked (const Metrics& metrics, const framecnt_t& frame) framecnt_t const offset_frame = frame + frame_offset_at (metrics, frame); double const pulse = pulse_at_frame_locked (metrics, offset_frame); - return beat_at_pulse (metrics, pulse); + return beat_at_pulse_locked (metrics, pulse); } double @@ -1741,12 +1753,10 @@ TempoMap::pulse_at_frame_locked (const Metrics& metrics, const framecnt_t& frame TempoSection* t; if ((t = dynamic_cast (*i)) != 0) { - if (prev_ts) { - if (t->frame() > frame) { - /*the previous ts is the one containing the frame */ - double const ret = prev_ts->pulse_at_frame (frame, _frame_rate); - return ret; - } + if (prev_ts && t->frame() > frame) { + /*the previous ts is the one containing the frame */ + double const ret = prev_ts->pulse_at_frame (frame, _frame_rate); + return ret; } accumulated_pulses = t->pulse(); prev_ts = t; @@ -1769,7 +1779,7 @@ TempoMap::frame_at_beat (const double& beat) const framecnt_t TempoMap::frame_at_beat_locked (const Metrics& metrics, const double& beat) const { - framecnt_t const frame = frame_at_pulse_locked (metrics, pulse_at_beat (metrics, beat)); + framecnt_t const frame = frame_at_pulse_locked (metrics, pulse_at_beat_locked (metrics, beat)); frameoffset_t const frame_off = frame_offset_at (metrics, frame); return frame - frame_off; } @@ -1805,28 +1815,28 @@ TempoMap::frame_at_pulse_locked (const Metrics& metrics, const double& pulse) co } double -TempoMap::beat_offset_at (const Metrics& metrics, const double& beat) const +TempoMap::pulse_offset_at (const Metrics& metrics, const double& pulse) const { MeterSection* prev_m = 0; - double beat_off = 0.0; + double pulse_off = first_meter().pulse(); 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) { + if (m->pulse() > pulse) { 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()); + pulse_off += (m->pulse() - prev_m->pulse()) - floor (m->pulse() - prev_m->pulse()); } } prev_m = m; } } - return beat_off; + return pulse_off; } frameoffset_t @@ -1871,7 +1881,7 @@ TempoMap::frame_time_locked (const Metrics& metrics, const BBT_Time& bbt) const { /* HOLD THE READER LOCK */ - framepos_t const ret = frame_at_pulse_locked (metrics, pulse_at_beat (metrics, bbt_to_beats_locked (metrics, bbt))); + framepos_t const ret = frame_at_pulse_locked (metrics, pulse_at_beat_locked (metrics, bbt_to_beats_locked (metrics, bbt))); return ret; } @@ -1891,6 +1901,7 @@ 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 << @@ -1898,6 +1909,7 @@ 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; } @@ -2441,7 +2453,7 @@ const Tempo TempoMap::tempo_at (const framepos_t& frame) const { Glib::Threads::RWLock::ReaderLock lm (lock); - frameoffset_t const frame_off = frame_offset_at (_metrics, frame); + //frameoffset_t const frame_off = frame_offset_at (_metrics, frame); TempoSection* prev_ts = 0; Metrics::const_iterator i; @@ -2475,7 +2487,7 @@ TempoMap::meter_section_at (framepos_t frame) const const MeterSection& TempoMap::meter_section_at_locked (framepos_t frame) const { - framepos_t const frame_off = frame + frame_offset_at (_metrics, frame); + //framepos_t const frame_off = frame + frame_offset_at (_metrics, frame); Metrics::const_iterator i; MeterSection* prev = 0; @@ -2636,7 +2648,7 @@ TempoMap::set_state (const XMLNode& node, int /*version*/) } void -TempoMap::dump (Metrics& metrics, std::ostream& o) const +TempoMap::dump (const Metrics& metrics, std::ostream& o) const { Glib::Threads::RWLock::ReaderLock lm (lock, Glib::Threads::TRY_LOCK); const MeterSection* m; -- cgit v1.2.3