Tempo ramps - tempo drags respect the snap modifier. add some documentation.
This commit is contained in:
parent
354567e5a7
commit
a9714de9b9
|
@ -3318,29 +3318,6 @@ TempoMarkerDrag::motion (GdkEvent* event, bool first_move)
|
|||
|
||||
framepos_t pf;
|
||||
double beat = 0.0;
|
||||
|
||||
if (!_editor->snap_musical()) {
|
||||
pf = adjusted_current_frame (event);
|
||||
} else {
|
||||
pf = adjusted_current_frame (event, false);
|
||||
Timecode::BBT_Time when;
|
||||
_editor->session()->tempo_map().bbt_time (pf, when);
|
||||
if (_real_section->position_lock_style() == MusicTime) {
|
||||
if (_editor->snap_type() == SnapToBar) {
|
||||
_editor->session()->tempo_map().round_bbt (when, -1);
|
||||
} else {
|
||||
_editor->session()->tempo_map().round_bbt (when, _editor->get_grid_beat_divisions (0));
|
||||
}
|
||||
beat = _editor->session()->tempo_map().bbt_to_beats (when);
|
||||
} else {
|
||||
if (_editor->snap_type() == SnapToBar) {
|
||||
_editor->session()->tempo_map().round_bbt (when, -1);
|
||||
} else {
|
||||
_editor->session()->tempo_map().round_bbt (when, _editor->get_grid_beat_divisions (0));
|
||||
}
|
||||
pf = _editor->session()->tempo_map().predict_tempo_frame (_real_section, Tempo (_real_section->beats_per_minute(), _real_section->note_type()), when);
|
||||
}
|
||||
}
|
||||
Tempo const tp = _marker->tempo();
|
||||
|
||||
if (Keyboard::modifier_state_equals (event->button.state, ArdourKeyboard::constraint_modifier ())) {
|
||||
|
@ -3350,12 +3327,47 @@ TempoMarkerDrag::motion (GdkEvent* event, bool first_move)
|
|||
strs << new_bpm;
|
||||
show_verbose_cursor_text (strs.str());
|
||||
} else if (_movable) {
|
||||
|
||||
if (_real_section->position_lock_style() == MusicTime) {
|
||||
_editor->session()->tempo_map().gui_move_tempo_beat (_real_section, tp, beat);
|
||||
if (!_editor->snap_musical()) {
|
||||
pf = adjusted_current_frame (event);
|
||||
} else {
|
||||
_editor->session()->tempo_map().gui_move_tempo_frame (_real_section, tp, pf);
|
||||
pf = adjusted_current_frame (event, false);
|
||||
bool use_snap;
|
||||
|
||||
if (Keyboard::modifier_state_equals (event->button.state, ArdourKeyboard::snap_modifier ())) {
|
||||
if (_editor->snap_mode() == Editing::SnapOff) {
|
||||
use_snap = true;
|
||||
} else {
|
||||
use_snap = false;
|
||||
}
|
||||
} else {
|
||||
if (_editor->snap_mode() == Editing::SnapOff) {
|
||||
use_snap = false;
|
||||
} else {
|
||||
use_snap = true;
|
||||
}
|
||||
}
|
||||
|
||||
Timecode::BBT_Time when;
|
||||
_editor->session()->tempo_map().bbt_time (pf, when);
|
||||
if (_real_section->position_lock_style() == MusicTime) {
|
||||
if (use_snap && _editor->snap_type() == SnapToBar) {
|
||||
_editor->session()->tempo_map().round_bbt (when, -1);
|
||||
} else if (use_snap) {
|
||||
_editor->session()->tempo_map().round_bbt (when, _editor->get_grid_beat_divisions (0));
|
||||
}
|
||||
beat = _editor->session()->tempo_map().bbt_to_beats (when);
|
||||
_editor->session()->tempo_map().gui_move_tempo_beat (_real_section, tp, beat);
|
||||
} else {
|
||||
if (use_snap && _editor->snap_type() == SnapToBar) {
|
||||
_editor->session()->tempo_map().round_bbt (when, -1);
|
||||
} else if (use_snap) {
|
||||
_editor->session()->tempo_map().round_bbt (when, _editor->get_grid_beat_divisions (0));
|
||||
}
|
||||
pf = _editor->session()->tempo_map().predict_tempo_frame (_real_section, Tempo (_real_section->beats_per_minute(), _real_section->note_type()), when);
|
||||
_editor->session()->tempo_map().gui_move_tempo_frame (_real_section, tp, pf);
|
||||
}
|
||||
}
|
||||
|
||||
show_verbose_cursor_time (pf);
|
||||
}
|
||||
_marker->set_position (pf);
|
||||
|
|
|
@ -55,6 +55,9 @@ class LIBARDOUR_API Tempo {
|
|||
Tempo (double bpm, double type=4.0) // defaulting to quarter note
|
||||
: _beats_per_minute (bpm), _note_type(type) {}
|
||||
|
||||
/* ..or more aptly 'pulse divisions per minute'.
|
||||
Nothing to do with actual beats, which are defined by the meter and tempo.
|
||||
*/
|
||||
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; }
|
||||
|
|
|
@ -604,7 +604,28 @@ MeterSection::get_state() const
|
|||
}
|
||||
|
||||
/***********************************************************************/
|
||||
/*
|
||||
Tempo Map Overview
|
||||
|
||||
We have tempos, which are nice to think of in whole pulses per minute,
|
||||
and meters which divide tempo pulses into bars (via divisions_per_bar)
|
||||
and beats (via note_divisor).
|
||||
Tempos and meters may be locked to audio or music.
|
||||
Because the notion of a beat cannot be determined without both tempo and meter, the first tempo
|
||||
and first meter are special. they must move together, and must be locked to audio.
|
||||
Audio locked tempos which lie before the first meter are made inactive.
|
||||
They will be re-activated if the first meter is again placed before them.
|
||||
|
||||
Both tempos and meters have a pulse position and a frame position.
|
||||
Recomputing the tempo map is the process where the 'missing' position
|
||||
(pulse in the case of AudioTime and frame for MusicTime) is calculated
|
||||
based on the lock preference (position_lock_style).
|
||||
|
||||
It is important to keep the _metrics in an order that makes sense.
|
||||
Because ramped MusicTime and AudioTime tempos can interact with each other
|
||||
and cause reordering, care must be taken to keep _metrics in a solved state.
|
||||
Solved means ordered by frame or pulse with frame-accurate precision (see check_solved()).
|
||||
*/
|
||||
struct MetricSectionSorter {
|
||||
bool operator() (const MetricSection* a, const MetricSection* b) {
|
||||
return a->pulse() < b->pulse();
|
||||
|
@ -2004,18 +2025,10 @@ TempoMap::check_solved (Metrics& metrics, bool by_frame)
|
|||
if ((by_frame && t->frame() < prev_ts->frame()) || (!by_frame && t->pulse() < prev_ts->pulse())) {
|
||||
return false;
|
||||
}
|
||||
if (by_frame && t->frame() != prev_ts->frame_at_pulse (t->pulse(), _frame_rate)) {
|
||||
/* precision check ensures pulses and frames align independent of lock style.*/
|
||||
if (t->frame() != prev_ts->frame_at_pulse (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 <<
|
||||
"|frame at beat :" << prev_ts->frame_at_pulse (t->pulse(), _frame_rate) << std::endl <<
|
||||
" |frame at tempo : " << prev_ts->frame_at_tempo (t->pulses_per_minute(), t->pulse(), _frame_rate) << std::endl;
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
}
|
||||
prev_ts = t;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user