Fix O(n) search on MIDI rec region update (now O(log(n)) per update, but could be...
authorDavid Robillard <d@drobilla.net>
Wed, 21 Oct 2009 16:39:39 +0000 (16:39 +0000)
committerDavid Robillard <d@drobilla.net>
Wed, 21 Oct 2009 16:39:39 +0000 (16:39 +0000)
git-svn-id: svn://localhost/ardour2/branches/3.0@5843 d708f5d6-7413-0410-9779-e7cbd77b26cf

gtk2_ardour/midi_streamview.cc
libs/evoral/evoral/Sequence.hpp
libs/evoral/src/Sequence.cpp

index 537c4cb725427a43bd8d37cc2e9ac6a0f9ad6d55..9d877383540985ee08b398b6bb8164bbd5c81eb2 100644 (file)
@@ -575,12 +575,12 @@ MidiStreamView::update_rec_regions (boost::shared_ptr<MidiModel> data, nframes_t
                                                rect->property_x2() = xend;
 
                                                ARDOUR::BeatsFramesConverter tconv(_trackview.session(), region->position());
+                                               const MidiModel::TimeType start_beats = tconv.from(start);
 
                                                /* draw events */
                                                MidiRegionView* mrv = (MidiRegionView*)iter->second;
 
-                                               // FIXME: this is offensively slow (linear search)
-                                               for (MidiModel::Notes::const_iterator i = data->notes().begin();
+                                               for (MidiModel::Notes::const_iterator i = data->note_lower_bound(start_beats);
                                                                i != data->notes().end(); ++i) {
 
                                                        const boost::shared_ptr<MidiRegionView::NoteType>& note = *i;
index 22d81b69485e7550d08b89d91f5e5a4eb869087a..b5737638e1f43c201a993af8651bc96f33dec6ff 100644 (file)
@@ -179,6 +179,8 @@ public:
        const_iterator        begin(Time t=0) const { return const_iterator(*this, t); }
        const const_iterator& end()           const { return _end_iter; }
 
+       typename Notes::const_iterator note_lower_bound (Time t) const;
+
        bool control_to_midi_event(boost::shared_ptr< Event<Time> >& ev,
                                   const ControlIterator&            iter) const;
 
index e27668e626021b5a5cdd0a4903948d5ed872c70b..b4b2d4d2fa1e6e3b4864478989c43e6b5f98394f 100644 (file)
@@ -99,12 +99,10 @@ Sequence<Time>::const_iterator::const_iterator(const Sequence<Time>& seq, Time t
 
        seq.read_lock();
 
-       // Find first note which begins after t
-       boost::shared_ptr< Note<Time> > search_note(new Note<Time>(0, t, 0, 0, 0));
-       _note_iter = seq.notes().lower_bound(search_note);
-       assert(_note_iter == seq.notes().end() || (*_note_iter)->time() >= t);
+       // Find first note which begins at or after t
+       _note_iter = seq.note_lower_bound(t);
 
-       // Find first sysex event after t
+       // Find first sysex event at or after t
        for (typename Sequence<Time>::SysExes::const_iterator i = seq.sysexes().begin();
                        i != seq.sysexes().end(); ++i) {
                if ((*i)->time() >= t) {
@@ -776,6 +774,17 @@ Sequence<Time>::set_notes (const Sequence<Time>::Notes& n)
        _notes = n;
 }
 
+/** Return the earliest note with time >= t */
+template<typename Time>
+typename Sequence<Time>::Notes::const_iterator
+Sequence<Time>::note_lower_bound (Time t) const
+{
+       boost::shared_ptr< Note<Time> > search_note(new Note<Time>(0, t, 0, 0, 0));
+       typename Sequence<Time>::Notes::const_iterator i = _notes.lower_bound(search_note);
+       assert(i == _notes.end() || (*i)->time() >= t);
+       return i;
+}
+
 template class Sequence<Evoral::MusicalTime>;
 
 } // namespace Evoral