From 49e1f7f79d9daa72bb03f4ec147c7a1703eadc0f Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Wed, 3 May 2023 21:51:26 -0600 Subject: [PATCH] fix logic of editing tempo & meter Old code use the TempoMetric (Tempo + Meter) in effect at the old location of the tempo/meter to compute the position of the edited tempo/meter, using a BBT time from the dialog. But this TempoMetric uses the very tempo/meter that we're editing! So we have to use previous_tempo() or previous_meter() to construct the relevant TempoMetric, and if it is the first tempo or meter, then obviously it cannot move position at all. --- gtk2_ardour/editor_tempodisplay.cc | 77 ++++++++++++++++++++++++++---- 1 file changed, 68 insertions(+), 9 deletions(-) diff --git a/gtk2_ardour/editor_tempodisplay.cc b/gtk2_ardour/editor_tempodisplay.cc index 004fced35d..7b58e52ae7 100644 --- a/gtk2_ardour/editor_tempodisplay.cc +++ b/gtk2_ardour/editor_tempodisplay.cc @@ -623,18 +623,46 @@ Editor::edit_meter_section (Temporal::MeterPoint& section) return; } + Temporal::TempoMetric tm (TempoMap::use()->metric_at (section.sclock())); + Temporal::MeterPoint const * mpp (TempoMap::use()->previous_meter (tm.meter())); + double bpb = meter_dialog.get_bpb (); bpb = max (1.0, bpb); // XXX is this a reasonable limit? double const note_type = meter_dialog.get_note_type (); const Meter meter (bpb, note_type); - Temporal::BBT_Time w; - meter_dialog.get_bbt_time (w); - Temporal::BBT_Argument when (timepos_t::zero (Temporal::BeatTime), w); + Temporal::Beats new_pos; + + if (!mpp) { + /* first meter, cannot move */ + new_pos = section.beats (); + } else { + /* Compute the given BBT time using a tempo metric composed + from the tempo in effect at the current position, and the + previous meter. + + Step 1: get BBT time from dialog + */ + + Temporal::BBT_Time w; + meter_dialog.get_bbt_time (w); + + /* Step 2: construct the relevant tempo metric */ + + TempoMetric prev_tm (tm.tempo(), *mpp); + + /* Step 3: construct new BBT_Argument */ + + Temporal::BBT_Argument when (tm.reftime(), w); + + /* Step 4: convert to quarters */ + + new_pos = prev_tm.quarters_at (when); + } TempoMapChange tmc (*this, _("edit time signature")); - tmc.map().set_meter (meter, when); + tmc.map().set_meter (meter, timepos_t (new_pos)); } void @@ -666,7 +694,6 @@ void Editor::edit_tempo_section (TempoPoint& section) { TempoDialog tempo_dialog (TempoMap::use(), section, _("done")); - Temporal::TempoMetric tm (TempoMap::use()->metric_at (section.sclock())); switch (tempo_dialog.run ()) { case RESPONSE_ACCEPT: @@ -675,6 +702,9 @@ Editor::edit_tempo_section (TempoPoint& section) return; } + Temporal::TempoMetric tm (TempoMap::use()->metric_at (section.sclock())); + Temporal::TempoPoint const * tpp (TempoMap::use()->previous_tempo (tm.tempo())); + double bpm = tempo_dialog.get_bpm (); double end_bpm = tempo_dialog.get_end_bpm (); int nt = tempo_dialog.get_note_type (); @@ -682,12 +712,41 @@ Editor::edit_tempo_section (TempoPoint& section) const Tempo tempo (bpm, end_bpm, nt); - Temporal::BBT_Time w; - tempo_dialog.get_bbt_time (w); - Temporal::BBT_Argument when (tm.reftime(), w); + Temporal::Beats new_pos; + + if (!tpp) { + /* first tempo, cannot move */ + new_pos = section.beats (); + } else { + /* Compute the given BBT time using a tempo metric composed + from the meter in effect at the current position, and the + previous tempo. + + Step 1: get BBT time from dialog + */ + + Temporal::BBT_Time w; + tempo_dialog.get_bbt_time (w); + + /* Step 2: construct the relevant tempo metric */ + + TempoMetric prev_tm (*tpp, tm.meter()); + + /* Step 3: construct new BBT_Argument */ + + Temporal::BBT_Argument when (tm.reftime(), w); + + /* Step 4: convert to quarters */ + + new_pos = prev_tm.quarters_at (when); + } TempoMapChange tmc (*this, _("edit tempo")); - tmc.map().replace_tempo (section, tempo, timepos_t (tmc.map().quarters_at (when))); + + // std::cerr << "using tempometric " << tm << std::endl; + // std::cerr << "edit tempo at " << when << " via quarters at = " << tmc.map().quarters_at (when) << std::endl; + + tmc.map().replace_tempo (section, tempo, timepos_t (new_pos)); } void