don't pass around event_id_t's so much when adding events to a Sequence

This commit is contained in:
Paul Davis 2016-11-03 23:32:46 +00:00
parent a565955d30
commit d1b799a2a2
6 changed files with 107 additions and 94 deletions

View file

@ -100,7 +100,7 @@ MidiStretch::run (boost::shared_ptr<Region> r, Progress*)
boost::shared_ptr<Evoral::Event<MidiModel::TimeType> > ev (new Evoral::Event<MidiModel::TimeType> (**i, true)); boost::shared_ptr<Evoral::Event<MidiModel::TimeType> > ev (new Evoral::Event<MidiModel::TimeType> (**i, true));
ev->set_time (new_time); ev->set_time (new_time);
new_model->append (ev, Evoral::next_event_id()); new_model->insert (ev);
} }
new_model->end_write (Evoral::Sequence<Evoral::Beats>::DeleteStuckNotes); new_model->end_write (Evoral::Sequence<Evoral::Beats>::DeleteStuckNotes);

View file

@ -425,16 +425,8 @@ SMFSource::append_event_beats (const Glib::Threads::Mutex::Lock& lock,
} }
} }
Evoral::event_id_t event_id;
if (ev->id() < 0) {
event_id = Evoral::next_event_id();
} else {
event_id = ev->id();
}
if (_model) { if (_model) {
_model->append (ev, event_id); _model->insert (ev);
} }
_length_beats = max(_length_beats, time); _length_beats = max(_length_beats, time);
@ -442,7 +434,7 @@ SMFSource::append_event_beats (const Glib::Threads::Mutex::Lock& lock,
const Evoral::Beats delta_time_beats = time - _last_ev_time_beats; const Evoral::Beats delta_time_beats = time - _last_ev_time_beats;
const uint32_t delta_time_ticks = delta_time_beats.to_ticks(ppqn()); 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(), ev->id());
_last_ev_time_beats = time; _last_ev_time_beats = time;
_flags = Source::Flag (_flags & ~Empty); _flags = Source::Flag (_flags & ~Empty);
} }
@ -470,18 +462,16 @@ SMFSource::append_event_frames (const Glib::Threads::Mutex::Lock& lock,
BeatsFramesConverter converter(_session.tempo_map(), position); 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) {
event_id = Evoral::next_event_id();
} else {
event_id = ev->id();
}
if (_model) { if (_model) {
boost::shared_ptr<Evoral::Event<Evoral::Beats> > beat_ev boost::shared_ptr<Evoral::Event<Evoral::Beats> > beat_ev
(new Evoral::Event<Evoral::Beats> (ev->event_type(), ev_time_beats, ev->size(), const_cast<uint8_t*>(ev->buffer()))); (new Evoral::Event<Evoral::Beats> (ev->event_type(), ev_time_beats, ev->size(), const_cast<uint8_t*>(ev->buffer())));
_model->append (beat_ev, event_id);
if (ev->id() >= 0) {
beat_ev->set_id (ev->id());
}
_model->insert (beat_ev);
} }
_length_beats = max(_length_beats, ev_time_beats); _length_beats = max(_length_beats, ev_time_beats);
@ -490,7 +480,7 @@ SMFSource::append_event_frames (const Glib::Threads::Mutex::Lock& lock,
const Evoral::Beats delta_time_beats = ev_time_beats - last_time_beats; const Evoral::Beats delta_time_beats = ev_time_beats - last_time_beats;
const uint32_t delta_time_ticks = delta_time_beats.to_ticks(ppqn()); 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(), ev->id());
_last_ev_time_frames = ev->time(); _last_ev_time_frames = ev->time();
_flags = Source::Flag (_flags & ~Empty); _flags = Source::Flag (_flags & ~Empty);
} }
@ -685,7 +675,12 @@ SMFSource::load_model (const Glib::Threads::Mutex::Lock& lock, bool force_reload
boost::shared_ptr<Evoral::Event<Evoral::Beats> > ev ( boost::shared_ptr<Evoral::Event<Evoral::Beats> > ev (
new Evoral::Event<Evoral::Beats> (event_type, event_time, size, buf, true)); new Evoral::Event<Evoral::Beats> (event_type, event_time, size, buf, true));
_model->append (ev, event_id);
if (event_id >= 0) {
ev->set_id (event_id);
}
_model->insert (ev);
// Set size to max capacity to minimize allocs in read_event // 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);

View file

@ -40,6 +40,7 @@ class LIBEVORAL_TEMPLATE_API Note {
#endif #endif
public: public:
Note(uint8_t chan=0, Time time=Time(), Time len=Time(), uint8_t note=0, uint8_t vel=0x40); Note(uint8_t chan=0, Time time=Time(), Time len=Time(), uint8_t note=0, uint8_t vel=0x40);
Note(MIDIEvent<Time> const & initial_on_event);
Note(const Note<Time>& copy); Note(const Note<Time>& copy);
~Note(); ~Note();

View file

@ -110,7 +110,7 @@ class LIBEVORAL_API Sequence : virtual public ControlSet {
void end_write (StuckNoteOption, Time when = Time()); void end_write (StuckNoteOption, Time when = Time());
void append (EventPtr const & ev, Evoral::event_id_t evid); void insert (EventPtr const & ev);
const TypeMap& type_map() const { return _type_map; } const TypeMap& type_map() const { return _type_map; }
@ -210,7 +210,6 @@ private:
typedef std::priority_queue<NotePtr, std::deque<NotePtr>, LaterNoteEndComparator> ActiveNotes; typedef std::priority_queue<NotePtr, std::deque<NotePtr>, LaterNoteEndComparator> ActiveNotes;
public: public:
const_iterator begin () const { return _events.begin(); } const_iterator begin () const { return _events.begin(); }
const const_iterator end() const { return _events.end(); } const const_iterator end() const { return _events.end(); }
/* XXX heap allocation for lower-bound ... fix this */ /* XXX heap allocation for lower-bound ... fix this */
@ -267,11 +266,11 @@ private:
bool overlaps_unlocked (const NotePtr& ev, const NotePtr& ignore_this_note) const; bool overlaps_unlocked (const NotePtr& ev, const NotePtr& ignore_this_note) const;
bool contains_unlocked (const NotePtr& ev) const; bool contains_unlocked (const NotePtr& ev) const;
void append_note_on_unlocked(const MIDIEvent<Time>& event, Evoral::event_id_t); void append_note_on_unlocked (boost::shared_ptr<MIDIEvent<Time> > const & event);
void append_note_off_unlocked(const MIDIEvent<Time>& event); void append_note_off_unlocked (boost::shared_ptr<MIDIEvent<Time> > const & event);
void append_control_unlocked(const Parameter& param, Time time, double value, Evoral::event_id_t); void append_control_unlocked (const Parameter& param, Time time, double value);
void append_sysex_unlocked(const MIDIEvent<Time>& ev, Evoral::event_id_t); void append_sysex_unlocked (boost::shared_ptr<MIDIEvent<Time> > const & ev);
void append_patch_change_unlocked(const PatchChange<Time>&, Evoral::event_id_t); void append_patch_change_unlocked (const PatchChange<Time>&);
void get_notes_by_pitch (Notes&, NoteOperator, uint8_t val, int chan_mask = 0) const; void get_notes_by_pitch (Notes&, NoteOperator, uint8_t val, int chan_mask = 0) const;
void get_notes_by_velocity (Notes&, NoteOperator, uint8_t val, int chan_mask = 0) const; void get_notes_by_velocity (Notes&, NoteOperator, uint8_t val, int chan_mask = 0) const;

View file

@ -51,6 +51,14 @@ Note<Time>::Note(uint8_t chan, Time t, Time l, uint8_t n, uint8_t v)
assert(channel() == chan); assert(channel() == chan);
} }
template<typename Time>
Note<Time>::Note (MIDIEvent<Time> const & ev)
: _on_event (ev, false) // re-use buffer
, _off_event (ev, true) // copy buffer
{
_off_event.set_type (MIDI_CMD_NOTE_OFF);
_off_event.set_velocity (0x40);
}
template<typename Time> template<typename Time>
Note<Time>::Note(const Note<Time>& copy) Note<Time>::Note(const Note<Time>& copy)

View file

@ -35,7 +35,9 @@
#include "evoral/Control.hpp" #include "evoral/Control.hpp"
#include "evoral/ControlList.hpp" #include "evoral/ControlList.hpp"
#include "evoral/ControlSet.hpp" #include "evoral/ControlSet.hpp"
#include "evoral/Event.hpp"
#include "evoral/EventSink.hpp" #include "evoral/EventSink.hpp"
#include "evoral/MIDIEvent.hpp"
#include "evoral/ParameterDescriptor.hpp" #include "evoral/ParameterDescriptor.hpp"
#include "evoral/Sequence.hpp" #include "evoral/Sequence.hpp"
#include "evoral/TypeMap.hpp" #include "evoral/TypeMap.hpp"
@ -408,66 +410,76 @@ Sequence<Time>::remove_sysex_unlocked (const SysExPtr sysex)
*/ */
template<typename Time> template<typename Time>
void void
Sequence<Time>::append(EventPtr const & event, event_id_t evid) Sequence<Time>::insert (EventPtr const & event)
{ {
WriteLock lock(write_lock()); WriteLock lock(write_lock());
const MIDIEvent<Time>& ev = (const MIDIEvent<Time>&)event; boost::shared_ptr<MIDIEvent<Time> > ev = boost::static_pointer_cast<MIDIEvent<Time> > (event);
if (!ev) {
/* Non-MIDI events not handled ... yet */
return;
}
assert (_writing); assert (_writing);
if (!midi_event_is_valid(ev.buffer(), ev.size())) { if (!midi_event_is_valid(ev->buffer(), ev->size())) {
cerr << "WARNING: Sequence ignoring illegal MIDI event" << endl; cerr << "WARNING: Sequence ignoring illegal MIDI event" << endl;
return; return;
} }
if (event->id() < 0) {
event->set_id (Evoral::next_event_id());
}
/* insert the event into the "master" event map */
_events.insert (event); _events.insert (event);
if (ev.is_note_on() && ev.velocity() > 0) { if (ev->is_note_on() && ev->velocity() > 0) {
append_note_on_unlocked (ev, evid); append_note_on_unlocked (ev);
} else if (ev.is_note_off() || (ev.is_note_on() && ev.velocity() == 0)) { } else if (ev->is_note_off() || (ev->is_note_on() && ev->velocity() == 0)) {
/* XXX note: event ID is discarded because we merge the on+off events into /* XXX note: event ID is discarded because we merge the on+off events into
a single note object a single note object
*/ */
append_note_off_unlocked (ev); append_note_off_unlocked (ev);
} else if (ev.is_sysex()) { } else if (ev->is_sysex()) {
append_sysex_unlocked(ev, evid); append_sysex_unlocked(ev);
} else if (ev.is_cc() && (ev.cc_number() == MIDI_CTL_MSB_BANK || ev.cc_number() == MIDI_CTL_LSB_BANK)) { } else if (ev->is_cc() && (ev->cc_number() == MIDI_CTL_MSB_BANK || ev->cc_number() == MIDI_CTL_LSB_BANK)) {
/* note bank numbers in our _bank[] array, so that we can write an event when the program change arrives */ /* note bank numbers in our _bank[] array, so that we can write an event when the program change arrives */
if (ev.cc_number() == MIDI_CTL_MSB_BANK) { if (ev->cc_number() == MIDI_CTL_MSB_BANK) {
_bank[ev.channel()] &= ~(0x7f << 7); _bank[ev->channel()] &= ~(0x7f << 7);
_bank[ev.channel()] |= ev.cc_value() << 7; _bank[ev->channel()] |= ev->cc_value() << 7;
} else { } else {
_bank[ev.channel()] &= ~0x7f; _bank[ev->channel()] &= ~0x7f;
_bank[ev.channel()] |= ev.cc_value(); _bank[ev->channel()] |= ev->cc_value();
} }
} else if (ev.is_cc()) { } else if (ev->is_cc()) {
append_control_unlocked( append_control_unlocked(
Parameter(ev.event_type(), ev.channel(), ev.cc_number()), Parameter(ev->event_type(), ev->channel(), ev->cc_number()),
ev.time(), ev.cc_value(), evid); ev->time(), ev->cc_value());
} else if (ev.is_pgm_change()) { } else if (ev->is_pgm_change()) {
/* write a patch change with this program change and any previously set-up bank number */ /* write a patch change with this program change and any previously set-up bank number */
append_patch_change_unlocked (PatchChange<Time> (ev.time(), ev.channel(), ev.pgm_number(), _bank[ev.channel()]), evid); append_patch_change_unlocked (PatchChange<Time> (ev->time(), ev->channel(), ev->pgm_number(), _bank[ev->channel()]));
} else if (ev.is_pitch_bender()) { } else if (ev->is_pitch_bender()) {
append_control_unlocked( append_control_unlocked(
Parameter(ev.event_type(), ev.channel()), Parameter(ev->event_type(), ev->channel()),
ev.time(), double ((0x7F & ev.pitch_bender_msb()) << 7 ev->time(), double ((0x7F & ev->pitch_bender_msb()) << 7
| (0x7F & ev.pitch_bender_lsb())), | (0x7F & ev->pitch_bender_lsb())));
evid); } else if (ev->is_poly_pressure()) {
} else if (ev.is_poly_pressure()) { append_control_unlocked (Parameter (ev->event_type(), ev->channel(), ev->poly_note()), ev->time(), ev->poly_pressure());
append_control_unlocked (Parameter (ev.event_type(), ev.channel(), ev.poly_note()), ev.time(), ev.poly_pressure(), evid); } else if (ev->is_channel_pressure()) {
} else if (ev.is_channel_pressure()) {
append_control_unlocked( append_control_unlocked(
Parameter(ev.event_type(), ev.channel()), Parameter(ev->event_type(), ev->channel()),
ev.time(), ev.channel_pressure(), evid); ev->time(), ev->channel_pressure());
} else if (!_type_map.type_is_midi(ev.event_type())) { } else if (!_type_map.type_is_midi(ev->event_type())) {
printf("WARNING: Sequence: Unknown event type %X: ", ev.event_type()); printf("WARNING: Sequence: Unknown event type %X: ", ev->event_type());
for (size_t i=0; i < ev.size(); ++i) { for (size_t i=0; i < ev->size(); ++i) {
printf("%X ", ev.buffer()[i]); printf("%X ", ev->buffer()[i]);
} }
printf("\n"); printf("\n");
} else { } else {
printf("WARNING: Sequence: Unknown MIDI event type %X\n", ev.type()); printf("WARNING: Sequence: Unknown MIDI event type %X\n", ev->type());
} }
_edited = true; _edited = true;
@ -475,27 +487,26 @@ Sequence<Time>::append(EventPtr const & event, event_id_t evid)
template<typename Time> template<typename Time>
void void
Sequence<Time>::append_note_on_unlocked (const MIDIEvent<Time>& ev, event_id_t evid) Sequence<Time>::append_note_on_unlocked (boost::shared_ptr<MIDIEvent<Time> > const & ev)
{ {
DEBUG_TRACE (DEBUG::Sequence, string_compose ("%1 c=%2 note %3 on @ %4 v=%5\n", this, DEBUG_TRACE (DEBUG::Sequence, string_compose ("%1 c=%2 note %3 on @ %4 v=%5\n", this,
(int)ev.channel(), (int)ev.note(), (int)ev->channel(), (int)ev->note(),
ev.time(), (int)ev.velocity())); ev->time(), (int)ev->velocity()));
assert(_writing); assert(_writing);
if (ev.note() > 127) { if (ev->note() > 127) {
error << string_compose (_("invalid note on number (%1) ignored"), (int) ev.note()) << endmsg; error << string_compose (_("invalid note on number (%1) ignored"), (int) ev->note()) << endmsg;
return; return;
} else if (ev.channel() >= 16) { } else if (ev->channel() >= 16) {
error << string_compose (_("invalid note on channel (%1) ignored"), (int) ev.channel()) << endmsg; error << string_compose (_("invalid note on channel (%1) ignored"), (int) ev->channel()) << endmsg;
return; return;
} else if (ev.velocity() == 0) { } else if (ev->velocity() == 0) {
// Note on with velocity 0 handled as note off by caller // Note on with velocity 0 handled as note off by caller
error << string_compose (_("invalid note on velocity (%1) ignored"), (int) ev.velocity()) << endmsg; error << string_compose (_("invalid note on velocity (%1) ignored"), (int) ev->velocity()) << endmsg;
return; return;
} }
NotePtr note(new Note<Time>(ev.channel(), ev.time(), Time(), ev.note(), ev.velocity())); NotePtr note (new Note<Time>(*ev.get()));
note->set_id (evid);
add_note_unlocked (note); add_note_unlocked (note);
@ -507,18 +518,18 @@ Sequence<Time>::append_note_on_unlocked (const MIDIEvent<Time>& ev, event_id_t e
template<typename Time> template<typename Time>
void void
Sequence<Time>::append_note_off_unlocked (const MIDIEvent<Time>& ev) Sequence<Time>::append_note_off_unlocked (boost::shared_ptr<MIDIEvent<Time> > const & ev)
{ {
DEBUG_TRACE (DEBUG::Sequence, string_compose ("%1 c=%2 note %3 OFF @ %4 v=%5\n", DEBUG_TRACE (DEBUG::Sequence, string_compose ("%1 c=%2 note %3 OFF @ %4 v=%5\n",
this, (int)ev.channel(), this, (int)ev->channel(),
(int)ev.note(), ev.time(), (int)ev.velocity())); (int)ev->note(), ev->time(), (int)ev->velocity()));
assert(_writing); assert(_writing);
if (ev.note() > 127) { if (ev->note() > 127) {
error << string_compose (_("invalid note off number (%1) ignored"), (int) ev.note()) << endmsg; error << string_compose (_("invalid note off number (%1) ignored"), (int) ev->note()) << endmsg;
return; return;
} else if (ev.channel() >= 16) { } else if (ev->channel() >= 16) {
error << string_compose (_("invalid note off channel (%1) ignored"), (int) ev.channel()) << endmsg; error << string_compose (_("invalid note off channel (%1) ignored"), (int) ev->channel()) << endmsg;
return; return;
} }
@ -534,19 +545,19 @@ Sequence<Time>::append_note_off_unlocked (const MIDIEvent<Time>& ev)
/* XXX use _overlap_pitch_resolution to determine FIFO/LIFO ... */ /* XXX use _overlap_pitch_resolution to determine FIFO/LIFO ... */
for (typename WriteNotes::iterator n = _write_notes[ev.channel()].begin(); n != _write_notes[ev.channel()].end(); ) { for (typename WriteNotes::iterator n = _write_notes[ev->channel()].begin(); n != _write_notes[ev->channel()].end(); ) {
typename WriteNotes::iterator tmp = n; typename WriteNotes::iterator tmp = n;
++tmp; ++tmp;
NotePtr nn = *n; NotePtr nn = *n;
if (ev.note() == nn->note() && nn->channel() == ev.channel()) { if (ev->note() == nn->note() && nn->channel() == ev->channel()) {
assert(ev.time() >= nn->time()); assert(ev->time() >= nn->time());
nn->set_length (ev.time() - nn->time()); nn->set_length (ev->time() - nn->time());
nn->set_off_velocity (ev.velocity()); nn->set_off_velocity (ev->velocity());
_write_notes[ev.channel()].erase(n); _write_notes[ev->channel()].erase(n);
DEBUG_TRACE (DEBUG::Sequence, string_compose ("resolved note @ %2 length: %1\n", nn->length(), nn->time())); DEBUG_TRACE (DEBUG::Sequence, string_compose ("resolved note @ %2 length: %1\n", nn->length(), nn->time()));
resolved = true; resolved = true;
break; break;
@ -556,14 +567,14 @@ Sequence<Time>::append_note_off_unlocked (const MIDIEvent<Time>& ev)
} }
if (!resolved) { if (!resolved) {
cerr << this << " spurious note off chan " << (int)ev.channel() cerr << this << " spurious note off chan " << (int)ev->channel()
<< ", note " << (int)ev.note() << " @ " << ev.time() << endl; << ", note " << (int)ev->note() << " @ " << ev->time() << endl;
} }
} }
template<typename Time> template<typename Time>
void void
Sequence<Time>::append_control_unlocked(const Parameter& param, Time time, double value, event_id_t /* evid */) Sequence<Time>::append_control_unlocked(const Parameter& param, Time time, double value)
{ {
DEBUG_TRACE (DEBUG::Sequence, string_compose ("%1 %2 @ %3 = %4 # controls: %5\n", DEBUG_TRACE (DEBUG::Sequence, string_compose ("%1 %2 @ %3 = %4 # controls: %5\n",
this, _type_map.to_symbol(param), time, value, _controls.size())); this, _type_map.to_symbol(param), time, value, _controls.size()));
@ -574,7 +585,7 @@ Sequence<Time>::append_control_unlocked(const Parameter& param, Time time, doubl
template<typename Time> template<typename Time>
void void
Sequence<Time>::append_sysex_unlocked(const MIDIEvent<Time>& ev, event_id_t /* evid */) Sequence<Time>::append_sysex_unlocked(boost::shared_ptr<MIDIEvent<Time> > const & ev)
{ {
#ifdef DEBUG_SEQUENCE #ifdef DEBUG_SEQUENCE
cerr << this << " SysEx @ " << ev.time() << " \t= \t [ " << hex; cerr << this << " SysEx @ " << ev.time() << " \t= \t [ " << hex;
@ -583,19 +594,18 @@ Sequence<Time>::append_sysex_unlocked(const MIDIEvent<Time>& ev, event_id_t /* e
} cerr << "]" << endl; } cerr << "]" << endl;
#endif #endif
boost::shared_ptr<MIDIEvent<Time> > event(new MIDIEvent<Time>(ev, true));
/* XXX sysex events should use IDs */ /* XXX sysex events should use IDs */
_sysexes.insert(event); _sysexes.insert (ev);
} }
template<typename Time> template<typename Time>
void void
Sequence<Time>::append_patch_change_unlocked (const PatchChange<Time>& ev, event_id_t id) Sequence<Time>::append_patch_change_unlocked (const PatchChange<Time>& ev)
{ {
PatchChangePtr p (new PatchChange<Time> (ev)); PatchChangePtr p (new PatchChange<Time> (ev));
if (p->id() < 0) { if (p->id() < 0) {
p->set_id (id); p->set_id (Evoral::next_event_id());
} }
_patch_changes.insert (p); _patch_changes.insert (p);