mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-09 16:24:57 +01:00
Use set over vector for Sequence::Notes, for logarithmic search by time.
git-svn-id: svn://localhost/ardour2/branches/3.0@5798 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
7b94110c54
commit
cb8407d26f
7 changed files with 49 additions and 52 deletions
|
|
@ -2368,17 +2368,12 @@ MidiRegionView::cut_copy_clear (Editing::CutCopyOp op)
|
||||||
MidiCutBuffer*
|
MidiCutBuffer*
|
||||||
MidiRegionView::selection_as_cut_buffer () const
|
MidiRegionView::selection_as_cut_buffer () const
|
||||||
{
|
{
|
||||||
NoteList notes;
|
Notes notes;
|
||||||
|
|
||||||
for (Selection::iterator i = _selection.begin(); i != _selection.end(); ++i) {
|
for (Selection::iterator i = _selection.begin(); i != _selection.end(); ++i) {
|
||||||
notes.push_back (boost::shared_ptr<NoteType> (new NoteType (*((*i)->note().get()))));
|
notes.insert (boost::shared_ptr<NoteType> (new NoteType (*((*i)->note().get()))));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* sort them into time order */
|
|
||||||
|
|
||||||
Evoral::Sequence<Evoral::MusicalTime>::LaterNoteComparator cmp;
|
|
||||||
sort (notes.begin(), notes.end(), cmp);
|
|
||||||
|
|
||||||
MidiCutBuffer* cb = new MidiCutBuffer (trackview.session());
|
MidiCutBuffer* cb = new MidiCutBuffer (trackview.session());
|
||||||
cb->set (notes);
|
cb->set (notes);
|
||||||
|
|
||||||
|
|
@ -2399,16 +2394,16 @@ MidiRegionView::paste (nframes64_t pos, float times, const MidiCutBuffer& mcb)
|
||||||
Evoral::MusicalTime duration;
|
Evoral::MusicalTime duration;
|
||||||
Evoral::MusicalTime end_point;
|
Evoral::MusicalTime end_point;
|
||||||
|
|
||||||
duration = mcb.notes().back()->end_time() - mcb.notes().front()->time();
|
duration = (*mcb.notes().rbegin())->end_time() - (*mcb.notes().begin())->time();
|
||||||
paste_pos_beats = frames_to_beats (pos - _region->position());
|
paste_pos_beats = frames_to_beats (pos - _region->position());
|
||||||
beat_delta = mcb.notes().front()->time() - paste_pos_beats;
|
beat_delta = (*mcb.notes().begin())->time() - paste_pos_beats;
|
||||||
paste_pos_beats = 0;
|
paste_pos_beats = 0;
|
||||||
|
|
||||||
_selection.clear ();
|
_selection.clear ();
|
||||||
|
|
||||||
for (int n = 0; n < (int) times; ++n) {
|
for (int n = 0; n < (int) times; ++n) {
|
||||||
|
|
||||||
for (NoteList::const_iterator i = mcb.notes().begin(); i != mcb.notes().end(); ++i) {
|
for (Notes::const_iterator i = mcb.notes().begin(); i != mcb.notes().end(); ++i) {
|
||||||
|
|
||||||
boost::shared_ptr<NoteType> copied_note (new NoteType (*((*i).get())));
|
boost::shared_ptr<NoteType> copied_note (new NoteType (*((*i).get())));
|
||||||
copied_note->set_time (paste_pos_beats + copied_note->time() - beat_delta);
|
copied_note->set_time (paste_pos_beats + copied_note->time() - beat_delta);
|
||||||
|
|
@ -2516,13 +2511,13 @@ MidiRegionView::goto_previous_note ()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MidiRegionView::selection_as_notelist (NoteList& selected)
|
MidiRegionView::selection_as_notelist (Notes& selected)
|
||||||
{
|
{
|
||||||
time_sort_events ();
|
time_sort_events ();
|
||||||
|
|
||||||
for (Events::iterator i = _events.begin(); i != _events.end(); ++i) {
|
for (Events::iterator i = _events.begin(); i != _events.end(); ++i) {
|
||||||
if ((*i)->selected()) {
|
if ((*i)->selected()) {
|
||||||
selected.push_back ((*i)->note());
|
selected.insert ((*i)->note());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@ class MidiRegionView : public RegionView
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef Evoral::Note<Evoral::MusicalTime> NoteType;
|
typedef Evoral::Note<Evoral::MusicalTime> NoteType;
|
||||||
typedef Evoral::Sequence<Evoral::MusicalTime>::Notes NoteList;
|
typedef Evoral::Sequence<Evoral::MusicalTime>::Notes Notes;
|
||||||
|
|
||||||
MidiRegionView (ArdourCanvas::Group *,
|
MidiRegionView (ArdourCanvas::Group *,
|
||||||
RouteTimeAxisView&,
|
RouteTimeAxisView&,
|
||||||
|
|
@ -285,7 +285,7 @@ class MidiRegionView : public RegionView
|
||||||
|
|
||||||
void show_list_editor ();
|
void show_list_editor ();
|
||||||
|
|
||||||
void selection_as_notelist (NoteList& selected);
|
void selection_as_notelist (Notes& selected);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/** Allows derived types to specify their visibility requirements
|
/** Allows derived types to specify their visibility requirements
|
||||||
|
|
|
||||||
|
|
@ -574,11 +574,10 @@ MidiStreamView::update_rec_regions (boost::shared_ptr<MidiModel> data, nframes_t
|
||||||
|
|
||||||
/* draw events */
|
/* draw events */
|
||||||
MidiRegionView* mrv = (MidiRegionView*)iter->second;
|
MidiRegionView* mrv = (MidiRegionView*)iter->second;
|
||||||
for (size_t i=0; i < data->n_notes(); ++i) {
|
for (MidiModel::Notes::const_iterator i = data->notes().begin();
|
||||||
|
i != data->notes().end(); ++i) {
|
||||||
|
|
||||||
// FIXME: slooooooooow!
|
const boost::shared_ptr<MidiRegionView::NoteType>& note = *i;
|
||||||
|
|
||||||
const boost::shared_ptr<MidiRegionView::NoteType> note = data->note_at(i);
|
|
||||||
|
|
||||||
if (note->length() > 0 && note->end_time() + region->position() > start)
|
if (note->length() > 0 && note->end_time() + region->position() > start)
|
||||||
mrv->resolve_note(note->note(), note->end_time());
|
mrv->resolve_note(note->note(), note->end_time());
|
||||||
|
|
@ -598,7 +597,6 @@ MidiStreamView::update_rec_regions (boost::shared_ptr<MidiModel> data, nframes_t
|
||||||
}
|
}
|
||||||
|
|
||||||
mrv->add_note (note, !update_range);
|
mrv->add_note (note, !update_range);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mrv->extend_active_notes();
|
mrv->extend_active_notes();
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ public:
|
||||||
template<typename Time>
|
template<typename Time>
|
||||||
class Sequence : virtual public ControlSet {
|
class Sequence : virtual public ControlSet {
|
||||||
public:
|
public:
|
||||||
Sequence(const TypeMap& type_map, size_t size=0);
|
Sequence(const TypeMap& type_map);
|
||||||
|
|
||||||
void write_lock();
|
void write_lock();
|
||||||
void write_unlock();
|
void write_unlock();
|
||||||
|
|
@ -78,12 +78,8 @@ public:
|
||||||
bool writing() const { return _writing; }
|
bool writing() const { return _writing; }
|
||||||
void end_write(bool delete_stuck=false);
|
void end_write(bool delete_stuck=false);
|
||||||
|
|
||||||
/** Resizes vector if necessary (NOT realtime safe) */
|
|
||||||
void append(const Event<Time>& ev);
|
void append(const Event<Time>& ev);
|
||||||
|
|
||||||
inline const boost::shared_ptr< const Note<Time> > note_at(size_t i) const { return _notes[i]; }
|
|
||||||
inline const boost::shared_ptr< Note<Time> > note_at(size_t i) { return _notes[i]; }
|
|
||||||
|
|
||||||
inline size_t n_notes() const { return _notes.size(); }
|
inline size_t n_notes() const { return _notes.size(); }
|
||||||
inline bool empty() const { return _notes.size() == 0 && ControlSet::controls_empty(); }
|
inline bool empty() const { return _notes.size() == 0 && ControlSet::controls_empty(); }
|
||||||
|
|
||||||
|
|
@ -92,6 +88,20 @@ public:
|
||||||
return a->time() < b->time();
|
return a->time() < b->time();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct NoteNumberComparator {
|
||||||
|
inline bool operator()(const boost::shared_ptr< const Note<Time> > a,
|
||||||
|
const boost::shared_ptr< const Note<Time> > b) const {
|
||||||
|
return a->note() < b->note();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EarlierNoteComparator {
|
||||||
|
inline bool operator()(const boost::shared_ptr< const Note<Time> > a,
|
||||||
|
const boost::shared_ptr< const Note<Time> > b) const {
|
||||||
|
return a->time() < b->time();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct LaterNoteComparator {
|
struct LaterNoteComparator {
|
||||||
typedef const Note<Time>* value_type;
|
typedef const Note<Time>* value_type;
|
||||||
inline bool operator()(const boost::shared_ptr< const Note<Time> > a,
|
inline bool operator()(const boost::shared_ptr< const Note<Time> > a,
|
||||||
|
|
@ -108,7 +118,7 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::vector< boost::shared_ptr< Note<Time> > > Notes;
|
typedef std::set<boost::shared_ptr< Note<Time> >, EarlierNoteComparator> Notes;
|
||||||
inline Notes& notes() { return _notes; }
|
inline Notes& notes() { return _notes; }
|
||||||
inline const Notes& notes() const { return _notes; }
|
inline const Notes& notes() const { return _notes; }
|
||||||
|
|
||||||
|
|
@ -199,7 +209,7 @@ private:
|
||||||
Notes _notes;
|
Notes _notes;
|
||||||
SysExes _sysexes;
|
SysExes _sysexes;
|
||||||
|
|
||||||
typedef std::vector<size_t> WriteNotes;
|
typedef std::set<boost::shared_ptr< Note<Time> >, NoteNumberComparator> WriteNotes;
|
||||||
WriteNotes _write_notes[16];
|
WriteNotes _write_notes[16];
|
||||||
bool _writing;
|
bool _writing;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -427,10 +427,9 @@ Sequence<Time>::const_iterator::operator=(const const_iterator& other)
|
||||||
// Sequence
|
// Sequence
|
||||||
|
|
||||||
template<typename Time>
|
template<typename Time>
|
||||||
Sequence<Time>::Sequence(const TypeMap& type_map, size_t size)
|
Sequence<Time>::Sequence(const TypeMap& type_map)
|
||||||
: _edited(false)
|
: _edited(false)
|
||||||
, _type_map(type_map)
|
, _type_map(type_map)
|
||||||
, _notes(size)
|
|
||||||
, _writing(false)
|
, _writing(false)
|
||||||
, _end_iter(*this, DBL_MAX)
|
, _end_iter(*this, DBL_MAX)
|
||||||
, _percussive(false)
|
, _percussive(false)
|
||||||
|
|
@ -569,14 +568,13 @@ Sequence<Time>::end_write(bool delete_stuck)
|
||||||
|
|
||||||
if (!_percussive && delete_stuck) {
|
if (!_percussive && delete_stuck) {
|
||||||
for (typename Notes::iterator n = _notes.begin(); n != _notes.end() ;) {
|
for (typename Notes::iterator n = _notes.begin(); n != _notes.end() ;) {
|
||||||
|
typename Notes::iterator next = n;
|
||||||
|
++next;
|
||||||
if ((*n)->length() == 0) {
|
if ((*n)->length() == 0) {
|
||||||
cerr << "WARNING: Stuck note lost: " << (*n)->note() << endl;
|
cerr << "WARNING: Stuck note lost: " << (*n)->note() << endl;
|
||||||
n = _notes.erase(n);
|
_notes.erase(n);
|
||||||
// we have to break here because erase invalidates the iterator
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
++n;
|
|
||||||
}
|
}
|
||||||
|
n = next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -611,7 +609,7 @@ Sequence<Time>::append(const Event<Time>& event)
|
||||||
|
|
||||||
const MIDIEvent<Time>& ev = (const MIDIEvent<Time>&)event;
|
const MIDIEvent<Time>& ev = (const MIDIEvent<Time>&)event;
|
||||||
|
|
||||||
assert(_notes.empty() || ev.time() >= _notes.back()->time());
|
assert(_notes.empty() || ev.time() >= (*_notes.rbegin())->time());
|
||||||
assert(_writing);
|
assert(_writing);
|
||||||
|
|
||||||
if (!midi_event_is_valid(ev.buffer(), ev.size())) {
|
if (!midi_event_is_valid(ev.buffer(), ev.size())) {
|
||||||
|
|
@ -678,14 +676,14 @@ Sequence<Time>::append_note_on_unlocked(uint8_t chan, Time time, uint8_t note_nu
|
||||||
_highest_note = note_num;
|
_highest_note = note_num;
|
||||||
|
|
||||||
boost::shared_ptr< Note<Time> > new_note(new Note<Time>(chan, time, 0, note_num, velocity));
|
boost::shared_ptr< Note<Time> > new_note(new Note<Time>(chan, time, 0, note_num, velocity));
|
||||||
_notes.push_back(new_note);
|
_notes.insert(new_note);
|
||||||
if (!_percussive) {
|
if (!_percussive) {
|
||||||
DUMP(format("Sustained: Appending active note on %1% channel %2%\n")
|
DUMP(format("Sustained: Appending active note on %1% channel %2%\n")
|
||||||
% (unsigned)(uint8_t)note_num % chan);
|
% (unsigned)(uint8_t)note_num % chan);
|
||||||
_write_notes[chan].push_back(_notes.size() - 1);
|
_write_notes[chan].insert(new_note);
|
||||||
} else {
|
} else {
|
||||||
DUMP("Percussive: NOT appending active note on\n");
|
DUMP("Percussive: NOT appending active note on\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Time>
|
template<typename Time>
|
||||||
|
|
@ -704,19 +702,15 @@ Sequence<Time>::append_note_off_unlocked(uint8_t chan, Time time, uint8_t note_n
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: make _write_notes fixed size (127 noted) for speed */
|
// TODO: support note off velocity
|
||||||
|
|
||||||
/* FIXME: note off velocity for that one guy out there who actually has
|
|
||||||
* keys that send it */
|
|
||||||
|
|
||||||
bool resolved = false;
|
bool resolved = false;
|
||||||
|
for (typename WriteNotes::iterator n = _write_notes[chan].begin();
|
||||||
for (WriteNotes::iterator n = _write_notes[chan].begin(); n
|
n != _write_notes[chan].end(); ++n) {
|
||||||
!= _write_notes[chan].end(); ++n) {
|
boost::shared_ptr< Note<Time> > note = *n;
|
||||||
Note<Time>& note = *_notes[*n].get();
|
if (note->note() == note_num) {
|
||||||
if (note.note() == note_num) {
|
assert(time >= note->time());
|
||||||
assert(time >= note.time());
|
note->set_length(time - note->time());
|
||||||
note.set_length(time - note.time());
|
|
||||||
_write_notes[chan].erase(n);
|
_write_notes[chan].erase(n);
|
||||||
DUMP(format("resolved note, length: %1%\n") % note.length());
|
DUMP(format("resolved note, length: %1%\n") % note.length());
|
||||||
resolved = true;
|
resolved = true;
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ class SMFTest : public CppUnit::TestFixture
|
||||||
void setUp() {
|
void setUp() {
|
||||||
type_map = new DummyTypeMap();
|
type_map = new DummyTypeMap();
|
||||||
assert(type_map);
|
assert(type_map);
|
||||||
seq = new MySequence<Time>(*type_map, 0);
|
seq = new MySequence<Time>(*type_map);
|
||||||
assert(seq);
|
assert(seq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ public:
|
||||||
template<typename Time>
|
template<typename Time>
|
||||||
class MySequence : public Sequence<Time> {
|
class MySequence : public Sequence<Time> {
|
||||||
public:
|
public:
|
||||||
MySequence(DummyTypeMap&map, int size) : Sequence<Time>(map, size) {}
|
MySequence(DummyTypeMap&map) : Sequence<Time>(map) {}
|
||||||
|
|
||||||
boost::shared_ptr<Control> control_factory(const Parameter& param) {
|
boost::shared_ptr<Control> control_factory(const Parameter& param) {
|
||||||
|
|
||||||
|
|
@ -107,7 +107,7 @@ class SequenceTest : public CppUnit::TestFixture
|
||||||
void setUp (void) {
|
void setUp (void) {
|
||||||
type_map = new DummyTypeMap();
|
type_map = new DummyTypeMap();
|
||||||
assert(type_map);
|
assert(type_map);
|
||||||
seq = new MySequence<Time>(*type_map, 0);
|
seq = new MySequence<Time>(*type_map);
|
||||||
assert(seq);
|
assert(seq);
|
||||||
|
|
||||||
for(int i = 0; i < 12; i++) {
|
for(int i = 0; i < 12; i++) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue