From 3a0a628a75fdbc9da1c0ad2a21f46286a5184503 Mon Sep 17 00:00:00 2001 From: nick_m Date: Sun, 16 Oct 2016 02:33:49 +1100 Subject: [PATCH] Rework duration clock and TempoMap::insert_time to include meter at offset. - should fix 7072 - also fixes scroll behavior over multiple tempi. --- gtk2_ardour/audio_clock.cc | 63 +++++++++++-- gtk2_ardour/audio_clock.h | 2 +- libs/ardour/tempo.cc | 178 ++++++++++++------------------------- 3 files changed, 114 insertions(+), 129 deletions(-) diff --git a/gtk2_ardour/audio_clock.cc b/gtk2_ardour/audio_clock.cc index ed81b6db21..7e490b4fdc 100644 --- a/gtk2_ardour/audio_clock.cc +++ b/gtk2_ardour/audio_clock.cc @@ -1003,7 +1003,7 @@ AudioClock::set (framepos_t when, bool force, framecnt_t offset) break; case BBT: - set_bbt (when, force); + set_bbt (when, offset, force); break; case MinSec: @@ -1226,7 +1226,7 @@ AudioClock::set_timecode (framepos_t when, bool /*force*/) } void -AudioClock::set_bbt (framepos_t when, bool /*force*/) +AudioClock::set_bbt (framepos_t when, framecnt_t offset, bool /*force*/) { char buf[16]; Timecode::BBT_Time BBT; @@ -1253,9 +1253,58 @@ AudioClock::set_bbt (framepos_t when, bool /*force*/) BBT.beats = 0; BBT.ticks = 0; } else { - BBT = _session->tempo_map().bbt_at_frame (when); - BBT.bars--; - BBT.beats--; + TempoMap& tmap (_session->tempo_map()); + const double divisions = tmap.meter_section_at_frame (offset).divisions_per_bar(); + + if (negative) { + BBT = tmap.bbt_at_beat (tmap.beat_at_frame (offset)); + Timecode::BBT_Time when_bbt = tmap.bbt_at_frame (offset - when); + + BBT.bars -= when_bbt.bars; + + if (BBT.ticks < when_bbt.ticks) { + if (BBT.beats == 1) { + BBT.bars--; + BBT.beats = divisions; + } else { + BBT.beats--; + } + BBT.ticks = Timecode::BBT_Time::ticks_per_beat - (when_bbt.ticks - BBT.ticks); + } else { + BBT.ticks -= when_bbt.ticks; + } + + if (BBT.beats < when_bbt.beats) { + BBT.bars--; + BBT.beats = divisions - (when_bbt.beats - BBT.beats); + } else { + BBT.beats -= when_bbt.beats; + } + } else { + BBT = tmap.bbt_at_beat (tmap.beat_at_frame (when + offset)); + Timecode::BBT_Time when_bbt = tmap.bbt_at_frame (offset); + + BBT.bars -= when_bbt.bars; + + if (BBT.ticks < when_bbt.ticks) { + if (BBT.beats == 1) { + BBT.bars--; + BBT.beats = divisions; + } else { + BBT.beats--; + } + BBT.ticks = Timecode::BBT_Time::ticks_per_beat - (when_bbt.ticks - BBT.ticks); + } else { + BBT.ticks -= when_bbt.ticks; + } + + if (BBT.beats < when_bbt.beats) { + BBT.bars--; + BBT.beats = divisions - (when_bbt.beats - BBT.beats); + } else { + BBT.beats -= when_bbt.beats; + } + } } } else { BBT = _session->tempo_map().bbt_at_frame (when); @@ -1732,7 +1781,7 @@ AudioClock::on_scroll_event (GdkEventScroll *ev) switch (ev->direction) { case GDK_SCROLL_UP: - frames = get_frame_step (f); + frames = get_frame_step (f, current_time(), 1); if (frames != 0) { if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) { frames *= 10; @@ -1743,7 +1792,7 @@ AudioClock::on_scroll_event (GdkEventScroll *ev) break; case GDK_SCROLL_DOWN: - frames = get_frame_step (f); + frames = get_frame_step (f, current_time(), -1); if (frames != 0) { if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) { frames *= 10; diff --git a/gtk2_ardour/audio_clock.h b/gtk2_ardour/audio_clock.h index 51cac850a0..79d05f62fe 100644 --- a/gtk2_ardour/audio_clock.h +++ b/gtk2_ardour/audio_clock.h @@ -209,7 +209,7 @@ class AudioClock : public CairoWidget, public ARDOUR::SessionHandlePtr void set_slave_info (); void set_timecode (framepos_t, bool); - void set_bbt (framepos_t, bool); + void set_bbt (framepos_t, ARDOUR::framecnt_t, bool); void set_minsec (framepos_t, bool); void set_frames (framepos_t, bool); diff --git a/libs/ardour/tempo.cc b/libs/ardour/tempo.cc index 27ba9f6223..1d6f4eccf2 100644 --- a/libs/ardour/tempo.cc +++ b/libs/ardour/tempo.cc @@ -3192,11 +3192,52 @@ TempoMap::bbt_duration_at (framepos_t pos, const BBT_Time& bbt, int dir) { Glib::Threads::RWLock::ReaderLock lm (lock); - 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; + BBT_Time pos_bbt = bbt_at_frame_locked (_metrics, pos); + const framecnt_t offset = frame_at_bbt_locked (_metrics, pos_bbt); + const double divisions = meter_section_at_frame_locked (_metrics, pos).divisions_per_bar(); - return frame_at_beat_locked (_metrics, total_beats); + if (dir > 0) { + pos_bbt.bars += bbt.bars; + + pos_bbt.ticks += bbt.ticks; + if ((double) pos_bbt.ticks > BBT_Time::ticks_per_beat) { + pos_bbt.beats += 1; + pos_bbt.ticks -= BBT_Time::ticks_per_beat; + } + + pos_bbt.beats += bbt.beats; + if ((double) pos_bbt.beats > divisions) { + pos_bbt.bars += 1; + pos_bbt.beats -= divisions; + } + + return frame_at_bbt_locked (_metrics, pos_bbt) - offset; + } else { + pos_bbt.bars -= bbt.bars; + + if (pos_bbt.ticks < bbt.ticks) { + if (pos_bbt.beats == 1) { + pos_bbt.bars--; + pos_bbt.beats = divisions; + } else { + pos_bbt.beats--; + } + pos_bbt.ticks = BBT_Time::ticks_per_beat - (bbt.ticks - pos_bbt.ticks); + } else { + pos_bbt.ticks -= bbt.ticks; + } + + if (pos_bbt.beats <= bbt.beats) { + pos_bbt.bars--; + pos_bbt.beats = divisions - (bbt.beats - pos_bbt.beats); + } else { + pos_bbt.beats -= bbt.beats; + } + + return offset - frame_at_bbt_locked (_metrics, pos_bbt); + } + + return 0; } framepos_t @@ -3890,129 +3931,24 @@ TempoMap::n_meters() const void TempoMap::insert_time (framepos_t where, framecnt_t amount) { - { - Glib::Threads::RWLock::WriterLock lm (lock); - for (Metrics::iterator i = _metrics.begin(); i != _metrics.end(); ++i) { - if ((*i)->frame() >= where && (*i)->movable ()) { - (*i)->set_frame ((*i)->frame() + amount); + for (Metrics::reverse_iterator i = _metrics.rbegin(); i != _metrics.rend(); ++i) { + if ((*i)->frame() >= where && (*i)->movable ()) { + MeterSection* ms; + TempoSection* ts; + + if ((ms = dynamic_cast (*i)) != 0) { + gui_move_meter (ms, (*i)->frame() + amount); + } + + if ((ts = dynamic_cast (*i)) != 0) { + gui_move_tempo (ts, (*i)->frame() + amount, 0); } } - - /* now reset the BBT time of all metrics, based on their new - * audio time. This is the only place where we do this reverse - * timestamp. - */ - - Metrics::iterator i; - const MeterSection* meter; - const TempoSection* tempo; - MeterSection *m; - TempoSection *t; - - meter = &first_meter (); - tempo = &first_tempo (); - - BBT_Time start; - BBT_Time end; - - // cerr << "\n###################### TIMESTAMP via AUDIO ##############\n" << endl; - - bool first = true; - MetricSection* prev = 0; - - for (i = _metrics.begin(); i != _metrics.end(); ++i) { - - BBT_Time bbt; - //TempoMetric metric (*meter, *tempo); - MeterSection* ms = const_cast(meter); - TempoSection* ts = const_cast(tempo); - if (prev) { - if (ts){ - if ((t = dynamic_cast(prev)) != 0) { - if (!t->active()) { - continue; - } - ts->set_pulse (t->pulse()); - } - if ((m = dynamic_cast(prev)) != 0) { - ts->set_pulse (m->pulse()); - } - ts->set_frame (prev->frame()); - - } - if (ms) { - if ((m = dynamic_cast(prev)) != 0) { - pair start = make_pair (m->beat(), m->bbt()); - ms->set_beat (start); - ms->set_pulse (m->pulse()); - } - if ((t = dynamic_cast(prev)) != 0) { - if (!t->active()) { - continue; - } - const double beat = beat_at_pulse_locked (_metrics, t->pulse()); - pair start = make_pair (beat, bbt_at_beat_locked (_metrics, beat)); - ms->set_beat (start); - ms->set_pulse (t->pulse()); - } - ms->set_frame (prev->frame()); - } - - } else { - // metric will be at frames=0 bbt=1|1|0 by default - // which is correct for our purpose - } - - // cerr << bbt << endl; - - if ((t = dynamic_cast(*i)) != 0) { - if (!t->active()) { - continue; - } - t->set_pulse (pulse_at_frame_locked (_metrics, m->frame())); - tempo = t; - // cerr << "NEW TEMPO, frame = " << (*i)->frame() << " beat = " << (*i)->pulse() <(*i)) != 0) { - bbt = bbt_at_frame_locked (_metrics, m->frame()); - - // cerr << "timestamp @ " << (*i)->frame() << " with " << bbt.bars << "|" << bbt.beats << "|" << bbt.ticks << " => "; - - if (first) { - first = false; - } else { - - if (bbt.ticks > BBT_Time::ticks_per_beat/2) { - /* round up to next beat */ - bbt.beats += 1; - } - - bbt.ticks = 0; - - if (bbt.beats != 1) { - /* round up to next bar */ - bbt.bars += 1; - bbt.beats = 1; - } - } - pair 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; - // cerr << "NEW METER, frame = " << (*i)->frame() << " beat = " << (*i)->pulse() <