Tempo ramps - update midi regions and locations when dragging tempo.
authornick_m <mainsbridge@gmail.com>
Tue, 29 Dec 2015 13:39:10 +0000 (00:39 +1100)
committernick_m <mainsbridge@gmail.com>
Fri, 27 May 2016 13:38:10 +0000 (23:38 +1000)
- also make locations and regions use a double beat rather than bbt for musical position.

gtk2_ardour/midi_region_view.cc
libs/ardour/ardour/location.h
libs/ardour/ardour/region.h
libs/ardour/ardour/session.h
libs/ardour/location.cc
libs/ardour/region.cc
libs/ardour/session.cc
libs/ardour/session_state.cc
libs/ardour/tempo.cc

index 961ab147c11d064ab9960747afdc00373f7292e8..61e9dea9d7a23fe72529f6852147a0c89dc4ce9b 100644 (file)
@@ -1742,8 +1742,8 @@ MidiRegionView::update_sustained (Note* ev, bool update_ghost_regions)
        }
 
        // Update color in case velocity has changed
-       ev->set_fill_color(ev->base_color());
-       ev->set_outline_color(ev->calculate_outline(ev->base_color(), ev->selected()));
+       //ev->set_fill_color(ev->base_color());
+       //ev->set_outline_color(ev->calculate_outline(ev->base_color(), ev->selected()));
 
        if (update_ghost_regions) {
                for (std::vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
index 530f757c65fa38be1a58f9412148c0961800480e..d31e9dccceb11b8528e87a315492be4ed584dcb5 100644 (file)
@@ -151,9 +151,9 @@ class LIBARDOUR_API Location : public SessionHandleRef, public PBD::StatefulDest
   private:
        std::string        _name;
        framepos_t         _start;
-       Timecode::BBT_Time _bbt_start;
+       double             _bbt_start;
        framepos_t         _end;
-       Timecode::BBT_Time _bbt_end;
+       double             _bbt_end;
        Flags              _flags;
        bool               _locked;
        PositionLockStyle  _position_lock_style;
index 6839340feea47ce12a355ddf715f5386fd59e4c5..383bc6675d2e600476c4e12d2d027e3972437f85 100644 (file)
@@ -27,7 +27,6 @@
 
 #include "pbd/undo.h"
 #include "pbd/signals.h"
-
 #include "ardour/ardour.h"
 #include "ardour/data_type.h"
 #include "ardour/automatable.h"
@@ -429,7 +428,7 @@ class LIBARDOUR_API Region
        framecnt_t              _last_length;
        framepos_t              _last_position;
        mutable RegionEditState _first_edit;
-       Timecode::BBT_Time      _bbt_time;
+       double                  _beat;
        layer_t                 _layer;
 
        void register_properties ();
index 1a4ddeb5625aeb5ef3f32625a2c65fb670232472..8d6dabd33100d9293b74408efd1bbe8761c71502 100644 (file)
@@ -1640,6 +1640,7 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
 
        TempoMap    *_tempo_map;
        void          tempo_map_changed (const PBD::PropertyChange&);
+       void          gui_tempo_map_changed ();
 
        /* edit/mix groups */
 
index 0820660db6cf201d978e42ab3ca361303686bf42..d827d0f2b606dfccd064c90c8771861795c84fb6 100644 (file)
@@ -207,8 +207,8 @@ Location::set_start (framepos_t s, bool force, bool allow_bbt_recompute)
 
                        start_changed (this); /* EMIT SIGNAL */
                        StartChanged (); /* EMIT SIGNAL */
-                       end_changed (this); /* EMIT SIGNAL */
-                       EndChanged (); /* EMIT SIGNAL */
+                       //end_changed (this); /* EMIT SIGNAL */
+                       //EndChanged (); /* EMIT SIGNAL */
                }
 
                /* moving the start (position) of a marker with a scene change
@@ -281,8 +281,8 @@ Location::set_end (framepos_t e, bool force, bool allow_bbt_recompute)
                        if (allow_bbt_recompute) {
                                recompute_bbt_from_frames ();
                        }
-                       start_changed (this); /* EMIT SIGNAL */
-                       StartChanged (); /* EMIT SIGNAL */
+                       //start_changed (this); /* EMIT SIGNAL */
+                       //StartChanged (); /* EMIT SIGNAL */
                        end_changed (this); /* EMIT SIGNAL */
                        EndChanged (); /* EMIT SIGNAL */
                }
@@ -396,21 +396,17 @@ Location::set (framepos_t s, framepos_t e, bool allow_bbt_recompute)
                assert (_end >= 0);
        }
 
-       if (start_change) {
+       if (start_change && end_change) {
+               changed (this);
+               Changed ();
+       } else if (start_change) {
                start_changed(this); /* EMIT SIGNAL */
                StartChanged(); /* EMIT SIGNAL */
-       }
-
-       if (end_change) {
+       } else if (end_change) {
                end_changed(this); /* EMIT SIGNAL */
                EndChanged(); /* EMIT SIGNAL */
        }
 
-       if (start_change && end_change) {
-               changed (this);
-               Changed ();
-       }
-
        return 0;
 }
 
@@ -726,8 +722,8 @@ Location::recompute_bbt_from_frames ()
                return;
        }
 
-       _session.bbt_time (_start, _bbt_start);
-       _session.bbt_time (_end, _bbt_end);
+       _bbt_start = _session.tempo_map().beat_at_frame (_start);
+       _bbt_end = _session.tempo_map().beat_at_frame (_end);
 }
 
 void
@@ -738,7 +734,7 @@ Location::recompute_frames_from_bbt ()
        }
 
        TempoMap& map (_session.tempo_map());
-       set (map.frame_time (_bbt_start), map.frame_time (_bbt_end), false);
+       set (map.frame_at_beat (_bbt_start), map.frame_at_beat (_bbt_end), false);
 }
 
 void
index ee666e51f02db0bb5a77f1eeb77cb1b64af7e6d3..8db3aa097a8e821134ba70a1344960c440847b04 100644 (file)
@@ -538,7 +538,7 @@ Region::set_position_lock_style (PositionLockStyle ps)
                _position_lock_style = ps;
 
                if (_position_lock_style == MusicTime) {
-                       _session.bbt_time (_position, _bbt_time);
+                       _beat = _session.tempo_map().beat_at_frame (_position);
                }
 
                send_change (Properties::position_lock_style);
@@ -553,9 +553,8 @@ Region::update_after_tempo_map_change ()
        if (!pl || _position_lock_style != MusicTime) {
                return;
        }
-
        TempoMap& map (_session.tempo_map());
-       framepos_t pos = map.frame_time (_bbt_time);
+       framepos_t pos = map.frame_at_beat (_beat);
        set_position_internal (pos, false);
 
        /* do this even if the position is the same. this helps out
@@ -651,7 +650,7 @@ void
 Region::recompute_position_from_lock_style ()
 {
        if (_position_lock_style == MusicTime) {
-               _session.bbt_time (_position, _bbt_time);
+               _beat = _session.tempo_map().beat_at_frame (_position);
        }
 }
 
@@ -1199,8 +1198,8 @@ Region::state ()
 
        if (_position_lock_style != AudioTime) {
                stringstream str;
-               str << _bbt_time;
-               node->add_property ("bbt-position", str.str());
+               str << _beat;
+               node->add_property ("beat", str.str());
        }
 
        for (uint32_t n=0; n < _sources.size(); ++n) {
@@ -1261,6 +1260,7 @@ int
 Region::_set_state (const XMLNode& node, int /*version*/, PropertyChange& what_changed, bool send)
 {
        XMLProperty const * prop;
+       Timecode::BBT_Time bbt_time;
 
        Stateful::save_extra_xml (node);
 
@@ -1274,9 +1274,21 @@ Region::_set_state (const XMLNode& node, int /*version*/, PropertyChange& what_c
                        _position_lock_style = AudioTime;
                } else {
                        if (sscanf (prop->value().c_str(), "%d|%d|%d",
-                                   &_bbt_time.bars,
-                                   &_bbt_time.beats,
-                                   &_bbt_time.ticks) != 3) {
+                                   &bbt_time.bars,
+                                   &bbt_time.beats,
+                                   &bbt_time.ticks) != 3) {
+                               _position_lock_style = AudioTime;
+                       }
+                       _beat = _session.tempo_map().bbt_to_beats (bbt_time);
+               }
+       }
+
+       if (_position_lock_style == MusicTime) {
+               if ((prop = node.property ("beat")) == 0) {
+                       /* missing BBT info, revert to audio time locking */
+                       _position_lock_style = AudioTime;
+               } else {
+                       if (sscanf (prop->value().c_str(), "%lf", &_beat) != 1) {
                                _position_lock_style = AudioTime;
                        }
                }
index 4097335f5b811138e035e9f654f89cdc4523fec3..e9bbaa5c4a06f2421ae258bef10bfe3f6b534665 100644 (file)
@@ -5437,6 +5437,16 @@ Session::tempo_map_changed (const PropertyChange&)
        set_dirty ();
 }
 
+void
+Session::gui_tempo_map_changed ()
+{
+       //clear_clicks (); ?
+
+       playlists->update_after_tempo_map_change ();
+
+       _locations->apply (*this, &Session::update_locations_after_tempo_map_change);
+}
+
 void
 Session::update_locations_after_tempo_map_change (const Locations::LocationList& loc)
 {
index 7bc9dfdeeb90b276864c12016122f5ae1afc365c..11b28a1e76f8b99378e967ccbda55b0b83365534 100644 (file)
@@ -248,6 +248,7 @@ Session::post_engine_init ()
                delete _tempo_map;
                _tempo_map = new TempoMap (_current_frame_rate);
                _tempo_map->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1));
+               _tempo_map->MetricPositionChanged.connect_same_thread (*this, boost::bind (&Session::gui_tempo_map_changed, this));
 
                /* MidiClock requires a tempo map */
 
index 1715aadf061760c174ff6067cba156118cf8f594..eebd47ab89e7d67e28f60decf67fb6f9fe90c7da 100644 (file)
@@ -434,7 +434,7 @@ MeterSection::get_state() const
                  bbt().beats,
                  bbt().ticks);
        root->add_property ("bbt", buf);
-       snprintf (buf, sizeof (buf), "%f", start());
+       snprintf (buf, sizeof (buf), "%lf", start());
        root->add_property ("start", buf);
        snprintf (buf, sizeof (buf), "%f", _note_type);
        root->add_property ("note-type", buf);
@@ -469,7 +469,7 @@ TempoMap::TempoMap (framecnt_t fr)
        start.beats = 1;
        start.ticks = 0;
 
-       TempoSection *t = new TempoSection (0.0, _default_tempo.beats_per_minute(), _default_tempo.note_type(), TempoSection::Type::Ramp);
+       TempoSection *t = new TempoSection (0.0, _default_tempo.beats_per_minute(), _default_tempo.note_type(), TempoSection::Type::Constant);
        MeterSection *m = new MeterSection (0.0, start, _default_meter.divisions_per_bar(), _default_meter.note_divisor());
 
        t->set_movable (false);
@@ -583,7 +583,7 @@ TempoMap::do_insert (MetricSection* section)
                        pair<double, BBT_Time> corrected = make_pair (m->start(), m->bbt());
                        corrected.second.beats = 1;
                        corrected.second.ticks = 0;
-
+                       corrected.first = bbt_to_beats (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_start (corrected);
@@ -1255,9 +1255,10 @@ TempoMap::beats_to_bbt (double beats)
 double
 TempoMap::tick_at_frame (framecnt_t frame) const
 {
+       /* HOLD (at least) THE READER LOCK */
 
        Metrics::const_iterator i;
-       const TempoSection* prev_ts = 0;
+       TempoSection* prev_ts = 0;
        double accumulated_ticks = 0.0;
 
        for (i = metrics.begin(); i != metrics.end(); ++i) {
@@ -1268,27 +1269,24 @@ TempoMap::tick_at_frame (framecnt_t frame) const
                        if ((prev_ts) && frame < t->frame()) {
                                /*the previous ts is the one containing the frame */
 
-                               framepos_t time = frame - prev_ts->frame();
-                               framepos_t last_frame = t->frame() - prev_ts->frame();
-                               double last_beats_per_minute = t->beats_per_minute();
+                               framepos_t const time = frame - prev_ts->frame();
+                               framepos_t const last_frame = t->frame() - prev_ts->frame();
+                               double const last_beats_per_minute = t->beats_per_minute();
 
                                return prev_ts->tick_at_frame (time, last_beats_per_minute, last_frame, _frame_rate) + accumulated_ticks;
                        }
 
                        if (prev_ts && t->frame() > prev_ts->frame()) {
-                               framepos_t time = t->frame() - prev_ts->frame();
-                               framepos_t last_frame = t->frame() - prev_ts->frame();
-                               double last_beats_per_minute = t->beats_per_minute();
-                               accumulated_ticks += prev_ts->tick_at_frame (time, last_beats_per_minute, last_frame, _frame_rate);
+                               accumulated_ticks = t->beat() * BBT_Time::ticks_per_beat;
                        }
 
                        prev_ts = t;
                }
        }
 
-       /* treated s linear for this ts */
-       framecnt_t frames_in_section = frame - prev_ts->frame();
-       double ticks_in_section = (frames_in_section / prev_ts->frames_per_beat (_frame_rate)) * Timecode::BBT_Time::ticks_per_beat;
+       /* treated as constant for this ts */
+       framecnt_t const frames_in_section = frame - prev_ts->frame();
+       double const ticks_in_section = (frames_in_section / prev_ts->frames_per_beat (_frame_rate)) * Timecode::BBT_Time::ticks_per_beat;
 
        return ticks_in_section + accumulated_ticks;
 
@@ -1310,28 +1308,26 @@ TempoMap::frame_at_tick (double tick) const
                if ((t = dynamic_cast<TempoSection*> (*i)) != 0) {
 
                        if (prev_ts && t->frame() > prev_ts->frame()) {
-                               framepos_t const time = t->frame() - prev_ts->frame();
-                               framepos_t const last_time = t->frame() - prev_ts->frame();
-                               double const last_beats_per_minute = t->beats_per_minute();
-                               accumulated_ticks += prev_ts->tick_at_frame (time, last_beats_per_minute, last_time, _frame_rate);
+                               accumulated_ticks = t->beat() * BBT_Time::ticks_per_beat;
                        }
 
                        if (prev_ts && tick < accumulated_ticks) {
                                /* prev_ts is the one affecting us. */
 
                                double const ticks_in_section = tick - accumulated_ticks_to_prev;
-                               framepos_t const section_start = prev_ts->frame();
                                framepos_t const last_time = t->frame() - prev_ts->frame();
                                double const last_beats_per_minute = t->beats_per_minute();
 
-                               return prev_ts->frame_at_tick (ticks_in_section, last_beats_per_minute, last_time, _frame_rate) + section_start;
+                               return prev_ts->frame_at_tick (ticks_in_section, last_beats_per_minute, last_time, _frame_rate) + prev_ts->frame();
                        }
                        accumulated_ticks_to_prev = accumulated_ticks;
                        prev_ts = t;
                }
        }
+       /* must be treated as constant, irrespective of _type */
        double const ticks_in_section = tick - accumulated_ticks_to_prev;
-       double const dtime = (ticks_in_section / BBT_Time::ticks_per_beat) * prev_ts->frames_per_beat(_frame_rate);
+       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();
 
        return ret;