diff --git a/gtk2_ardour/midi_region_view.cc b/gtk2_ardour/midi_region_view.cc index e3ff928e1d..f31735fcd2 100644 --- a/gtk2_ardour/midi_region_view.cc +++ b/gtk2_ardour/midi_region_view.cc @@ -1703,22 +1703,26 @@ void MidiRegionView::update_sustained (Note* ev, bool update_ghost_regions) { boost::shared_ptr note = ev->note(); - const double x = trackview.editor().sample_to_pixel (source_beats_to_region_frames (note->time())); + const double x0 = trackview.editor().sample_to_pixel (source_beats_to_region_frames (note->time())); + double x1; const double y0 = 1 + floor(midi_stream_view()->note_to_y(note->note())); - - ev->set_x0 (x); - ev->set_y0 (y0); + double y1; /* trim note display to not overlap the end of its region */ if (note->length() > 0) { const framepos_t note_end_frames = min (source_beats_to_region_frames (note->end_time()), _region->length()); - ev->set_x1 (std::max(1., trackview.editor().sample_to_pixel (note_end_frames)) - 1); + x1 = std::max(1., trackview.editor().sample_to_pixel (note_end_frames)) - 1; } else { - ev->set_x1 (std::max(1., trackview.editor().sample_to_pixel (_region->length())) - 1); + x1 = std::max(1., trackview.editor().sample_to_pixel (_region->length())) - 1; } - ev->set_y1 (y0 + std::max(1., floor(midi_stream_view()->note_height()) - 1)); + y1 = y0 + std::max(1., floor(midi_stream_view()->note_height()) - 1); + + ev->set_x0 (x0); + ev->set_x1 (x1); + ev->set_y0 (y0); + ev->set_y1 (y1); if (!note->length()) { if (_active_notes && note->note() < 128) { @@ -1726,7 +1730,7 @@ MidiRegionView::update_sustained (Note* ev, bool update_ghost_regions) if (old_rect) { /* There is an active note on this key, so we have a stuck note. Finish the old rectangle here. */ - old_rect->set_x1 (x); + old_rect->set_x1 (x1); old_rect->set_outline_all (); } _active_notes[note->note()] = ev; @@ -2508,6 +2512,8 @@ MidiRegionView::move_selection(double dx, double dy, double cumulative_dy) to_play.push_back ((*i)->note()); } (*i)->move_event(dx, dy); + Note* canvas_note = dynamic_cast(*i); + canvas_note->set_x1 (snap_to_pixel (canvas_note->x1(), false)); } if (dy && !_selection.empty() && !_no_sound_notes && UIConfiguration::instance().get_sound_midi_notes()) { diff --git a/libs/ardour/ardour/tempo.h b/libs/ardour/ardour/tempo.h index 10cf44e06c..a73379b62f 100644 --- a/libs/ardour/ardour/tempo.h +++ b/libs/ardour/ardour/tempo.h @@ -435,8 +435,9 @@ private: double beat_at_frame_locked (const Metrics& metrics, framecnt_t frame) const; framecnt_t frame_at_beat_locked (const Metrics& metrics, double beat) const; double tick_at_frame_locked (const Metrics& metrics, framecnt_t frame) const; + double tick_offset_at (const Metrics& metrics, double tick) const; - framecnt_t frame_offset_at (const Metrics& metrics, framepos_t frame) const; + frameoffset_t frame_offset_at (const Metrics& metrics, framepos_t frame) const; framecnt_t frame_at_tick_locked (const Metrics& metrics, double tick) const; framepos_t frame_time_locked (const Metrics& metrics, const Timecode::BBT_Time&); diff --git a/libs/ardour/tempo.cc b/libs/ardour/tempo.cc index 66a10e4483..7c4ffd6a10 100644 --- a/libs/ardour/tempo.cc +++ b/libs/ardour/tempo.cc @@ -1529,7 +1529,9 @@ TempoMap::bbt_to_beats_locked (const Metrics& metrics, Timecode::BBT_Time bbt) double accumulated_beats = 0.0; double accumulated_bars = 0.0; MeterSection* prev_ms = 0; - + /* because audio-locked meters have 'fake' integral beats, + we don't have to worry about any offset here. + */ for (Metrics::const_iterator i = metrics.begin(); i != metrics.end(); ++i) { MeterSection* m; if ((m = dynamic_cast (*i)) != 0) { @@ -1651,6 +1653,35 @@ TempoMap::tick_at_frame_locked (const Metrics& metrics, framecnt_t frame) const } +framecnt_t +TempoMap::frame_at_tick_locked (const Metrics& metrics, double tick) const +{ + /* HOLD THE READER LOCK */ + + const TempoSection* prev_ts = 0; + double accumulated_ticks = 0.0; + + for (Metrics::const_iterator i = metrics.begin(); i != metrics.end(); ++i) { + TempoSection* t; + + if ((t = dynamic_cast (*i)) != 0) { + if (prev_ts && t->tick() > tick) { + return prev_ts->frame_at_tick (tick, _frame_rate); + } + + accumulated_ticks = t->tick(); + prev_ts = t; + } + } + /* must be treated as constant, irrespective of _type */ + double const ticks_in_section = tick - accumulated_ticks; + double const dtime = (ticks_in_section / BBT_Time::ticks_per_beat) * prev_ts->frames_per_beat (_frame_rate); + + framecnt_t const ret = (((framecnt_t) floor (dtime)) + prev_ts->frame()); + + return ret; +} + double TempoMap::tick_offset_at (const Metrics& metrics, double tick) const { @@ -1675,10 +1706,10 @@ TempoMap::tick_offset_at (const Metrics& metrics, double tick) const return beat_off; } -framecnt_t +frameoffset_t TempoMap::frame_offset_at (const Metrics& metrics, framepos_t frame) const { - framecnt_t frame_off = 0; + frameoffset_t frame_off = 0; for (Metrics::const_iterator i = metrics.begin(); i != metrics.end(); ++i) { MeterSection* m = 0; @@ -1687,7 +1718,7 @@ TempoMap::frame_offset_at (const Metrics& metrics, framepos_t frame) const break; } if (m->position_lock_style() == AudioTime) { - frame_off = frame_at_beat_locked (metrics, m->beat()) - m->frame(); + frame_off += frame_at_beat_locked (metrics, m->beat()) - m->frame(); } } } @@ -1695,36 +1726,6 @@ TempoMap::frame_offset_at (const Metrics& metrics, framepos_t frame) const return frame_off; } -framecnt_t -TempoMap::frame_at_tick_locked (const Metrics& metrics, double tick) const -{ - /* HOLD THE READER LOCK */ - - const TempoSection* prev_ts = 0; - double accumulated_ticks = 0.0; - - for (Metrics::const_iterator i = metrics.begin(); i != metrics.end(); ++i) { - TempoSection* t; - - if ((t = dynamic_cast (*i)) != 0) { - if (prev_ts && t->tick() > tick) { - /* prev_ts is the one affecting us. */ - return prev_ts->frame_at_tick (tick, _frame_rate); - } - - accumulated_ticks = t->tick(); - prev_ts = t; - } - } - /* must be treated as constant, irrespective of _type */ - double const ticks_in_section = tick - accumulated_ticks; - double const dtime = (ticks_in_section / BBT_Time::ticks_per_beat) * prev_ts->frames_per_beat (_frame_rate); - - framecnt_t const ret = (((framecnt_t) floor (dtime)) + prev_ts->frame()); - - return ret; -} - double TempoMap::beat_at_frame (framecnt_t frame) const { @@ -1943,7 +1944,6 @@ TempoMap::solve_map (Metrics& imaginary, TempoSection* section, const Tempo& bpm } imaginary.sort (cmp); - if (section->position_lock_style() == AudioTime) { /* we're setting the beat */ section->set_position_lock_style (MusicTime); @@ -2094,9 +2094,11 @@ TempoMap::bbt_duration_at (framepos_t pos, const BBT_Time& bbt, int dir) framecnt_t const ret = time_at_bbt - offset_pos; return ret - frame_offset_at (_metrics, pos); } + double const ticks = bbt.ticks + (bbt.beats * BBT_Time::ticks_per_beat); framecnt_t const ret = (framecnt_t) floor ((ticks / BBT_Time::ticks_per_beat) * first->frames_per_beat(_frame_rate)); - return ret - frame_offset_at (_metrics, pos); + /* daft */ + return (offset_pos + ret) - frame_offset_at (_metrics, pos); } framepos_t @@ -2272,11 +2274,12 @@ TempoMap::get_grid (vector& points, while (cnt <= upper_beat) { framecnt_t pos = frame_at_beat_locked (_metrics, cnt); - framecnt_t const frame_offset = frame_offset_at (_metrics, pos); + Tempo const tempo = tempo_at (pos); + + frameoffset_t const frame_offset = frame_offset_at (_metrics, pos); pos -= frame_offset; MeterSection const meter = meter_section_at (pos); - Tempo const tempo = tempo_at (pos); BBT_Time const bbt = beats_to_bbt_locked (_metrics, (double) cnt); points.push_back (BBTPoint (meter, tempo, pos, bbt.bars, bbt.beats)); @@ -2348,7 +2351,7 @@ const Tempo TempoMap::tempo_at (framepos_t frame) const { Glib::Threads::RWLock::ReaderLock lm (lock); - + frameoffset_t const frame_off = frame + frame_offset_at (_metrics, frame); TempoSection* prev_ts = 0; Metrics::const_iterator i; @@ -2356,9 +2359,9 @@ TempoMap::tempo_at (framepos_t frame) const for (i = _metrics.begin(); i != _metrics.end(); ++i) { TempoSection* t; if ((t = dynamic_cast (*i)) != 0) { - if ((prev_ts) && t->frame() > frame) { + if ((prev_ts) && t->frame() > frame_off) { /* this is the one past frame */ - double const ret = prev_ts->tempo_at_frame (frame, _frame_rate); + double const ret = prev_ts->tempo_at_frame (frame_off, _frame_rate); Tempo const ret_tempo (ret, prev_ts->note_type()); return ret_tempo; } @@ -2376,7 +2379,7 @@ const MeterSection& TempoMap::meter_section_at (framepos_t frame) const { Glib::Threads::RWLock::ReaderLock lm (lock); - + framepos_t const frame_off = frame + frame_offset_at (_metrics, frame); Metrics::const_iterator i; MeterSection* prev = 0; @@ -2385,7 +2388,7 @@ TempoMap::meter_section_at (framepos_t frame) const if ((t = dynamic_cast (*i)) != 0) { - if ((*i)->frame() > frame) { + if ((*i)->frame() > frame_off) { break; } @@ -2433,7 +2436,9 @@ TempoMap::meter_section_at (double beat) const const Meter& TempoMap::meter_at (framepos_t frame) const { - TempoMetric m (metric_at (frame)); + framepos_t const frame_off = frame + frame_offset_at (_metrics, frame); + TempoMetric m (metric_at (frame_off)); + return m.meter(); }