From: nick_m Date: Tue, 29 Dec 2015 13:39:10 +0000 (+1100) Subject: Tempo ramps - update midi regions and locations when dragging tempo. X-Git-Tag: 5.0-pre0~546 X-Git-Url: https://main.carlh.net/gitweb/?a=commitdiff_plain;ds=sidebyside;h=885f1fd684da31a730f90ebad23ad9ff39baedb0;p=ardour.git Tempo ramps - update midi regions and locations when dragging tempo. - also make locations and regions use a double beat rather than bbt for musical position. --- diff --git a/gtk2_ardour/midi_region_view.cc b/gtk2_ardour/midi_region_view.cc index 961ab147c1..61e9dea9d7 100644 --- a/gtk2_ardour/midi_region_view.cc +++ b/gtk2_ardour/midi_region_view.cc @@ -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::iterator i = ghosts.begin(); i != ghosts.end(); ++i) { diff --git a/libs/ardour/ardour/location.h b/libs/ardour/ardour/location.h index 530f757c65..d31e9dccce 100644 --- a/libs/ardour/ardour/location.h +++ b/libs/ardour/ardour/location.h @@ -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; diff --git a/libs/ardour/ardour/region.h b/libs/ardour/ardour/region.h index 6839340fee..383bc6675d 100644 --- a/libs/ardour/ardour/region.h +++ b/libs/ardour/ardour/region.h @@ -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 (); diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 1a4ddeb562..8d6dabd331 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -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 */ diff --git a/libs/ardour/location.cc b/libs/ardour/location.cc index 0820660db6..d827d0f2b6 100644 --- a/libs/ardour/location.cc +++ b/libs/ardour/location.cc @@ -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 diff --git a/libs/ardour/region.cc b/libs/ardour/region.cc index ee666e51f0..8db3aa097a 100644 --- a/libs/ardour/region.cc +++ b/libs/ardour/region.cc @@ -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; } } diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index 4097335f5b..e9bbaa5c4a 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -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) { diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index 7bc9dfdeeb..11b28a1e76 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -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 */ diff --git a/libs/ardour/tempo.cc b/libs/ardour/tempo.cc index 1715aadf06..eebd47ab89 100644 --- a/libs/ardour/tempo.cc +++ b/libs/ardour/tempo.cc @@ -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 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 (*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;