diff options
Diffstat (limited to 'libs/ardour/tempo.cc')
-rw-r--r-- | libs/ardour/tempo.cc | 135 |
1 files changed, 133 insertions, 2 deletions
diff --git a/libs/ardour/tempo.cc b/libs/ardour/tempo.cc index 3227278875..7fd41b12c1 100644 --- a/libs/ardour/tempo.cc +++ b/libs/ardour/tempo.cc @@ -2654,6 +2654,10 @@ TempoMap::gui_dilate_tempo (MeterSection* ms, const framepos_t& frame) Metrics future_map; TempoSection* ts = 0; + if (frame <= first_meter().frame()) { + return; + } + if (ms->position_lock_style() == AudioTime) { /* disabled for now due to faked tempo locked to meter pulse */ return; @@ -2678,8 +2682,8 @@ TempoMap::gui_dilate_tempo (MeterSection* ms, const framepos_t& frame) constant to constant is straightforward, as the tempo prev to prev_t has constant slope. */ double contribution = 0.0; - frameoffset_t frame_contribution = 0.0; - frameoffset_t prev_t_frame_contribution = 0.0; + frameoffset_t frame_contribution = 0; + frameoffset_t prev_t_frame_contribution = fr_off; if (prev_to_prev_t && prev_to_prev_t->type() == TempoSection::Ramp) { /* prev to prev_t's position will remain constant in terms of frame and pulse. lets use frames. */ @@ -2778,6 +2782,133 @@ TempoMap::gui_dilate_tempo (MeterSection* ms, const framepos_t& frame) MetricPositionChanged (); // Emit Signal } +void +TempoMap::gui_dilate_tempo (const framepos_t& frame, const framepos_t& end_frame) +{ + Metrics future_map; + TempoSection* ts = 0; + + + { + Glib::Threads::RWLock::WriterLock lm (lock); + ts = const_cast<TempoSection*>(&tempo_section_at_locked (_metrics, frame - 1)); + if (!ts) { + return; + } + TempoSection* prev_t = copy_metrics_and_point (_metrics, future_map, ts); + TempoSection* prev_to_prev_t = 0; + const frameoffset_t fr_off = end_frame - frame; + double new_bpm = 0.0; + + if (prev_t && prev_t->pulse() > 0.0) { + prev_to_prev_t = const_cast<TempoSection*>(&tempo_section_at_locked (future_map, prev_t->frame() - 1)); + } + + /* the change in frames is the result of changing the slope of at most 2 previous tempo sections. + constant to constant is straightforward, as the tempo prev to prev_t has constant slope. + */ + double contribution = 0.0; + frameoffset_t frame_contribution = 0; + frameoffset_t prev_t_frame_contribution = fr_off; + + if (prev_to_prev_t && prev_to_prev_t->type() == TempoSection::Ramp) { + /* prev to prev_t's position will remain constant in terms of frame and pulse. lets use frames. */ + contribution = (prev_t->frame() - prev_to_prev_t->frame()) / (double) (frame - prev_to_prev_t->frame()); + frame_contribution = contribution * (double) fr_off; + prev_t_frame_contribution -= frame_contribution; + } + + if (prev_t->type() == TempoSection::Constant || prev_t->c_func() == 0.0) { + + if (prev_t->position_lock_style() == MusicTime) { + if (prev_to_prev_t && prev_to_prev_t->type() == TempoSection::Ramp) { + new_bpm = prev_t->beats_per_minute() * ((frame - prev_t->frame()) + / (double) (frame + prev_t_frame_contribution - prev_t->frame())); + + } else { + /* prev to prev is irrelevant */ + const double meter_pulse = prev_t->pulse_at_frame (frame, _frame_rate); + const double frame_pulse = prev_t->pulse_at_frame (end_frame, _frame_rate); + + if (frame_pulse != prev_t->pulse()) { + new_bpm = prev_t->beats_per_minute() * ((meter_pulse - prev_t->pulse()) / (frame_pulse - prev_t->pulse())); + } else { + new_bpm = prev_t->beats_per_minute(); + } + } + } else { + /* AudioTime */ + if (prev_to_prev_t && prev_to_prev_t->type() == TempoSection::Ramp) { + new_bpm = prev_t->beats_per_minute() * ((frame - prev_t->frame()) + / (double) (frame + prev_t_frame_contribution - prev_t->frame())); + } else { + /* prev_to_prev_t is irrelevant */ + + if (end_frame != prev_t->frame()) { + new_bpm = prev_t->beats_per_minute() * ((frame - prev_t->frame()) / (double) (end_frame - prev_t->frame())); + } else { + new_bpm = prev_t->beats_per_minute(); + } + } + } + } else if (prev_t->c_func() < 0.0) { + if (prev_to_prev_t && prev_to_prev_t->type() == TempoSection::Ramp) { + new_bpm = prev_t->tempo_at_frame (prev_t->frame() + frame_contribution, _frame_rate) * (double) prev_t->note_type(); + } else { + /* prev_to_prev_t is irrelevant */ + new_bpm = prev_t->tempo_at_frame (prev_t->frame() + fr_off, _frame_rate) * (double) prev_t->note_type(); + + } + const double end_minute = ((end_frame - prev_t->frame()) / (double) _frame_rate) / 60.0; + const double end_tempo = prev_t->tempo_at_frame (end_frame, _frame_rate); + const double future_c = log (end_tempo / (new_bpm / (double) prev_t->note_type())) / end_minute; + + /* limits - a bit clunky, but meh */ + if (future_c > -20.1 && future_c < 20.1) { + new_bpm = prev_t->beats_per_minute() * ((frame - prev_t->frame()) + / (double) ((frame + prev_t_frame_contribution) - prev_t->frame())); + } + + } else if (prev_t->c_func() > 0.0) { + if (prev_to_prev_t && prev_to_prev_t->type() == TempoSection::Ramp) { + new_bpm = prev_t->tempo_at_frame (prev_t->frame() - frame_contribution, _frame_rate) * (double) prev_t->note_type(); + } else { + /* prev_to_prev_t is irrelevant */ + new_bpm = prev_t->tempo_at_frame (prev_t->frame() - fr_off, _frame_rate) * (double) prev_t->note_type(); + } + const double end_minute = ((end_frame - prev_t->frame()) / (double) _frame_rate) / 60.0; + const double end_tempo = prev_t->tempo_at_frame (end_frame, _frame_rate); + const double future_c = log (end_tempo / (new_bpm / (double) prev_t->note_type())) / end_minute; + + /* limits - a bit clunky, but meh */ + if (future_c > -20.1 && future_c < 20.1) { + new_bpm = prev_t->beats_per_minute() * ((frame - prev_t->frame()) + / (double) ((frame + prev_t_frame_contribution) - prev_t->frame())); + } + } + + prev_t->set_beats_per_minute (new_bpm); + recompute_tempos (future_map); + recompute_meters (future_map); + + if (check_solved (future_map, true)) { + + prev_t = const_cast<TempoSection*>(&tempo_section_at_locked (_metrics, frame - 1)); + prev_t->set_beats_per_minute (new_bpm); + recompute_tempos (_metrics); + recompute_meters (_metrics); + } + } + + Metrics::const_iterator d = future_map.begin(); + while (d != future_map.end()) { + delete (*d); + ++d; + } + + MetricPositionChanged (); // Emit Signal +} + framecnt_t TempoMap::bbt_duration_at (framepos_t pos, const BBT_Time& bbt, int dir) { |