Tempo ramps - pressing constraint modifier keys during tempo drag changes tempo with vertical movement, incorporating beat constraint (if present).

- makes it easy to find suitable accelerandos for hit points in conjunction
	  with playhead position, beat-locked tempos and initial meter frame.
This commit is contained in:
nick_m
2016-03-26 04:48:29 +11:00
parent 1be5a42737
commit 69b6379b23
6 changed files with 57 additions and 15 deletions

View File

@@ -3312,17 +3312,24 @@ TempoMarkerDrag::motion (GdkEvent* event, bool first_move)
_marker->hide();
}
framepos_t const pf = adjusted_current_frame (event, false);
framepos_t const pf = adjusted_current_frame (event);
Tempo const tp = _marker->tempo();
_marker->set_position (pf);
/* just here for a check/laugh
if (_real_section->position_lock_style() == MusicTime) {
const double baf = _editor->session()->tempo_map().beat_at_frame (pf);
_editor->session()->tempo_map().gui_move_tempo_beat (_real_section, tp, baf);
if (Keyboard::modifier_state_equals (event->button.state, ArdourKeyboard::constraint_modifier ())) {
double new_bpm = tp.beats_per_minute() + ((grab_y() - current_pointer_y()) / 4.0);
_real_section->set_beats_per_minute (new_bpm);
_editor->session()->tempo_map().gui_change_tempo (_real_section, Tempo (new_bpm, _real_section->note_type()));
} else {
*/
_editor->session()->tempo_map().gui_move_tempo_frame (_real_section, tp, pf);
//}
/* just here for a check/laugh
if (_real_section->position_lock_style() == MusicTime) {
const double baf = _editor->session()->tempo_map().beat_at_frame (pf);
_editor->session()->tempo_map().gui_move_tempo_beat (_real_section, tp, baf);
} else {
*/
_editor->session()->tempo_map().gui_move_tempo_frame (_real_section, tp, pf);
//}
}
show_verbose_cursor_time (pf);
}
@@ -3362,11 +3369,11 @@ TempoMarkerDrag::finished (GdkEvent* event, bool movement_occurred)
} else {
if (_marker->tempo().position_lock_style() == MusicTime) {
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())
double const pulse = map.predict_tempo_pulse (_real_section, Tempo (_real_section->beats_per_minute(), _real_section->note_type()), _real_section->frame());
map.replace_tempo (*_real_section, Tempo (_real_section->beats_per_minute(), _real_section->note_type())
, pulse, _marker->tempo().type());
} else {
map.replace_tempo (*_real_section, Tempo (_marker->tempo().beats_per_minute(), _marker->tempo().note_type())
map.replace_tempo (*_real_section, Tempo (_real_section->beats_per_minute(), _real_section->note_type())
, _real_section->frame(), _marker->tempo().type());
}

View File

@@ -727,7 +727,7 @@ public:
}
bool y_movement_matters () const {
return false;
return true;
}
void setup_pointer_frame_offset ();

View File

@@ -684,7 +684,7 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
new TempoMarkerDrag (
this,
item,
Keyboard::modifier_state_contains (event->button.state, Keyboard::CopyModifier)
Keyboard::modifier_state_equals (event->button.state, Keyboard::CopyModifier)
),
event
);

View File

@@ -143,6 +143,9 @@ Editor::marker_position_changed ()
if ((tempo_marker = dynamic_cast<TempoMarker*> (*x)) != 0) {
if ((ts = &tempo_marker->tempo()) != 0) {
tempo_marker->set_position (ts->frame ());
char buf[64];
snprintf (buf, sizeof (buf), "%.2f", ts->beats_per_minute());
tempo_marker->set_name (buf);
}
}
if ((meter_marker = dynamic_cast<MeterMarker*> (*x)) != 0) {

View File

@@ -56,6 +56,7 @@ class LIBARDOUR_API Tempo {
: _beats_per_minute (bpm), _note_type(type) {}
double beats_per_minute () const { return _beats_per_minute; }
void set_beats_per_minute (double bpm) { _beats_per_minute = bpm; }
double note_type () const { return _note_type; }
double pulses_per_minute () const { return _beats_per_minute / _note_type; }
/** audio samples per beat
@@ -387,6 +388,7 @@ class LIBARDOUR_API TempoMap : public PBD::StatefulDestructible
void gui_move_tempo_beat (TempoSection*, const Tempo& bpm, const double& frame);
void gui_move_meter (MeterSection*, const Meter& mt, const framepos_t& frame);
void gui_move_meter (MeterSection*, const Meter& mt, const double& beat);
bool gui_change_tempo (TempoSection*, const Tempo& bpm);
bool can_solve_bbt (TempoSection* section, const Tempo& bpm, const Timecode::BBT_Time& bbt);

View File

@@ -1159,6 +1159,34 @@ TempoMap::gui_move_meter (MeterSection* ms, const Meter& mt, const double& beat
MetricPositionChanged (); // Emit Signal
}
bool
TempoMap::gui_change_tempo (TempoSection* ts, const Tempo& bpm)
{
Metrics future_map;
bool can_solve = false;
{
Glib::Threads::RWLock::WriterLock lm (lock);
TempoSection* new_section = copy_metrics_and_point (future_map, ts);
new_section->set_beats_per_minute (bpm.beats_per_minute());
recompute_tempos (future_map);
if (check_solved (future_map, true)) {
ts->set_beats_per_minute (bpm.beats_per_minute());
recompute_map (_metrics);
can_solve = true;
}
}
Metrics::const_iterator d = future_map.begin();
while (d != future_map.end()) {
delete (*d);
++d;
}
if (can_solve) {
MetricPositionChanged (); // Emit Signal
}
return can_solve;
}
TempoSection*
TempoMap::copy_metrics_and_point (Metrics& copy, TempoSection* section)
{
@@ -1949,6 +1977,7 @@ TempoMap::solve_map (Metrics& imaginary, TempoSection* section, const Tempo& bpm
MetricSectionSorter cmp;
section->set_frame (frame);
for (Metrics::iterator i = imaginary.begin(); i != imaginary.end(); ++i) {
TempoSection* t;
if ((t = dynamic_cast<TempoSection*> (*i)) != 0) {
@@ -1970,7 +1999,7 @@ TempoMap::solve_map (Metrics& imaginary, TempoSection* section, const Tempo& bpm
}
if (section_prev) {
section_prev->set_c_func (section_prev->compute_c_func_pulse (section->pulses_per_minute(), section->pulse(), _frame_rate));
section_prev->set_c_func (section_prev->compute_c_func_frame (bpm.pulses_per_minute(), frame, _frame_rate));
section->set_pulse (section_prev->pulse_at_frame (frame, _frame_rate));
}
@@ -2029,6 +2058,7 @@ TempoMap::solve_map (Metrics& imaginary, TempoSection* section, const Tempo& bpm
TempoSection* section_prev = 0;
section->set_pulse (pulse);
section->set_beats_per_minute (bpm.beats_per_minute());
for (Metrics::iterator i = imaginary.begin(); i != imaginary.end(); ++i) {
TempoSection* t;
@@ -2050,7 +2080,7 @@ TempoMap::solve_map (Metrics& imaginary, TempoSection* section, const Tempo& bpm
}
}
if (section_prev) {
section_prev->set_c_func (section_prev->compute_c_func_pulse (section->pulses_per_minute(), pulse, _frame_rate));
section_prev->set_c_func (section_prev->compute_c_func_pulse (bpm.pulses_per_minute(), pulse, _frame_rate));
section->set_frame (section_prev->frame_at_pulse (pulse, _frame_rate));
}