From cb567dd8818cf4d871a1f77385a3ce8f8c1f91ed Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Thu, 3 Nov 2016 10:44:17 +0000 Subject: [PATCH] remove complex iterator from Evoral::Sequence and replace with wrapping a normal std::multiset iterator --- libs/ardour/ardour/midi_source.h | 1 - libs/ardour/midi_model.cc | 6 +- libs/ardour/midi_region.cc | 7 +- libs/ardour/midi_source.cc | 183 +++++--------- libs/ardour/midi_stretch.cc | 2 +- libs/evoral/evoral/Sequence.hpp | 92 ++----- libs/evoral/src/Sequence.cpp | 405 +------------------------------ 7 files changed, 90 insertions(+), 606 deletions(-) diff --git a/libs/ardour/ardour/midi_source.h b/libs/ardour/ardour/midi_source.h index 29f88773a9..731fd1d835 100644 --- a/libs/ardour/ardour/midi_source.h +++ b/libs/ardour/ardour/midi_source.h @@ -236,7 +236,6 @@ class LIBARDOUR_API MidiSource : virtual public Source, public boost::enable_sha mutable bool _model_iter_valid; mutable Evoral::Beats _length_beats; - mutable framepos_t _last_read_end; /** The total duration of the current capture. */ framepos_t _capture_length; diff --git a/libs/ardour/midi_model.cc b/libs/ardour/midi_model.cc index d410b1ab3e..e50a3678ef 100644 --- a/libs/ardour/midi_model.cc +++ b/libs/ardour/midi_model.cc @@ -1428,7 +1428,7 @@ MidiModel::write_to (boost::shared_ptr source, source->drop_model(source_lock); source->mark_streaming_midi_write_started (source_lock, note_mode()); - for (Evoral::Sequence::const_iterator i = begin(TimeType(), true); i != end(); ++i) { + for (Evoral::Sequence::const_iterator i = begin (); i != end(); ++i) { source->append_event_beats(source_lock, *i); } @@ -1466,7 +1466,7 @@ MidiModel::sync_to_source (const Glib::Threads::Mutex::Lock& source_lock) ms->mark_streaming_midi_write_started (source_lock, note_mode()); - for (Evoral::Sequence::const_iterator i = begin(TimeType(), true); i != end(); ++i) { + for (Evoral::Sequence::const_iterator i = begin (); i != end(); ++i) { ms->append_event_beats(source_lock, *i); } @@ -1501,7 +1501,7 @@ MidiModel::write_section_to (boost::shared_ptr source, source->drop_model(source_lock); source->mark_streaming_midi_write_started (source_lock, note_mode()); - for (Evoral::Sequence::const_iterator i = begin(TimeType(), true); i != end(); ++i) { + for (Evoral::Sequence::const_iterator i = begin (); i != end(); ++i) { if (i->time() >= begin_time && i->time() < end_time) { Evoral::MIDIEvent mev (*i, true); /* copy the event */ diff --git a/libs/ardour/midi_region.cc b/libs/ardour/midi_region.cc index a2838bdc55..1ce304ce37 100644 --- a/libs/ardour/midi_region.cc +++ b/libs/ardour/midi_region.cc @@ -421,8 +421,7 @@ MidiRegion::_read_at (const SourceList& /*srcs*/, << " _start = " << _start << " intoffset = " << internal_offset << " pulse = " << pulse() - << " start_pulse = " << start_pulse() - << " start_beat = " << _start_beats + << " beat = " << _start_beats << endl; #endif @@ -438,8 +437,8 @@ MidiRegion::_read_at (const SourceList& /*srcs*/, tracker, filter, _filtered_parameters, - pulse(), - _start_beats + pulse(), // position of region in musical time + _start_beats // offset into source file in musical time ) != to_read) { return 0; /* "read nothing" */ } diff --git a/libs/ardour/midi_source.cc b/libs/ardour/midi_source.cc index a770a2c290..ae2589f1cb 100644 --- a/libs/ardour/midi_source.cc +++ b/libs/ardour/midi_source.cc @@ -63,7 +63,6 @@ MidiSource::MidiSource (Session& s, string name, Source::Flag flags) , _writing(false) , _model_iter_valid(false) , _length_beats(0.0) - , _last_read_end(0) , _capture_length(0) , _capture_loop_length(0) { @@ -74,7 +73,6 @@ MidiSource::MidiSource (Session& s, const XMLNode& node) , _writing(false) , _model_iter_valid(false) , _length_beats(0.0) - , _last_read_end(0) , _capture_length(0) , _capture_loop_length(0) { @@ -182,151 +180,91 @@ void MidiSource::invalidate (const Lock& lock, std::set::WeakNotePtr>* notes) { _model_iter_valid = false; - _model_iter.invalidate(notes); + //_model_iter.invalidate(notes); } framecnt_t MidiSource::midi_read (const Lock& lm, Evoral::EventSink& dst, - framepos_t source_start, - framepos_t start, + framepos_t source_start, // position of source origin (samples) + framepos_t start, // first position to read (samples) framecnt_t cnt, Evoral::Range* loop_range, MidiStateTracker* tracker, MidiChannelFilter* filter, const std::set& filtered, - const double pulse, - const double start_beats) const + const double pulse, // position of start of region in musical time + const double start_beats // offset into data in musical time (equivalent to _start above) + ) const { - //BeatsFramesConverter converter(_session.tempo_map(), source_start); - const int32_t tpb = Timecode::BBT_Time::ticks_per_beat; - const double pulse_tick_res = floor ((pulse * 4.0 * tpb) + 0.5) / tpb; - const double start_qn = (pulse * 4.0) - start_beats; - - DEBUG_TRACE (DEBUG::MidiSourceIO, - string_compose ("MidiSource::midi_read() %5 sstart %1 start %2 cnt %3 tracker %4\n", - source_start, start, cnt, tracker, name())); if (!_model) { return read_unlocked (lm, dst, source_start, start, cnt, loop_range, tracker, filter); } - // Find appropriate model iterator - Evoral::Sequence::const_iterator& i = _model_iter; - const bool linear_read = _last_read_end != 0 && start == _last_read_end; - if (!linear_read || !_model_iter_valid) { + /* Events in the model are timestamped relative to the start of the model (zero). + * We're looking for events in the model corresponding to events on a given section of the + * timeline. Unless the start of the model (zero) is at the the origin of the timeline, + * these two time coordinates are displaced from each other. So we need to compute + * the relative displacement, and then look for the correct events. + * + * start on timeline (samples): start + * source start on timeline (musical): start of region - start_offset_of_region_within_file + * convert start + * compute different in musical time + */ + + const int32_t tpb = Timecode::BBT_Time::ticks_per_beat; + const double pulse_tick_res = floor ((pulse * 4.0 * tpb) + 0.5) / tpb; + + /* musical time position of start of source */ + + const TimeType start_qn ((pulse * 4.0) - start_beats); + const TimeType read_start_qn (_session.tempo_map().exact_beat_at_frame (start, 0)); + const TimeType read_end_qn (_session.tempo_map().exact_beat_at_frame (start+cnt, 0)); + const TimeType first_possible_event_time = read_start_qn - start_qn; + const TimeType last_possible_event_time = read_end_qn - start_qn; + + DEBUG_TRACE (DEBUG::MidiSourceIO, + string_compose ("MidiSource::midi_read() %5 sstart %1 start %2 (qn = %5) cnt %3 tracker %4\n", + source_start, start, cnt, tracker, name(), start_qn)); + + for (MidiModel::const_iterator i = _model->lower_bound (first_possible_event_time); i != _model->end() && i->time() < last_possible_event_time; ++i) { + #if 0 - // Cached iterator is invalid, search for the first event past start - i = _model->begin(converter.from(start), false, filtered, - linear_read ? &_model->active_notes() : NULL); - _model_iter_valid = true; - if (!linear_read) { - _model->active_notes().clear(); - } -#else - /* hot-fix http://tracker.ardour.org/view.php?id=6541 - * "parallel playback of linked midi regions -> no note-offs" - * - * A midi source can be used by multiple tracks simultaneously, - * in which case midi_read() may be called from different tracks for - * overlapping time-ranges. - * - * However there is only a single iterator for a given midi-source. - * This results in every midi_read() performing a seek. - * - * If seeking is performed with - * _model->begin(converter.from(start),...) - * the model is used for seeking. That method seeks to the first - * *note-on* event after 'start'. - * - * _model->begin(converter.from( ) ,..) eventually calls - * Sequence