Tempo ramps - music-locked meters now use beats rather than pulses as their reference.

- fixes many problems with a non-zero audio-locked first meter.
This commit is contained in:
nick_m 2016-03-23 01:11:00 +11:00
parent ba3ae54f51
commit 58d4889ad3
5 changed files with 72 additions and 57 deletions

View file

@ -3182,7 +3182,7 @@ MeterMarkerDrag::motion (GdkEvent* event, bool first_move)
_marker->hide();
}
framepos_t const pf = adjusted_current_frame (event);
framepos_t const pf = adjusted_current_frame (event, false);
_marker->set_position (pf);
if (_marker->meter().position_lock_style() == MusicTime) {
double const baf = _editor->session()->tempo_map().beat_at_frame (_editor->session()->tempo_map().round_to_bar (pf, (RoundMode) 0));
@ -3366,8 +3366,8 @@ TempoMarkerDrag::finished (GdkEvent* event, bool movement_occurred)
XMLNode &before = map.get_state();
if (_marker->tempo().position_lock_style() == MusicTime) {
double const beat = map.predict_tempo_beat (_real_section, _marker->tempo(), _real_section->frame());
map.add_tempo (_marker->tempo(), beat, _marker->tempo().type());
double const pulse = map.predict_tempo_pulse (_real_section, _marker->tempo(), _real_section->frame());
map.add_tempo (_marker->tempo(), pulse, _marker->tempo().type());
} else {
map.add_tempo (_marker->tempo(), _real_section->frame(), _marker->tempo().type());
}
@ -3377,11 +3377,10 @@ TempoMarkerDrag::finished (GdkEvent* event, bool movement_occurred)
_editor->commit_reversible_command ();
} else {
/* we removed it before, so add it back now */
if (_marker->tempo().position_lock_style() == MusicTime) {
double const beat = map.predict_tempo_beat (_real_section, _marker->tempo(), _real_section->frame());
double const pulse = map.predict_tempo_pulse (_real_section, _marker->tempo(), _real_section->frame());
map.replace_tempo (*_real_section, Tempo (_marker->tempo().beats_per_minute(), _marker->tempo().note_type())
, beat, _marker->tempo().type());
, pulse, _marker->tempo().type());
} else {
map.replace_tempo (*_real_section, Tempo (_marker->tempo().beats_per_minute(), _marker->tempo().note_type())
, _real_section->frame(), _marker->tempo().type());

View file

@ -6552,7 +6552,7 @@ Editor::define_one_bar (framepos_t start, framepos_t end)
} else if (t.frame() == start) {
_session->tempo_map().change_existing_tempo_at (start, beats_per_minute, t.note_type());
} else {
_session->tempo_map().add_tempo (Tempo (beats_per_minute, t.note_type()), _session->tempo_map().beat_at_frame (start), TempoSection::Constant);
_session->tempo_map().add_tempo (Tempo (beats_per_minute, t.note_type()), start, TempoSection::Constant);
}
XMLNode& after (_session->tempo_map().get_state());

View file

@ -242,7 +242,7 @@ Editor::mouse_add_new_tempo_event (framepos_t frame)
begin_reversible_command (_("add tempo mark"));
XMLNode &before = map.get_state();
if (tempo_dialog.get_lock_style() == MusicTime) {
map.add_tempo (Tempo (bpm,nt), map.bbt_to_beats (requested), tempo_dialog.get_tempo_type());
map.add_tempo (Tempo (bpm,nt), map.pulse_at_beat (map.bbt_to_beats (requested)), tempo_dialog.get_tempo_type());
} else {
map.add_tempo (Tempo (bpm,nt), frame, tempo_dialog.get_tempo_type());
}
@ -373,7 +373,7 @@ Editor::edit_tempo_section (TempoSection* section)
begin_reversible_command (_("replace tempo mark"));
XMLNode &before = _session->tempo_map().get_state();
if (tempo_dialog.get_lock_style() == MusicTime) {
_session->tempo_map().replace_tempo (*section, Tempo (bpm, nt), beat, tempo_dialog.get_tempo_type());
_session->tempo_map().replace_tempo (*section, Tempo (bpm, nt), _session->tempo_map().pulse_at_beat (beat), tempo_dialog.get_tempo_type());
} else {
framepos_t const f = _session->tempo_map().predict_tempo_frame (section, Tempo (bpm, nt), when);
_session->tempo_map().replace_tempo (*section, Tempo (bpm, nt), f, tempo_dialog.get_tempo_type());

View file

@ -365,7 +365,7 @@ class LIBARDOUR_API TempoMap : public PBD::StatefulDestructible
const TempoSection& tempo_section_at (framepos_t frame) const;
const MeterSection& meter_section_at (framepos_t frame) const;
void add_tempo (const Tempo&, const double& beat, TempoSection::Type type);
void add_tempo (const Tempo&, const double& pulse, TempoSection::Type type);
void add_tempo (const Tempo&, const framepos_t& frame, TempoSection::Type type);
void add_meter (const Meter&, const double& beat, const Timecode::BBT_Time& where);
@ -375,7 +375,7 @@ class LIBARDOUR_API TempoMap : public PBD::StatefulDestructible
void remove_meter (const MeterSection&, bool send_signal);
framepos_t predict_tempo_frame (TempoSection* section, const Tempo& bpm, const Timecode::BBT_Time& bbt);
double predict_tempo_beat (TempoSection* section, const Tempo& bpm, const framepos_t& beat);
double predict_tempo_pulse (TempoSection* section, const Tempo& bpm, const framepos_t& frame);
void replace_tempo (const TempoSection&, const Tempo&, const double& where, TempoSection::Type type);
void replace_tempo (const TempoSection&, const Tempo&, const framepos_t& frame, TempoSection::Type type);
@ -399,7 +399,7 @@ class LIBARDOUR_API TempoMap : public PBD::StatefulDestructible
XMLNode& get_state (void);
int set_state (const XMLNode&, int version);
void dump (Metrics& metrics, std::ostream&) const;
void dump (const Metrics& metrics, std::ostream&) const;
void clear ();
TempoMetric metric_at (Timecode::BBT_Time bbt) const;
@ -426,20 +426,24 @@ class LIBARDOUR_API TempoMap : public PBD::StatefulDestructible
Timecode::BBT_Time beats_to_bbt (const double& beats);
Timecode::BBT_Time pulse_to_bbt (const double& pulse);
double pulse_at_beat (const double& beat) const;
double beat_at_pulse (const double& pulse) const;
PBD::Signal0<void> MetricPositionChanged;
private:
double pulse_at_beat (const Metrics& metrics, const double& beat) const;
double beat_at_pulse (const Metrics& metrics, const double& pulse) const;
double pulse_at_beat_locked (const Metrics& metrics, const double& beat) const;
double beat_at_pulse_locked (const Metrics& metrics, const double& pulse) const;
double pulse_at_frame_locked (const Metrics& metrics, const framecnt_t& frame) const;
framecnt_t frame_at_pulse_locked (const Metrics& metrics, const double& beat) const;
double pulse_offset_at (const Metrics& metrics, const double& pulse) const;
frameoffset_t frame_offset_at (const Metrics& metrics, const framepos_t& frame) const;
double beat_at_frame_locked (const Metrics& metrics, const framecnt_t& frame) const;
framecnt_t frame_at_beat_locked (const Metrics& metrics, const double& beat) const;
double bbt_to_beats_locked (const Metrics& metrics, const Timecode::BBT_Time& bbt) const ;
Timecode::BBT_Time beats_to_bbt_locked (const Metrics& metrics, const double& beats) const;
double pulse_at_frame_locked (const Metrics& metrics, const framecnt_t& frame) const;
framecnt_t frame_at_pulse_locked (const Metrics& metrics, const double& beat) const;
double beat_offset_at (const Metrics& metrics, const double& beat) const;
frameoffset_t frame_offset_at (const Metrics& metrics, const framepos_t& frame) const;
framepos_t frame_time_locked (const Metrics& metrics, const Timecode::BBT_Time&) const;
@ -476,7 +480,7 @@ private:
void do_insert (MetricSection* section);
void add_tempo_locked (const Tempo&, double where, bool recompute, TempoSection::Type type);
void add_tempo_locked (const Tempo&, double pulse, bool recompute, TempoSection::Type type);
void add_tempo_locked (const Tempo&, framepos_t frame, bool recompute, TempoSection::Type type);
void add_meter_locked (const Meter&, double beat, Timecode::BBT_Time where, bool recompute);

View file

@ -715,7 +715,7 @@ TempoMap::do_insert (MetricSection* section)
corrected.first = bbt_to_beats_locked (_metrics, 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_pulse (corrected);
//m->set_pulse (corrected);
}
}
@ -822,14 +822,14 @@ TempoMap::do_insert (MetricSection* section)
}
void
TempoMap::replace_tempo (const TempoSection& ts, const Tempo& tempo, const double& where, TempoSection::Type type)
TempoMap::replace_tempo (const TempoSection& ts, const Tempo& tempo, const double& pulse, TempoSection::Type type)
{
{
Glib::Threads::RWLock::WriterLock lm (lock);
TempoSection& first (first_tempo());
if (ts.pulse() != first.pulse()) {
remove_tempo_locked (ts);
add_tempo_locked (tempo, where, true, type);
add_tempo_locked (tempo, pulse, true, type);
} else {
first.set_type (type);
{
@ -865,11 +865,11 @@ TempoMap::replace_tempo (const TempoSection& ts, const Tempo& tempo, const frame
}
void
TempoMap::add_tempo (const Tempo& tempo, const double& where, ARDOUR::TempoSection::Type type)
TempoMap::add_tempo (const Tempo& tempo, const double& pulse, ARDOUR::TempoSection::Type type)
{
{
Glib::Threads::RWLock::WriterLock lm (lock);
add_tempo_locked (tempo, where, true, type);
add_tempo_locked (tempo, pulse, true, type);
}
PropertyChanged (PropertyChange ());
@ -888,9 +888,8 @@ TempoMap::add_tempo (const Tempo& tempo, const framepos_t& frame, ARDOUR::TempoS
}
void
TempoMap::add_tempo_locked (const Tempo& tempo, double where, bool recompute, ARDOUR::TempoSection::Type type)
TempoMap::add_tempo_locked (const Tempo& tempo, double pulse, bool recompute, ARDOUR::TempoSection::Type type)
{
double pulse = pulse_at_beat (_metrics, where);
TempoSection* ts = new TempoSection (pulse, tempo.beats_per_minute(), tempo.note_type(), type);
do_insert (ts);
@ -1007,7 +1006,7 @@ TempoMap::add_meter_locked (const Meter& meter, double beat, BBT_Time where, boo
}
/* new meters *always* start on a beat. */
where.ticks = 0;
double pulse = pulse_at_beat (_metrics, beat);
double pulse = pulse_at_beat_locked (_metrics, beat);
MeterSection* new_meter = new MeterSection (pulse, where, meter.divisions_per_bar(), meter.note_divisor());
do_insert (new_meter);
@ -1024,7 +1023,7 @@ TempoMap::add_meter_locked (const Meter& meter, framepos_t frame, bool recompute
MeterSection* new_meter = new MeterSection (frame, meter.divisions_per_bar(), meter.note_divisor());
double paf = pulse_at_frame_locked (_metrics, frame);
pair<double, BBT_Time> beat = make_pair (paf, beats_to_bbt_locked (_metrics, beat_at_pulse (_metrics, paf)));
pair<double, BBT_Time> beat = make_pair (paf, beats_to_bbt_locked (_metrics, beat_at_pulse_locked (_metrics, paf)));
new_meter->set_pulse (beat);
do_insert (new_meter);
@ -1050,7 +1049,7 @@ TempoMap::predict_tempo_frame (TempoSection* section, const Tempo& bpm, const BB
framepos_t ret = 0;
TempoSection* new_section = copy_metrics_and_point (future_map, section);
double const beat = bbt_to_beats_locked (future_map, bbt);
if (solve_map (future_map, new_section, bpm, pulse_at_beat (future_map, beat))) {
if (solve_map (future_map, new_section, bpm, pulse_at_beat_locked (future_map, beat))) {
ret = new_section->frame();
} else {
ret = frame_at_beat_locked (_metrics, beat);
@ -1065,7 +1064,7 @@ TempoMap::predict_tempo_frame (TempoSection* section, const Tempo& bpm, const BB
}
double
TempoMap::predict_tempo_beat (TempoSection* section, const Tempo& bpm, const framepos_t& frame)
TempoMap::predict_tempo_pulse (TempoSection* section, const Tempo& bpm, const framepos_t& frame)
{
Glib::Threads::RWLock::ReaderLock lm (lock);
Metrics future_map;
@ -1073,9 +1072,9 @@ TempoMap::predict_tempo_beat (TempoSection* section, const Tempo& bpm, const fra
TempoSection* new_section = copy_metrics_and_point (future_map, section);
if (solve_map (future_map, new_section, bpm, frame)) {
ret = beat_at_pulse (future_map, new_section->pulse());
ret = new_section->pulse();
} else {
ret = beat_at_frame_locked (_metrics, frame);
ret = pulse_at_frame_locked (_metrics, frame);
}
Metrics::const_iterator d = future_map.begin();
@ -1114,7 +1113,7 @@ TempoMap::gui_move_tempo_beat (TempoSection* ts, const Tempo& bpm, const double
{
Glib::Threads::RWLock::WriterLock lm (lock);
TempoSection* new_section = copy_metrics_and_point (future_map, ts);
if (solve_map (future_map, new_section, bpm, pulse_at_beat (future_map, beat))) {
if (solve_map (future_map, new_section, bpm, pulse_at_beat_locked (future_map, beat))) {
solve_map (_metrics, ts, bpm, beat);
}
}
@ -1144,7 +1143,7 @@ TempoMap::gui_move_meter (MeterSection* ms, const Meter& mt, const double& beat
{
{
Glib::Threads::RWLock::WriterLock lm (lock);
solve_map (_metrics, ms, mt, pulse_at_beat (_metrics, beat));
solve_map (_metrics, ms, mt, pulse_at_beat_locked (_metrics, beat));
}
MetricPositionChanged (); // Emit Signal
@ -1429,7 +1428,14 @@ TempoMap::recompute_map (Metrics& metrics, framepos_t end)
}
double
TempoMap::pulse_at_beat (const Metrics& metrics, const double& beat) const
TempoMap::pulse_at_beat (const double& beat) const
{
Glib::Threads::RWLock::ReaderLock lm (lock);
return pulse_at_beat_locked (_metrics, beat);
}
double
TempoMap::pulse_at_beat_locked (const Metrics& metrics, const double& beat) const
{
MeterSection* prev_ms = 0;
double accumulated_beats = 0.0;
@ -1450,11 +1456,17 @@ TempoMap::pulse_at_beat (const Metrics& metrics, const double& beat) const
}
double
TempoMap::beat_at_pulse (const Metrics& metrics, const double& pulse) const
TempoMap::beat_at_pulse (const double& pulse) const
{
Glib::Threads::RWLock::ReaderLock lm (lock);
return beat_at_pulse_locked (_metrics, pulse);
}
double
TempoMap::beat_at_pulse_locked (const Metrics& metrics, const double& pulse) const
{
MeterSection* prev_ms = 0;
double accumulated_beats = 0.0;
for (Metrics::const_iterator i = metrics.begin(); i != metrics.end(); ++i) {
MeterSection* m;
if ((m = dynamic_cast<MeterSection*> (*i)) != 0) {
@ -1543,7 +1555,7 @@ TempoMap::bbt_time (framepos_t frame, BBT_Time& bbt)
}
Glib::Threads::RWLock::ReaderLock lm (lock);
frameoffset_t const frame_off = frame_offset_at (_metrics, frame);
double const beat = beat_at_pulse (_metrics, pulse_at_frame_locked (_metrics, frame + frame_off));
double const beat = beat_at_pulse_locked (_metrics, pulse_at_frame_locked (_metrics, frame + frame_off));
bbt = beats_to_bbt_locked (_metrics, beat);
}
@ -1727,7 +1739,7 @@ TempoMap::beat_at_frame_locked (const Metrics& metrics, const framecnt_t& frame)
framecnt_t const offset_frame = frame + frame_offset_at (metrics, frame);
double const pulse = pulse_at_frame_locked (metrics, offset_frame);
return beat_at_pulse (metrics, pulse);
return beat_at_pulse_locked (metrics, pulse);
}
double
@ -1741,13 +1753,11 @@ TempoMap::pulse_at_frame_locked (const Metrics& metrics, const framecnt_t& frame
TempoSection* t;
if ((t = dynamic_cast<TempoSection*> (*i)) != 0) {
if (prev_ts) {
if (t->frame() > frame) {
if (prev_ts && t->frame() > frame) {
/*the previous ts is the one containing the frame */
double const ret = prev_ts->pulse_at_frame (frame, _frame_rate);
return ret;
}
}
accumulated_pulses = t->pulse();
prev_ts = t;
}
@ -1769,7 +1779,7 @@ TempoMap::frame_at_beat (const double& beat) const
framecnt_t
TempoMap::frame_at_beat_locked (const Metrics& metrics, const double& beat) const
{
framecnt_t const frame = frame_at_pulse_locked (metrics, pulse_at_beat (metrics, beat));
framecnt_t const frame = frame_at_pulse_locked (metrics, pulse_at_beat_locked (metrics, beat));
frameoffset_t const frame_off = frame_offset_at (metrics, frame);
return frame - frame_off;
}
@ -1805,28 +1815,28 @@ TempoMap::frame_at_pulse_locked (const Metrics& metrics, const double& pulse) co
}
double
TempoMap::beat_offset_at (const Metrics& metrics, const double& beat) const
TempoMap::pulse_offset_at (const Metrics& metrics, const double& pulse) const
{
MeterSection* prev_m = 0;
double beat_off = 0.0;
double pulse_off = first_meter().pulse();
for (Metrics::const_iterator i = metrics.begin(); i != metrics.end(); ++i) {
MeterSection* m = 0;
if ((m = dynamic_cast<MeterSection*> (*i)) != 0) {
if (prev_m) {
if (m->beat() > beat) {
if (m->pulse() > pulse) {
break;
}
if (m->position_lock_style() == AudioTime) {
beat_off += ((m->pulse() - prev_m->pulse()) / prev_m->note_divisor()) - floor ((m->pulse() - prev_m->pulse()) / prev_m->note_divisor());
pulse_off += (m->pulse() - prev_m->pulse()) - floor (m->pulse() - prev_m->pulse());
}
}
prev_m = m;
}
}
return beat_off;
return pulse_off;
}
frameoffset_t
@ -1871,7 +1881,7 @@ TempoMap::frame_time_locked (const Metrics& metrics, const BBT_Time& bbt) const
{
/* HOLD THE READER LOCK */
framepos_t const ret = frame_at_pulse_locked (metrics, pulse_at_beat (metrics, bbt_to_beats_locked (metrics, bbt)));
framepos_t const ret = frame_at_pulse_locked (metrics, pulse_at_beat_locked (metrics, bbt_to_beats_locked (metrics, bbt)));
return ret;
}
@ -1891,6 +1901,7 @@ TempoMap::check_solved (Metrics& metrics, bool by_frame)
if (by_frame && t->frame() != prev_ts->frame_at_tempo (t->pulses_per_minute(), t->pulse(), _frame_rate)) {
return false;
}
/*
if (!by_frame && fabs (t->pulse() - prev_ts->pulse_at_tempo (t->pulses_per_minute(), t->frame(), _frame_rate)) > 0.00001) {
std::cerr << "beat precision too low for bpm: " << t->beats_per_minute() << std::endl <<
" |error :" << t->pulse() - prev_ts->pulse_at_tempo (t->pulses_per_minute(), t->frame(), _frame_rate) << std::endl <<
@ -1898,6 +1909,7 @@ TempoMap::check_solved (Metrics& metrics, bool by_frame)
" |frame at tempo : " << prev_ts->frame_at_tempo (t->pulses_per_minute(), t->pulse(), _frame_rate) << std::endl;
return false;
}
*/
}
prev_ts = t;
}
@ -2441,7 +2453,7 @@ const Tempo
TempoMap::tempo_at (const framepos_t& frame) const
{
Glib::Threads::RWLock::ReaderLock lm (lock);
frameoffset_t const frame_off = frame_offset_at (_metrics, frame);
//frameoffset_t const frame_off = frame_offset_at (_metrics, frame);
TempoSection* prev_ts = 0;
Metrics::const_iterator i;
@ -2475,7 +2487,7 @@ TempoMap::meter_section_at (framepos_t frame) const
const MeterSection&
TempoMap::meter_section_at_locked (framepos_t frame) const
{
framepos_t const frame_off = frame + frame_offset_at (_metrics, frame);
//framepos_t const frame_off = frame + frame_offset_at (_metrics, frame);
Metrics::const_iterator i;
MeterSection* prev = 0;
@ -2636,7 +2648,7 @@ TempoMap::set_state (const XMLNode& node, int /*version*/)
}
void
TempoMap::dump (Metrics& metrics, std::ostream& o) const
TempoMap::dump (const Metrics& metrics, std::ostream& o) const
{
Glib::Threads::RWLock::ReaderLock lm (lock, Glib::Threads::TRY_LOCK);
const MeterSection* m;