X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;ds=inline;f=libs%2Fardour%2Ftempo.cc;h=8c710ad180896a95f7284e9ffb050f37540dc119;hb=a68ff8e5408c5043477c3ec6823dd71486380a44;hp=8af5ab3fbebe98621acafd6c896861de51943a11;hpb=8b4f5dcd5f6a570ef920fe77c4dba5242726db5f;p=ardour.git diff --git a/libs/ardour/tempo.cc b/libs/ardour/tempo.cc index 8af5ab3fbe..8c710ad180 100644 --- a/libs/ardour/tempo.cc +++ b/libs/ardour/tempo.cc @@ -879,7 +879,7 @@ TempoMap::do_insert (MetricSection* section) } _metrics.insert (i, section); - //dump (_metrics, std::cerr); + //dump (_metrics, std::cout); } } @@ -1084,7 +1084,7 @@ TempoMap::add_meter (const Meter& meter, const framepos_t& frame, const double& } MeterSection* -TempoMap::add_meter_locked (const Meter& meter, double beat, BBT_Time where, bool recompute) +TempoMap::add_meter_locked (const Meter& meter, double beat, const BBT_Time& where, bool recompute) { /* a new meter always starts a new bar on the first beat. so round the start time appropriately. remember that @@ -1093,14 +1093,9 @@ TempoMap::add_meter_locked (const Meter& meter, double beat, BBT_Time where, boo */ - if (where.beats != 1) { - where.beats = 1; - where.bars++; - } - /* new meters *always* start on a beat. */ - where.ticks = 0; const double pulse = pulse_at_beat_locked (_metrics, beat); MeterSection* new_meter = new MeterSection (pulse, beat, where, meter.divisions_per_bar(), meter.note_divisor()); + do_insert (new_meter); if (recompute) { @@ -1111,19 +1106,19 @@ TempoMap::add_meter_locked (const Meter& meter, double beat, BBT_Time where, boo } MeterSection* -TempoMap::add_meter_locked (const Meter& meter, framepos_t frame, double beat, Timecode::BBT_Time where, bool recompute) +TempoMap::add_meter_locked (const Meter& meter, framepos_t frame, double beat, const Timecode::BBT_Time& where, bool recompute) { + /* add meter-locked tempo */ + TempoSection* t = add_tempo_locked (tempo_at_locked (_metrics, frame), frame, true, TempoSection::Ramp); + if (t) { + t->set_locked_to_meter (true); + } + MeterSection* new_meter = new MeterSection (frame, beat, where, meter.divisions_per_bar(), meter.note_divisor()); - TempoSection* t = 0; - double pulse = pulse_at_frame_locked (_metrics, frame); - new_meter->set_pulse (pulse); + new_meter->set_pulse (pulse_at_frame_locked (_metrics, frame)); do_insert (new_meter); - /* add meter-locked tempo */ - t = add_tempo_locked (tempo_at_locked (_metrics, frame), frame, true, TempoSection::Ramp); - t->set_locked_to_meter (true); - if (recompute) { solve_map (_metrics, new_meter, frame); } @@ -1365,7 +1360,6 @@ TempoMap::recompute_meters (Metrics& metrics) } if (meter_locked_tempo) { meter_locked_tempo->set_pulse (pulse); - recompute_tempos (metrics); } meter->set_beat (b_bbt); meter->set_pulse (pulse); @@ -1398,7 +1392,6 @@ TempoMap::recompute_meters (Metrics& metrics) prev_m = meter; } } - //dump (_metrics, std::cerr; } void @@ -2025,8 +2018,6 @@ TempoMap::solve_map (Metrics& imaginary, TempoSection* section, const framepos_t return true; } - //dump (imaginary, std::cerr); - return false; } @@ -2100,8 +2091,6 @@ TempoMap::solve_map (Metrics& imaginary, TempoSection* section, const double& pu return true; } - //dump (imaginary, std::cerr); - return false; } @@ -2261,7 +2250,7 @@ TempoMap::solve_map (Metrics& imaginary, MeterSection* section, const framepos_t } else { recompute_meters (imaginary); } - //dump (imaginary, std::cerr); + return true; } @@ -2272,7 +2261,7 @@ TempoMap::solve_map (Metrics& imaginary, MeterSection* section, const BBT_Time& for (Metrics::iterator i = imaginary.begin(); i != imaginary.end(); ++i) { MeterSection* m; if ((m = dynamic_cast (*i)) != 0) { - if (m->bbt().bars == when.bars) { + if (m != section && m->bbt().bars == when.bars) { return false; } } @@ -2368,6 +2357,7 @@ TempoMap::solve_map (Metrics& imaginary, MeterSection* section, const BBT_Time& MetricSectionSorter cmp; imaginary.sort (cmp); + if (section->position_lock_style() == AudioTime) { /* we're setting the pulse */ section->set_position_lock_style (MusicTime); @@ -2563,28 +2553,6 @@ TempoMap::gui_move_tempo_beat (TempoSection* ts, const double& beat) MetricPositionChanged (); // Emit Signal } -void -TempoMap::gui_move_tempo_pulse (TempoSection* ts, const double& pulse) -{ - Metrics future_map; - { - Glib::Threads::RWLock::WriterLock lm (lock); - TempoSection* tempo_copy = copy_metrics_and_point (_metrics, future_map, ts); - if (solve_map (future_map, tempo_copy, pulse)) { - solve_map (_metrics, ts, pulse); - recompute_meters (_metrics); - } - } - - Metrics::const_iterator d = future_map.begin(); - while (d != future_map.end()) { - delete (*d); - ++d; - } - - MetricPositionChanged (); // Emit Signal -} - void TempoMap::gui_move_meter (MeterSection* ms, const framepos_t& frame) { @@ -2664,6 +2632,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; @@ -2688,8 +2660,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. */ @@ -2739,12 +2711,6 @@ TempoMap::gui_dilate_tempo (MeterSection* ms, const framepos_t& frame) new_bpm = prev_t->tempo_at_frame (prev_t->frame() + fr_off, _frame_rate) * (double) prev_t->note_type(); } - const double diff = (prev_t->tempo_at_frame (frame, _frame_rate) * prev_t->note_type()) - prev_t->beats_per_minute(); - if (diff > -0.1 && diff < 0.1) { - new_bpm = prev_t->beats_per_minute() * ((ms->frame() - prev_t->frame()) - / (double) ((ms->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(); @@ -2752,13 +2718,13 @@ TempoMap::gui_dilate_tempo (MeterSection* ms, const framepos_t& frame) /* 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(); } + } - /* limits - a bit clunky, but meh */ - const double diff = (prev_t->tempo_at_frame (frame, _frame_rate) * prev_t->note_type()) - prev_t->beats_per_minute(); - if (diff > -0.1 && diff < 0.1) { - new_bpm = prev_t->beats_per_minute() * ((ms->frame() - prev_t->frame()) - / (double) ((ms->frame() + prev_t_frame_contribution) - prev_t->frame())); - } + /* limits - a bit clunky, but meh */ + const double diff = (prev_t->tempo_at_frame (frame, _frame_rate) * prev_t->note_type()) - prev_t->beats_per_minute(); + if (diff > -1.0 && diff < 1.0) { + new_bpm = prev_t->beats_per_minute() * ((ms->frame() - prev_t->frame()) + / (double) ((ms->frame() + prev_t_frame_contribution) - prev_t->frame())); } prev_t->set_beats_per_minute (new_bpm); @@ -2788,6 +2754,129 @@ TempoMap::gui_dilate_tempo (MeterSection* ms, const framepos_t& frame) MetricPositionChanged (); // Emit Signal } +void +TempoMap::gui_dilate_tempo (TempoSection* ts, const framepos_t& frame, const framepos_t& end_frame, const double& pulse) +{ + /* + Ts (future prev_t) Tnext + | | + | [drag^] | + |----------|---------- + e_f pulse(frame) + */ + + Metrics future_map; + + { + Glib::Threads::RWLock::WriterLock lm (lock); + + 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; + + if (prev_t && prev_t->pulse() > 0.0) { + prev_to_prev_t = const_cast(&tempo_section_at_locked (future_map, prev_t->frame() - 1)); + } + + TempoSection* next_t = 0; + for (Metrics::iterator i = future_map.begin(); i != future_map.end(); ++i) { + TempoSection* t = 0; + if ((t = dynamic_cast (*i)) != 0) { + if (t->frame() > ts->frame()) { + next_t = t; + break; + } + } + } + + /* 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; + double start_pulse = prev_t->pulse_at_frame (frame, _frame_rate); + + if (next_t && prev_to_prev_t && prev_to_prev_t->type() == TempoSection::Ramp) { + contribution = (prev_t->frame() - prev_to_prev_t->frame()) / (double) (next_t->frame() - prev_to_prev_t->frame()); + } + + frameoffset_t prev_t_frame_contribution = fr_off - (contribution * (double) fr_off); + double end_pulse = prev_t->pulse_at_frame (end_frame, _frame_rate); + double new_bpm; + + 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_to_prev_t->frame()) + / (double) ((frame + prev_t_frame_contribution) - prev_to_prev_t->frame())); + + } else { + /* prev to prev is irrelevant */ + + if (start_pulse != prev_t->pulse()) { + new_bpm = prev_t->beats_per_minute() * ((start_pulse - prev_t->pulse()) / (end_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 { + + double frame_ratio; + double pulse_ratio; + const framepos_t pulse_pos = prev_t->frame_at_pulse (pulse, _frame_rate); + + if (prev_to_prev_t) { + + frame_ratio = (((pulse_pos - fr_off) - prev_to_prev_t->frame()) / (double) ((pulse_pos) - prev_to_prev_t->frame())); + pulse_ratio = ((start_pulse - prev_to_prev_t->pulse()) / (end_pulse - prev_to_prev_t->pulse())); + } else { + + frame_ratio = (((pulse_pos - fr_off) - prev_t->frame()) / (double) ((pulse_pos) - prev_t->frame())); + pulse_ratio = (start_pulse / end_pulse); + } + new_bpm = prev_t->beats_per_minute() * (pulse_ratio * frame_ratio); + } + + prev_t->set_beats_per_minute (new_bpm); + recompute_tempos (future_map); + recompute_meters (future_map); + + if (check_solved (future_map, true)) { + ts->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) {