Tempo ramps - setting bbt of an audio-locked tempo marker in the tempo dialog works.
authornick_m <mainsbridge@gmail.com>
Mon, 29 Feb 2016 16:59:32 +0000 (03:59 +1100)
committernick_m <mainsbridge@gmail.com>
Fri, 27 May 2016 13:38:10 +0000 (23:38 +1000)
gtk2_ardour/editor_tempodisplay.cc
libs/ardour/ardour/tempo.h
libs/ardour/tempo.cc

index 95fb178421a6f43109f3856c05e2b41da1b8c05f..a971e98abe5407e7adc1a15b4ec88e9d62ba78a9 100644 (file)
@@ -378,8 +378,7 @@ Editor::edit_tempo_section (TempoSection* section)
        if (tempo_dialog.get_lock_style() == MusicTime) {
                _session->tempo_map().replace_tempo (*section, Tempo (bpm, nt), beat, tempo_dialog.get_tempo_type());
        } else {
-               _session->tempo_map().replace_c_func_from_tempo_and_beat (bpm, beat);
-               framepos_t const f = _session->tempo_map().frame_at_beat (beat);
+               framepos_t const f = _session->tempo_map().compute_replacement_tempo_section (section, bpm, beat);
                _session->tempo_map().replace_tempo (*section, Tempo (bpm, nt), f, tempo_dialog.get_tempo_type());
        }
        XMLNode &after = _session->tempo_map().get_state();
index 6ce59ffbeab9ba74ce0412ac83ba8dc517531153..d1ee1090bcce65513a439027f87a2e83d09cea22 100644 (file)
@@ -371,7 +371,7 @@ class LIBARDOUR_API TempoMap : public PBD::StatefulDestructible
        void remove_tempo (const TempoSection&, bool send_signal);
        void remove_meter (const MeterSection&, bool send_signal);
 
-       void replace_c_func_from_tempo_and_beat (const double& tempo, const double& beat);
+       framepos_t compute_replacement_tempo_section (TempoSection* section, const double& tempo, const double& beat);
        void replace_tempo (const TempoSection&, const Tempo&, const double& where, TempoSection::Type type);
        void replace_tempo (const TempoSection&, const Tempo&, const framepos_t& where, TempoSection::Type type);
 
index da22da4bd22fa45844dd6ca73571cb44a511a296..15d88b01c975f2201650743594061cbcad4f06b4 100644 (file)
@@ -824,33 +824,87 @@ TempoMap::do_insert (MetricSection* section)
        }
 }
 
-/*
-This is for a gui who needs to know the frame of a beat if a proposed tempo section were to be placed there.
-You probably shouldn't use this unless you know what you're doing,
-as it doesn't recompute the tempo map and will make a ramp invalid intil that next happens.
-It is assumed that the next frame calculation is the last time you need this c_func before the next do_insert() and/or recompute_map().
+/**
+* This is for a gui that needs to know the frame of a beat if a tempo section were to be moved or altered.
+* It actually alters tha ramps up to the beat parameter, so calling this commits you to replacing the section immediately.
+* It will not emit a signal or recompute the map, as you probably want to replace the tempo or do somethig else before that happens.
+* @param section - the section you want to alter
+* @param bpm - the new tempo
+* @param beat - the beat where the altered tempo will fall
+* @return returns - the position in frames where the new tempo section will lie
 */
-void
-TempoMap::replace_c_func_from_tempo_and_beat (const double& bpm, const double& beat)
+framepos_t
+TempoMap::compute_replacement_tempo_section (TempoSection* section, const double& bpm, const double& beat)
 {
-       Glib::Threads::RWLock::WriterLock lm (lock);
        TempoSection* prev_ts = 0;
        TempoSection* t;
+       framepos_t ret = 0;
+       MetricSectionSorter cmp;
+
+       Glib::Threads::RWLock::WriterLock lm (lock);
 
        for (Metrics::iterator i = metrics.begin(); i != metrics.end(); ++i) {
                if ((t = dynamic_cast<TempoSection*> (*i)) != 0) {
                        if (prev_ts) {
-                               prev_ts->set_c_func_from_tempo_and_beat (bpm, beat, _frame_rate);
+                               if (section->beat() == t->beat()) {
+                                       continue;
+                               }
+                               if (beat < t->beat()){
+                                       prev_ts->set_c_func_from_tempo_and_beat (bpm, beat, _frame_rate);
+                                       section->set_beat (beat);
+                                       section->set_frame (prev_ts->frame_at_beat (beat, _frame_rate));
+                                       break;
+                               }
+
+                               if (t->position_lock_style() == MusicTime) {
+                                       prev_ts->set_c_func_from_tempo_and_beat (t->beats_per_minute(), t->beat(), _frame_rate);
+                                       t->set_frame (prev_ts->frame_at_beat (t->beat(), _frame_rate));
+                               } else {
+                                       prev_ts->set_c_func (prev_ts->compute_c_func (t->beats_per_minute(), t->frame(), _frame_rate));
+                                       t->set_beat (prev_ts->beat_at_frame (t->frame(), _frame_rate));
+                               }
+                       }
+                       prev_ts = t;
+               }
+       }
+       /* now we do the whole thing again because audio-locked sections will have caused a re-order */
+       prev_ts = 0;
+       metrics.sort (cmp);
 
-                               if (beat < t->beat()) {
-                                       return;
+       for (Metrics::iterator i = metrics.begin(); i != metrics.end(); ++i) {
+               if ((t = dynamic_cast<TempoSection*> (*i)) != 0) {
+                       if (prev_ts) {
+                               if (section->beat() == t->beat()) {
+                                       continue;
+                               }
+                               if (beat < t->beat()){
+                                       prev_ts->set_c_func_from_tempo_and_beat (bpm, beat, _frame_rate);
+                                       ret = prev_ts->frame_at_beat (beat, _frame_rate);
+                                       section->set_frame (ret);
+                                       prev_ts = section;
+                                       break;
+                               }
+                               if (t->position_lock_style() == MusicTime) {
+                                       prev_ts->set_c_func_from_tempo_and_beat (t->beats_per_minute(), t->beat(), _frame_rate);
+                                       t->set_frame (prev_ts->frame_at_beat (t->beat(), _frame_rate));
+                               } else {
+                                       prev_ts->set_c_func (prev_ts->compute_c_func (t->beats_per_minute(), t->frame(), _frame_rate));
+                                       t->set_beat (prev_ts->beat_at_frame (t->frame(), _frame_rate));
                                }
                        }
                        prev_ts = t;
                }
        }
-       /* there is always at least one tempo section */
-       prev_ts->set_c_func_from_tempo_and_beat (bpm, beat, _frame_rate);
+
+       if (!ret) {
+               prev_ts->set_c_func_from_tempo_and_beat (bpm, beat, _frame_rate);
+               section->set_beat (beat);
+               section->set_frame (prev_ts->frame_at_beat (beat, _frame_rate));
+
+               ret = prev_ts->frame_at_beat (beat, _frame_rate);
+       }
+
+       return ret;
 }
 
 void