13
0

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.
This commit is contained in:
nick_m 2015-12-30 00:39:10 +11:00
parent 772683d2df
commit 885f1fd684
9 changed files with 68 additions and 53 deletions

View 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) {

View 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;

View 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 ();

View 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 */

View 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,19 +396,15 @@ Location::set (framepos_t s, framepos_t e, bool allow_bbt_recompute)
assert (_end >= 0);
}
if (start_change) {
start_changed(this); /* EMIT SIGNAL */
StartChanged(); /* EMIT SIGNAL */
}
if (end_change) {
end_changed(this); /* EMIT SIGNAL */
EndChanged(); /* EMIT SIGNAL */
}
if (start_change && end_change) {
changed (this);
Changed ();
} else if (start_change) {
start_changed(this); /* EMIT SIGNAL */
StartChanged(); /* EMIT SIGNAL */
} else if (end_change) {
end_changed(this); /* EMIT SIGNAL */
EndChanged(); /* EMIT SIGNAL */
}
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

View 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;
}
}

View 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)
{

View 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 */

View 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;