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:
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
@@ -727,7 +727,7 @@ public:
|
||||
}
|
||||
|
||||
bool y_movement_matters () const {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void setup_pointer_frame_offset ();
|
||||
|
||||
@@ -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
|
||||
);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user