diff options
author | nick_m <mainsbridge@gmail.com> | 2016-08-13 02:23:07 +1000 |
---|---|---|
committer | nick_m <mainsbridge@gmail.com> | 2016-08-14 03:04:53 +1000 |
commit | 5c2ccc4f3eeccaedf8399e0c80d0394cf2b4f132 (patch) | |
tree | 3725e8f5b4abf8c0a2dc1f277ba8e5e9999b5561 | |
parent | 23d1d1f55bdb6c1e4418284afdf50c74dc1e25ed (diff) |
Allow negative return in TempoMap::beat_at_frame() and its exact_ variant.
- audio-locked midi regions can be start-trimmed properly
when close to 1|1|0
- a midi region placed before the first meter
will continue the tempo curve and first meter.
Only a couple of callers require change, as bbt_at_beat() already
deals with this.
-rw-r--r-- | gtk2_ardour/editor_rulers.cc | 4 | ||||
-rw-r--r-- | gtk2_ardour/editor_tempodisplay.cc | 2 | ||||
-rw-r--r-- | gtk2_ardour/step_editor.cc | 2 | ||||
-rw-r--r-- | libs/ardour/tempo.cc | 53 |
4 files changed, 28 insertions, 33 deletions
diff --git a/gtk2_ardour/editor_rulers.cc b/gtk2_ardour/editor_rulers.cc index 868b006900..6c9e45abc8 100644 --- a/gtk2_ardour/editor_rulers.cc +++ b/gtk2_ardour/editor_rulers.cc @@ -1017,14 +1017,14 @@ Editor::compute_bbt_ruler_scale (std::vector<ARDOUR::TempoMap::BBTPoint>& grid, std::vector<TempoMap::BBTPoint>::const_iterator i; Timecode::BBT_Time lower_beat, upper_beat; // the beats at each end of the ruler - double floor_lower_beat = floor(_session->tempo_map().beat_at_frame (lower)); + double floor_lower_beat = floor(max (0.0, _session->tempo_map().beat_at_frame (lower))); if (floor_lower_beat < 0.0) { floor_lower_beat = 0.0; } const framecnt_t beat_before_lower_pos = _session->tempo_map().frame_at_beat (floor_lower_beat); - const framecnt_t beat_after_upper_pos = _session->tempo_map().frame_at_beat (floor (_session->tempo_map().beat_at_frame (upper)) + 1.0); + const framecnt_t beat_after_upper_pos = _session->tempo_map().frame_at_beat (floor (max (0.0, _session->tempo_map().beat_at_frame (upper))) + 1.0); _session->bbt_time (beat_before_lower_pos, lower_beat); _session->bbt_time (beat_after_upper_pos, upper_beat); diff --git a/gtk2_ardour/editor_tempodisplay.cc b/gtk2_ardour/editor_tempodisplay.cc index 722490c26e..9c562a4d86 100644 --- a/gtk2_ardour/editor_tempodisplay.cc +++ b/gtk2_ardour/editor_tempodisplay.cc @@ -279,7 +279,7 @@ Editor::compute_current_bbt_points (std::vector<TempoMap::BBTPoint>& grid, frame /* prevent negative values of leftmost from creeping into tempomap */ - const double lower_beat = floor (_session->tempo_map().beat_at_frame (leftmost)) - 1.0; + const double lower_beat = floor (max (0.0, _session->tempo_map().beat_at_frame (leftmost))) - 1.0; _session->tempo_map().get_grid (grid, max (_session->tempo_map().frame_at_beat (lower_beat), (framepos_t) 0), rightmost); } diff --git a/gtk2_ardour/step_editor.cc b/gtk2_ardour/step_editor.cc index 3ea3bb4ccd..c45c0f4461 100644 --- a/gtk2_ardour/step_editor.cc +++ b/gtk2_ardour/step_editor.cc @@ -117,7 +117,7 @@ StepEditor::prepare_step_edit_region () const Meter& m = _mtv.session()->tempo_map().meter_at_frame (step_edit_insert_position); - double baf = _mtv.session()->tempo_map().beat_at_frame (step_edit_insert_position); + double baf = max (0.0, _mtv.session()->tempo_map().beat_at_frame (step_edit_insert_position)); double next_bar_in_beats = baf + m.divisions_per_bar(); framecnt_t next_bar_pos = _mtv.session()->tempo_map().frame_at_beat (next_bar_in_beats); framecnt_t len = next_bar_pos - step_edit_insert_position; diff --git a/libs/ardour/tempo.cc b/libs/ardour/tempo.cc index 11da2fc81d..5a75e46eee 100644 --- a/libs/ardour/tempo.cc +++ b/libs/ardour/tempo.cc @@ -1454,6 +1454,14 @@ TempoMap::metric_at (BBT_Time bbt) const return m; } +/** Returns the beat duration corresponding to the supplied frame, possibly returning a negative value. + * @param frame The session frame position. + * @return The beat duration according to the tempo map at the supplied frame. + * If the supplied frame lies before the first meter, the returned beat duration will be negative. + * The returned beat is obtained using the first meter and the continuation of the tempo curve (backwards). + * + * This function uses both tempo and meter. + */ double TempoMap::beat_at_frame (const framecnt_t& frame) const { @@ -1461,7 +1469,7 @@ TempoMap::beat_at_frame (const framecnt_t& frame) const return beat_at_frame_locked (_metrics, frame); } -/* meter / tempo section based */ +/* This function uses both tempo and meter.*/ double TempoMap::beat_at_frame_locked (const Metrics& metrics, const framecnt_t& frame) const { @@ -1478,9 +1486,7 @@ TempoMap::beat_at_frame_locked (const Metrics& metrics, const framecnt_t& frame) prev_m = static_cast<MeterSection*> (*i); } } - if (frame < prev_m->frame()) { - return 0.0; - } + const double beat = prev_m->beat() + (ts.pulse_at_frame (frame, _frame_rate) - prev_m->pulse()) * prev_m->note_divisor(); /* audio locked meters fake their beat */ @@ -2977,6 +2983,15 @@ TempoMap::gui_dilate_tempo (TempoSection* ts, const framepos_t& frame, const fra MetricPositionChanged (); // Emit Signal } +/** Returns the exact beat subdivision closest to the supplied frame, possibly returning a negative value. + * @param frame The session frame position. + * @param sub_num The requested beat subdivision to use when rounding the frame position. + * @return The beat position of the supplied frame. + * If the supplied frame lies before the first meter, the return will be negative. + * The returned beat is obtained using the first meter and the continuation of the tempo curve (backwards). + * + * This function uses both tempo and meter. + */ double TempoMap::exact_beat_at_frame (const framepos_t& frame, const int32_t sub_num) { @@ -2989,6 +3004,7 @@ double TempoMap::exact_beat_at_frame_locked (const Metrics& metrics, const framepos_t& frame, const int32_t sub_num) { double beat = beat_at_frame_locked (metrics, frame); + if (sub_num > 1) { beat = floor (beat) + (floor (((beat - floor (beat)) * (double) sub_num) + 0.5) / sub_num); } else if (sub_num == 1) { @@ -3009,7 +3025,7 @@ TempoMap::bbt_duration_at (framepos_t pos, const BBT_Time& bbt, int dir) { Glib::Threads::RWLock::ReaderLock lm (lock); - const double tick_at_time = beat_at_frame_locked (_metrics, pos) * BBT_Time::ticks_per_beat; + const double tick_at_time = max (0.0, beat_at_frame_locked (_metrics, pos)) * BBT_Time::ticks_per_beat; const double bbt_ticks = bbt.ticks + (bbt.beats * BBT_Time::ticks_per_beat); const double total_beats = (tick_at_time + bbt_ticks) / BBT_Time::ticks_per_beat; @@ -3032,7 +3048,7 @@ framepos_t TempoMap::round_to_beat_subdivision (framepos_t fr, int sub_num, RoundMode dir) { Glib::Threads::RWLock::ReaderLock lm (lock); - uint32_t ticks = (uint32_t) floor (beat_at_frame_locked (_metrics, fr) * BBT_Time::ticks_per_beat); + uint32_t ticks = (uint32_t) floor (max (0.0, beat_at_frame_locked (_metrics, fr)) * BBT_Time::ticks_per_beat); uint32_t beats = (uint32_t) floor (ticks / BBT_Time::ticks_per_beat); uint32_t ticks_one_subdivisions_worth = (uint32_t) BBT_Time::ticks_per_beat / sub_num; @@ -3715,7 +3731,7 @@ TempoMap::insert_time (framepos_t where, framecnt_t amount) bbt.beats = 1; } } - pair<double, BBT_Time> start = make_pair (beat_at_frame_locked (_metrics, m->frame()), bbt); + pair<double, BBT_Time> start = make_pair (max (0.0, beat_at_frame_locked (_metrics, m->frame())), bbt); m->set_beat (start); m->set_pulse (pulse_at_frame_locked (_metrics, m->frame())); meter = m; @@ -3803,28 +3819,7 @@ TempoMap::framepos_plus_beats (framepos_t frame, Evoral::Beats beats) const { Glib::Threads::RWLock::ReaderLock lm (lock); - const TempoSection& ts = tempo_section_at_frame_locked (_metrics, frame); - MeterSection* prev_m = 0; - MeterSection* next_m = 0; - - for (Metrics::const_iterator i = _metrics.begin(); i != _metrics.end(); ++i) { - if (!(*i)->is_tempo()) { - if (prev_m && (*i)->frame() > frame) { - next_m = static_cast<MeterSection*> (*i); - break; - } - prev_m = static_cast<MeterSection*> (*i); - } - } - - double pos_beat = prev_m->beat() + (ts.pulse_at_frame (frame, _frame_rate) - prev_m->pulse()) * prev_m->note_divisor(); - - /* audio locked meters fake their beat */ - if (next_m && next_m->beat() < pos_beat) { - pos_beat = next_m->beat(); - } - - return frame_at_beat_locked (_metrics, pos_beat + beats.to_double()); + return frame_at_beat_locked (_metrics, beat_at_frame_locked (_metrics, frame) + beats.to_double()); } /** Subtract some (fractional) beats from a frame position, and return the result in frames */ |