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:
parent
772683d2df
commit
885f1fd684
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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 ();
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user