From a565955d30d640b03e5e7a7551f94d985137270a Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Thu, 3 Nov 2016 14:38:35 +0000 Subject: [PATCH] remove complex iterators from Evoral::Sequence and add "global" _events member to store shared_ptr to all events in a time-ordered map --- libs/ardour/ardour/midi_pattern_source.h | 4 +- libs/ardour/ardour/midi_playlist_source.h | 4 +- libs/ardour/ardour/midi_source.h | 7 +- libs/ardour/ardour/smf_source.h | 4 +- libs/ardour/import.cc | 15 ++-- libs/ardour/midi_model.cc | 20 ++--- libs/ardour/midi_playlist_source.cc | 4 +- libs/ardour/midi_source.cc | 14 ++-- libs/ardour/midi_state_tracker.cc | 13 ++-- libs/ardour/midi_stretch.cc | 15 ++-- libs/ardour/session.cc | 4 +- libs/ardour/smf_source.cc | 92 ++++++++++------------- libs/evoral/evoral/Sequence.hpp | 35 +++------ libs/evoral/src/Sequence.cpp | 86 ++------------------- 14 files changed, 102 insertions(+), 215 deletions(-) diff --git a/libs/ardour/ardour/midi_pattern_source.h b/libs/ardour/ardour/midi_pattern_source.h index 30d79268b6..fdb5a87636 100644 --- a/libs/ardour/ardour/midi_pattern_source.h +++ b/libs/ardour/ardour/midi_pattern_source.h @@ -39,9 +39,9 @@ class LIBARDOUR_API MidiPatternSource : public MidiSource, public PatternSource MidiSource one, so these are no-ops. */ void append_event_beats(const Lock& lock, - const Evoral::Event& ev) {} + boost::shared_ptr > const & ev) {} void append_event_frames(const Lock& lock, - const Evoral::Event& ev, + boost::shared_ptr > const & ev, framepos_t source_start) {} void mark_streaming_midi_write_started (const Lock& lock, NoteMode mode) {} void mark_streaming_write_started (const Lock& lock) {} diff --git a/libs/ardour/ardour/midi_playlist_source.h b/libs/ardour/ardour/midi_playlist_source.h index 7e54cde788..15a4acf056 100644 --- a/libs/ardour/ardour/midi_playlist_source.h +++ b/libs/ardour/ardour/midi_playlist_source.h @@ -45,8 +45,8 @@ public: XMLNode& get_state (); int set_state (const XMLNode&, int version); - void append_event_beats(const Glib::Threads::Mutex::Lock& lock, const Evoral::Event& ev); - void append_event_frames(const Glib::Threads::Mutex::Lock& lock, const Evoral::Event& ev, framepos_t source_start); + void append_event_beats(const Glib::Threads::Mutex::Lock& lock, boost::shared_ptr > const & ev); + void append_event_frames(const Glib::Threads::Mutex::Lock& lock, boost::shared_ptr > const & ev, framepos_t source_start); void load_model(const Glib::Threads::Mutex::Lock& lock, bool force_reload=false); void destroy_model(const Glib::Threads::Mutex::Lock& lock); diff --git a/libs/ardour/ardour/midi_source.h b/libs/ardour/ardour/midi_source.h index 731fd1d835..98eb1752f1 100644 --- a/libs/ardour/ardour/midi_source.h +++ b/libs/ardour/ardour/midi_source.h @@ -114,16 +114,13 @@ class LIBARDOUR_API MidiSource : virtual public Source, public boost::enable_sha * * Caller must ensure that the event is later than the last written event. */ - virtual void append_event_beats(const Lock& lock, - const Evoral::Event& ev) = 0; + virtual void append_event_beats(Lock const & lock, boost::shared_ptr > const & ev) = 0; /** Append a single event with a timestamp in frames. * * Caller must ensure that the event is later than the last written event. */ - virtual void append_event_frames(const Lock& lock, - const Evoral::Event& ev, - framepos_t source_start) = 0; + virtual void append_event_frames(Lock const & lock, const boost::shared_ptr > & ev, framepos_t source_start) = 0; virtual bool empty () const; virtual framecnt_t length (framepos_t pos) const; diff --git a/libs/ardour/ardour/smf_source.h b/libs/ardour/ardour/smf_source.h index 979c20dd21..445abb8a58 100644 --- a/libs/ardour/ardour/smf_source.h +++ b/libs/ardour/ardour/smf_source.h @@ -51,8 +51,8 @@ public: return safe_midi_file_extension(path); } - void append_event_beats (const Lock& lock, const Evoral::Event& ev); - void append_event_frames (const Lock& lock, const Evoral::Event& ev, framepos_t source_start); + void append_event_beats (const Lock& lock, boost::shared_ptr > const & ev); + void append_event_frames (const Lock& lock, boost::shared_ptr > const & ev, framepos_t source_start); void mark_streaming_midi_write_started (const Lock& lock, NoteMode mode); void mark_streaming_write_completed (const Lock& lock); diff --git a/libs/ardour/import.cc b/libs/ardour/import.cc index 36dc48e651..433fb662ea 100644 --- a/libs/ardour/import.cc +++ b/libs/ardour/import.cc @@ -415,13 +415,13 @@ write_midi_data_to_new_files (Evoral::SMF* source, ImportStatus& status, first = false; } - smfs->append_event_beats( - source_lock, - Evoral::Event( - 0, - Evoral::Beats::ticks_at_rate(t, source->ppqn()), - size, - buf)); + smfs->append_event_beats (source_lock, + boost::shared_ptr > ( + new Evoral::Event ( + 0, + Evoral::Beats::ticks_at_rate(t, source->ppqn()), + size, + buf))); if (status.progress < 0.99) { status.progress += 0.01; @@ -629,4 +629,3 @@ Session::import_files (ImportStatus& status) status.done = true; } - diff --git a/libs/ardour/midi_model.cc b/libs/ardour/midi_model.cc index e50a3678ef..d7b0edaa30 100644 --- a/libs/ardour/midi_model.cc +++ b/libs/ardour/midi_model.cc @@ -1429,11 +1429,11 @@ MidiModel::write_to (boost::shared_ptr source, source->mark_streaming_midi_write_started (source_lock, note_mode()); for (Evoral::Sequence::const_iterator i = begin (); i != end(); ++i) { - source->append_event_beats(source_lock, *i); + source->append_event_beats (source_lock, *i); } set_percussive(old_percussive); - source->mark_streaming_write_completed(source_lock); + source->mark_streaming_write_completed (source_lock); set_edited(false); @@ -1502,17 +1502,17 @@ MidiModel::write_section_to (boost::shared_ptr source, source->mark_streaming_midi_write_started (source_lock, note_mode()); for (Evoral::Sequence::const_iterator i = begin (); i != end(); ++i) { - if (i->time() >= begin_time && i->time() < end_time) { + if ((*i)->time() >= begin_time && (*i)->time() < end_time) { - Evoral::MIDIEvent mev (*i, true); /* copy the event */ + boost::shared_ptr > mev (new Evoral::MIDIEvent (**i, true)); /* copy the event */ if (offset_events) { - mev.set_time(mev.time() - begin_time); + mev->set_time(mev->time() - begin_time); } - if (mev.is_note_off()) { + if (mev->is_note_off()) { - if (!mst.active (mev.note(), mev.channel())) { + if (!mst.active (mev->note(), mev->channel())) { /* the matching note-on was outside the time range we were given, so just ignore this note-off. @@ -1521,10 +1521,10 @@ MidiModel::write_section_to (boost::shared_ptr source, } source->append_event_beats (source_lock, mev); - mst.remove (mev.note(), mev.channel()); + mst.remove (mev->note(), mev->channel()); - } else if (mev.is_note_on()) { - mst.add (mev.note(), mev.channel()); + } else if (mev->is_note_on()) { + mst.add (mev->note(), mev->channel()); source->append_event_beats(source_lock, mev); } else { source->append_event_beats(source_lock, mev); diff --git a/libs/ardour/midi_playlist_source.cc b/libs/ardour/midi_playlist_source.cc index 8b7e87889e..4e4b9ea7f3 100644 --- a/libs/ardour/midi_playlist_source.cc +++ b/libs/ardour/midi_playlist_source.cc @@ -152,14 +152,14 @@ MidiPlaylistSource::write_unlocked (const Lock&, } void -MidiPlaylistSource::append_event_beats(const Glib::Threads::Mutex::Lock& /*lock*/, const Evoral::Event& /*ev*/) +MidiPlaylistSource::append_event_beats(const Glib::Threads::Mutex::Lock& /*lock*/, boost::shared_ptr > const & /*ev*/) { fatal << string_compose (_("programming error: %1"), "MidiPlaylistSource::append_event_beats() called - should be impossible") << endmsg; abort(); /*NOTREACHED*/ } void -MidiPlaylistSource::append_event_frames(const Glib::Threads::Mutex::Lock& /*lock*/, const Evoral::Event& /* ev */, framepos_t /*source_start*/) +MidiPlaylistSource::append_event_frames(const Glib::Threads::Mutex::Lock& /*lock*/, boost::shared_ptr > const & /* ev */, framepos_t /*source_start*/) { fatal << string_compose (_("programming error: %1"), "MidiPlaylistSource::append_event_frames() called - should be impossible") << endmsg; abort(); /*NOTREACHED*/ diff --git a/libs/ardour/midi_source.cc b/libs/ardour/midi_source.cc index ae2589f1cb..6778af3cc7 100644 --- a/libs/ardour/midi_source.cc +++ b/libs/ardour/midi_source.cc @@ -229,13 +229,13 @@ MidiSource::midi_read (const Lock& lm, 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) { + for (MidiModel::const_iterator i = _model->lower_bound (first_possible_event_time); i != _model->end() && (*i)->time() < last_possible_event_time; ++i) { #if 0 - if (filter && filter->filter(i->buffer(), i->size())) { + if (filter && filter->filter((*i)->buffer(), (*i)->size())) { DEBUG_TRACE (DEBUG::MidiSourceIO, string_compose ("%1: filter event @ %2 type %3 size %4\n", - _name, i->time(), i->event_type(), i->size())); + _name, (*i)->time(), (*i)->event_type(), (*i)->size())); continue; } @@ -243,18 +243,18 @@ MidiSource::midi_read (const Lock& lm, // time_frames = loop_range->squish (time_frames); } - // dst.write (time_frames, i->event_type(), i->size(), i->buffer()); + // dst.write (time_frames, (*i)->event_type(), (*i)->size(), (*i)->buffer()); #ifndef NDEBUG if (DEBUG_ENABLED(DEBUG::MidiSourceIO)) { DEBUG_STR_DECL(a); DEBUG_STR_APPEND(a, string_compose ("%1 added event @ %2 sz %3 within %4 .. %5 ", - _name, time_frames, i->size(), + _name, time_frames, (*i)->size(), start + source_start, start + cnt + source_start)); for (size_t n=0; n < i->size(); ++n) { DEBUG_STR_APPEND(a,hex); DEBUG_STR_APPEND(a,"0x"); - DEBUG_STR_APPEND(a,(int)i->buffer()[n]); + DEBUG_STR_APPEND(a,(int)(*i)->buffer()[n]); DEBUG_STR_APPEND(a,' '); } DEBUG_STR_APPEND(a,'\n'); @@ -264,7 +264,7 @@ MidiSource::midi_read (const Lock& lm, #endif if (tracker) { - tracker->track (*i); + tracker->track (**i); } } diff --git a/libs/ardour/midi_state_tracker.cc b/libs/ardour/midi_state_tracker.cc index 3e81a064c8..d0970b8517 100644 --- a/libs/ardour/midi_state_tracker.cc +++ b/libs/ardour/midi_state_tracker.cc @@ -181,12 +181,13 @@ MidiStateTracker::resolve_notes (MidiSource& src, const MidiSource::Lock& lock, for (int channel = 0; channel < 16; ++channel) { for (int note = 0; note < 128; ++note) { while (_active_notes[note + 128 * channel]) { - Evoral::MIDIEvent ev ((MIDI_CMD_NOTE_OFF|channel), time, 3, 0, true); - ev.set_type (MIDI_CMD_NOTE_OFF); - ev.set_channel (channel); - ev.set_note (note); - ev.set_velocity (0); - src.append_event_beats (lock, ev); + Evoral::MIDIEvent * ev = new Evoral::MIDIEvent ((MIDI_CMD_NOTE_OFF|channel), time, 3, 0, true); + ev->set_type (MIDI_CMD_NOTE_OFF); + ev->set_channel (channel); + ev->set_note (note); + ev->set_velocity (0); + boost::shared_ptr > e (ev); + src.append_event_beats (lock, e); DEBUG_TRACE (PBD::DEBUG::MidiTrackers, string_compose ("%1: MS-resolved note %2/%3 at %4\n", this, (int) note, (int) channel, time)); _active_notes[note + 128 * channel]--; diff --git a/libs/ardour/midi_stretch.cc b/libs/ardour/midi_stretch.cc index 12372bb7c7..0c7c682ef5 100644 --- a/libs/ardour/midi_stretch.cc +++ b/libs/ardour/midi_stretch.cc @@ -95,17 +95,12 @@ MidiStretch::run (boost::shared_ptr r, Progress*) boost::shared_ptr new_model = new_src->model(); new_model->start_write(); - /* Note: pass true into force_discrete for the begin() iterator so that the model doesn't - * do interpolation of controller data when we stretch. - */ - for (Evoral::Sequence::const_iterator i = old_model->begin (); - i != old_model->end(); ++i) { - const MidiModel::TimeType new_time = i->time() * (double)_request.time_fraction; + for (Evoral::Sequence::const_iterator i = old_model->begin (); i != old_model->end(); ++i) { + const MidiModel::TimeType new_time = (*i)->time() * (double)_request.time_fraction; - // FIXME: double copy - Evoral::Event ev(*i, true); - ev.set_time(new_time); - new_model->append(ev, Evoral::next_event_id()); + boost::shared_ptr > ev (new Evoral::Event (**i, true)); + ev->set_time (new_time); + new_model->append (ev, Evoral::next_event_id()); } new_model->end_write (Evoral::Sequence::DeleteStuckNotes); diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index 5605ac1e6c..f618f412b1 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -5974,8 +5974,8 @@ Session::write_one_track (Track& track, framepos_t start, framepos_t end, const MidiBuffer& buf = buffers.get_midi(0); for (MidiBuffer::const_iterator i = buf.begin(); i != buf.end(); ++i) { - Evoral::Event ev = *i; - ev.set_time(ev.time() - position); + boost::shared_ptr > ev (new Evoral::Event (*i)); + ev->set_time (ev->time() - position); ms->append_event_frames(lock, ev, ms->timeline_position()); } } diff --git a/libs/ardour/smf_source.cc b/libs/ardour/smf_source.cc index 33ba6e2a00..42a85f4fe4 100644 --- a/libs/ardour/smf_source.cc +++ b/libs/ardour/smf_source.cc @@ -334,7 +334,7 @@ SMFSource::write_unlocked (const Lock& lock, _model->start_write(); } - Evoral::MIDIEvent ev; + boost::shared_ptr > ev; while (true) { /* Get the event time, in frames since session start but ignoring looping. */ bool ret; @@ -376,15 +376,14 @@ SMFSource::write_unlocked (const Lock& lock, } time -= position; - ev.set(buf, size, time); - ev.set_event_type(midi_parameter_type(ev.buffer()[0])); - ev.set_id(Evoral::next_event_id()); + ev.reset (new Evoral::MIDIEvent (midi_parameter_type (buf[0]), time, size, buf)); + ev->set_id (Evoral::next_event_id()); - if (!(ev.is_channel_event() || ev.is_smf_meta_event() || ev.is_sysex())) { + if (!(ev->is_channel_event() || ev->is_smf_meta_event() || ev->is_sysex())) { continue; } - append_event_frames(lock, ev, position); + append_event_frames (lock, ev, position); } Evoral::SMF::flush (); @@ -396,19 +395,19 @@ SMFSource::write_unlocked (const Lock& lock, /** Append an event with a timestamp in beats */ void SMFSource::append_event_beats (const Glib::Threads::Mutex::Lock& lock, - const Evoral::Event& ev) + boost::shared_ptr > const & ev) { - if (!_writing || ev.size() == 0) { + if (!_writing || ev->size() == 0) { return; } #if 0 printf("SMFSource: %s - append_event_beats ID = %d time = %lf, size = %u, data = ", - name().c_str(), ev.id(), ev.time(), ev.size()); - for (size_t i = 0; i < ev.size(); ++i) printf("%X ", ev.buffer()[i]); printf("\n"); + name().c_str(), ev->id(), ev->time(), ev->size()); + for (size_t i = 0; i < ev->size(); ++i) printf("%X ", ev->buffer()[i]); printf("\n"); #endif - Evoral::Beats time = ev.time(); + Evoral::Beats time = ev->time(); if (time < _last_ev_time_beats) { const Evoral::Beats difference = _last_ev_time_beats - time; if (difference.to_double() / (double)ppqn() < 1.0) { @@ -420,7 +419,7 @@ SMFSource::append_event_beats (const Glib::Threads::Mutex::Lock& lock, } else { /* Out of order by more than a tick. */ warning << string_compose(_("Skipping event with unordered beat time %1 < %2 (off by %3 beats, %4 ticks)"), - ev.time(), _last_ev_time_beats, difference, difference.to_double() / (double)ppqn()) + ev->time(), _last_ev_time_beats, difference, difference.to_double() / (double)ppqn()) << endmsg; return; } @@ -428,10 +427,10 @@ SMFSource::append_event_beats (const Glib::Threads::Mutex::Lock& lock, Evoral::event_id_t event_id; - if (ev.id() < 0) { + if (ev->id() < 0) { event_id = Evoral::next_event_id(); } else { - event_id = ev.id(); + event_id = ev->id(); } if (_model) { @@ -443,7 +442,7 @@ SMFSource::append_event_beats (const Glib::Threads::Mutex::Lock& lock, const Evoral::Beats delta_time_beats = time - _last_ev_time_beats; const uint32_t delta_time_ticks = delta_time_beats.to_ticks(ppqn()); - Evoral::SMF::append_event_delta(delta_time_ticks, ev.size(), ev.buffer(), event_id); + Evoral::SMF::append_event_delta(delta_time_ticks, ev->size(), ev->buffer(), event_id); _last_ev_time_beats = time; _flags = Source::Flag (_flags & ~Empty); } @@ -451,39 +450,37 @@ SMFSource::append_event_beats (const Glib::Threads::Mutex::Lock& lock, /** Append an event with a timestamp in frames (framepos_t) */ void SMFSource::append_event_frames (const Glib::Threads::Mutex::Lock& lock, - const Evoral::Event& ev, - framepos_t position) + boost::shared_ptr > const & ev, + framepos_t position) { - if (!_writing || ev.size() == 0) { + if (!_writing || ev->size() == 0) { return; } // printf("SMFSource: %s - append_event_frames ID = %d time = %u, size = %u, data = ", - // name().c_str(), ev.id(), ev.time(), ev.size()); - // for (size_t i=0; i < ev.size(); ++i) printf("%X ", ev.buffer()[i]); printf("\n"); + // name().c_str(), ev->id(), ev->time(), ev->size()); + // for (size_t i=0; i < ev->size(); ++i) printf("%X ", ev->buffer()[i]); printf("\n"); - if (ev.time() < _last_ev_time_frames) { + if (ev->time() < _last_ev_time_frames) { warning << string_compose(_("Skipping event with unordered frame time %1 < %2"), - ev.time(), _last_ev_time_frames) + ev->time(), _last_ev_time_frames) << endmsg; return; } BeatsFramesConverter converter(_session.tempo_map(), position); - const Evoral::Beats ev_time_beats = converter.from(ev.time()); + const Evoral::Beats ev_time_beats = converter.from(ev->time()); Evoral::event_id_t event_id; - if (ev.id() < 0) { + if (ev->id() < 0) { event_id = Evoral::next_event_id(); } else { - event_id = ev.id(); + event_id = ev->id(); } if (_model) { - const Evoral::Event beat_ev (ev.event_type(), - ev_time_beats, - ev.size(), - const_cast(ev.buffer())); + boost::shared_ptr > beat_ev + (new Evoral::Event (ev->event_type(), ev_time_beats, ev->size(), const_cast(ev->buffer()))); _model->append (beat_ev, event_id); } @@ -493,8 +490,8 @@ SMFSource::append_event_frames (const Glib::Threads::Mutex::Lock& lock, const Evoral::Beats delta_time_beats = ev_time_beats - last_time_beats; const uint32_t delta_time_ticks = delta_time_beats.to_ticks(ppqn()); - Evoral::SMF::append_event_delta(delta_time_ticks, ev.size(), ev.buffer(), event_id); - _last_ev_time_frames = ev.time(); + Evoral::SMF::append_event_delta (delta_time_ticks, ev->size(), ev->buffer(), event_id); + _last_ev_time_frames = ev->time(); _flags = Source::Flag (_flags & ~Empty); } @@ -603,12 +600,6 @@ SMFSource::safe_midi_file_extension (const string& file) return true; } -static bool compare_eventlist ( - const std::pair< Evoral::Event*, gint >& a, - const std::pair< Evoral::Event*, gint >& b) { - return ( a.first->time() < b.first->time() ); -} - void SMFSource::load_model (const Glib::Threads::Mutex::Lock& lock, bool force_reload) { @@ -651,7 +642,10 @@ SMFSource::load_model (const Glib::Threads::Mutex::Lock& lock, bool force_reload std::list< std::pair< Evoral::Event*, gint > > eventlist; for (unsigned i = 1; i <= num_tracks(); ++i) { - if (seek_to_track(i)) continue; + + if (seek_to_track(i)) { + continue; + } time = 0; have_event_id = false; @@ -689,14 +683,12 @@ SMFSource::load_model (const Glib::Threads::Mutex::Lock& lock, bool force_reload delta_t, time, size, ss , event_type, event_id, name())); #endif - eventlist.push_back(make_pair ( - new Evoral::Event ( - event_type, event_time, - size, buf, true) - , event_id)); + boost::shared_ptr > ev ( + new Evoral::Event (event_type, event_time, size, buf, true)); + _model->append (ev, event_id); // Set size to max capacity to minimize allocs in read_event - scratch_size = std::max(size, scratch_size); + scratch_size = std::max (size, scratch_size); size = scratch_size; _length_beats = max(_length_beats, event_time); @@ -707,23 +699,15 @@ SMFSource::load_model (const Glib::Threads::Mutex::Lock& lock, bool force_reload } } - eventlist.sort(compare_eventlist); - - std::list< std::pair< Evoral::Event*, gint > >::iterator it; - for (it=eventlist.begin(); it!=eventlist.end(); ++it) { - _model->append (*it->first, it->second); - delete it->first; - } - // cerr << "----SMF-SRC-----\n"; // _playback_buf->dump (cerr); // cerr << "----------------\n"; _model->end_write (Evoral::Sequence::ResolveStuckNotes, _length_beats); _model->set_edited (false); - invalidate(lock); + invalidate (lock); - free(buf); + free (buf); } void diff --git a/libs/evoral/evoral/Sequence.hpp b/libs/evoral/evoral/Sequence.hpp index 84c59c0fd8..9704645b9d 100644 --- a/libs/evoral/evoral/Sequence.hpp +++ b/libs/evoral/evoral/Sequence.hpp @@ -41,22 +41,6 @@ template class EventSink; template class Note; template class Event; -/** An iterator over (the x axis of) a 2-d double coordinate space. - */ -class /*LIBEVORAL_API*/ ControlIterator { -public: - ControlIterator(boost::shared_ptr al, double ax, double ay) - : list(al) - , x(ax) - , y(ay) - {} - - boost::shared_ptr list; - double x; - double y; -}; - - /** This is a higher level view of events, with separate representations for * notes (instead of just unassociated note on/off events) and controller data. * Controller data is represented as a list of time-stamped float values. */ @@ -80,13 +64,17 @@ class LIBEVORAL_API Sequence : virtual public ControlSet { }; public: + typedef typename boost::shared_ptr > EventPtr; + typedef typename boost::weak_ptr > WeakEventPtr; + typedef typename boost::shared_ptr > constEventPtr; + struct EventTimeComparator { - bool operator() (Event