mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-15 19:16:40 +01:00
remove complex iterators from Evoral::Sequence and add "global" _events member to store shared_ptr to all events in a time-ordered map
This commit is contained in:
parent
cb567dd881
commit
a565955d30
14 changed files with 102 additions and 215 deletions
|
|
@ -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<Evoral::Beats>& ev) {}
|
||||
boost::shared_ptr<Evoral::Event<Evoral::Beats> > const & ev) {}
|
||||
void append_event_frames(const Lock& lock,
|
||||
const Evoral::Event<framepos_t>& ev,
|
||||
boost::shared_ptr<Evoral::Event<framepos_t> > 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) {}
|
||||
|
|
|
|||
|
|
@ -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<Evoral::Beats>& ev);
|
||||
void append_event_frames(const Glib::Threads::Mutex::Lock& lock, const Evoral::Event<framepos_t>& ev, framepos_t source_start);
|
||||
void append_event_beats(const Glib::Threads::Mutex::Lock& lock, boost::shared_ptr<Evoral::Event<Evoral::Beats> > const & ev);
|
||||
void append_event_frames(const Glib::Threads::Mutex::Lock& lock, boost::shared_ptr<Evoral::Event<framepos_t> > 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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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<Evoral::Beats>& ev) = 0;
|
||||
virtual void append_event_beats(Lock const & lock, boost::shared_ptr<Evoral::Event<Evoral::Beats> > 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<framepos_t>& ev,
|
||||
framepos_t source_start) = 0;
|
||||
virtual void append_event_frames(Lock const & lock, const boost::shared_ptr <Evoral::Event<framepos_t> > & ev, framepos_t source_start) = 0;
|
||||
|
||||
virtual bool empty () const;
|
||||
virtual framecnt_t length (framepos_t pos) const;
|
||||
|
|
|
|||
|
|
@ -51,8 +51,8 @@ public:
|
|||
return safe_midi_file_extension(path);
|
||||
}
|
||||
|
||||
void append_event_beats (const Lock& lock, const Evoral::Event<Evoral::Beats>& ev);
|
||||
void append_event_frames (const Lock& lock, const Evoral::Event<framepos_t>& ev, framepos_t source_start);
|
||||
void append_event_beats (const Lock& lock, boost::shared_ptr<Evoral::Event<Evoral::Beats> > const & ev);
|
||||
void append_event_frames (const Lock& lock, boost::shared_ptr<Evoral::Event<framepos_t> > 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);
|
||||
|
|
|
|||
|
|
@ -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<Evoral::Beats>(
|
||||
0,
|
||||
Evoral::Beats::ticks_at_rate(t, source->ppqn()),
|
||||
size,
|
||||
buf));
|
||||
smfs->append_event_beats (source_lock,
|
||||
boost::shared_ptr<Evoral::Event<Evoral::Beats> > (
|
||||
new Evoral::Event<Evoral::Beats> (
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1429,11 +1429,11 @@ MidiModel::write_to (boost::shared_ptr<MidiSource> source,
|
|||
source->mark_streaming_midi_write_started (source_lock, note_mode());
|
||||
|
||||
for (Evoral::Sequence<TimeType>::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<MidiSource> source,
|
|||
source->mark_streaming_midi_write_started (source_lock, note_mode());
|
||||
|
||||
for (Evoral::Sequence<TimeType>::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<TimeType> mev (*i, true); /* copy the event */
|
||||
boost::shared_ptr<Evoral::MIDIEvent<TimeType> > mev (new Evoral::MIDIEvent<TimeType> (**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<MidiSource> 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);
|
||||
|
|
|
|||
|
|
@ -152,14 +152,14 @@ MidiPlaylistSource::write_unlocked (const Lock&,
|
|||
}
|
||||
|
||||
void
|
||||
MidiPlaylistSource::append_event_beats(const Glib::Threads::Mutex::Lock& /*lock*/, const Evoral::Event<Evoral::Beats>& /*ev*/)
|
||||
MidiPlaylistSource::append_event_beats(const Glib::Threads::Mutex::Lock& /*lock*/, boost::shared_ptr<Evoral::Event<Evoral::Beats> > 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<framepos_t>& /* ev */, framepos_t /*source_start*/)
|
||||
MidiPlaylistSource::append_event_frames(const Glib::Threads::Mutex::Lock& /*lock*/, boost::shared_ptr<Evoral::Event<framepos_t> > const & /* ev */, framepos_t /*source_start*/)
|
||||
{
|
||||
fatal << string_compose (_("programming error: %1"), "MidiPlaylistSource::append_event_frames() called - should be impossible") << endmsg;
|
||||
abort(); /*NOTREACHED*/
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<Evoral::Beats> 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<Evoral::Beats> * ev = new Evoral::MIDIEvent<Evoral::Beats> ((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<Evoral::Event<Evoral::Beats> > 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]--;
|
||||
|
|
|
|||
|
|
@ -95,17 +95,12 @@ MidiStretch::run (boost::shared_ptr<Region> r, Progress*)
|
|||
boost::shared_ptr<MidiModel> 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<MidiModel::TimeType>::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<MidiModel::TimeType>::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<MidiModel::TimeType> ev(*i, true);
|
||||
ev.set_time(new_time);
|
||||
new_model->append(ev, Evoral::next_event_id());
|
||||
boost::shared_ptr<Evoral::Event<MidiModel::TimeType> > ev (new Evoral::Event<MidiModel::TimeType> (**i, true));
|
||||
ev->set_time (new_time);
|
||||
new_model->append (ev, Evoral::next_event_id());
|
||||
}
|
||||
|
||||
new_model->end_write (Evoral::Sequence<Evoral::Beats>::DeleteStuckNotes);
|
||||
|
|
|
|||
|
|
@ -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<framepos_t> ev = *i;
|
||||
ev.set_time(ev.time() - position);
|
||||
boost::shared_ptr<Evoral::Event<framepos_t> > ev (new Evoral::Event<framepos_t> (*i));
|
||||
ev->set_time (ev->time() - position);
|
||||
ms->append_event_frames(lock, ev, ms->timeline_position());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -334,7 +334,7 @@ SMFSource::write_unlocked (const Lock& lock,
|
|||
_model->start_write();
|
||||
}
|
||||
|
||||
Evoral::MIDIEvent<framepos_t> ev;
|
||||
boost::shared_ptr<Evoral::MIDIEvent<framepos_t> > 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<framepos_t> (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<Evoral::Beats>& ev)
|
||||
boost::shared_ptr<Evoral::Event<Evoral::Beats> > 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<framepos_t>& ev,
|
||||
framepos_t position)
|
||||
boost::shared_ptr <Evoral::Event<framepos_t> > 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<Evoral::Beats> beat_ev (ev.event_type(),
|
||||
ev_time_beats,
|
||||
ev.size(),
|
||||
const_cast<uint8_t*>(ev.buffer()));
|
||||
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())));
|
||||
_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<Evoral::Beats>*, gint >& a,
|
||||
const std::pair< Evoral::Event<Evoral::Beats>*, 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<Evoral::Beats>*, 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<Evoral::Beats> (
|
||||
event_type, event_time,
|
||||
size, buf, true)
|
||||
, event_id));
|
||||
boost::shared_ptr<Evoral::Event<Evoral::Beats> > ev (
|
||||
new Evoral::Event<Evoral::Beats> (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<Evoral::Beats>*, 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<Evoral::Beats>::ResolveStuckNotes, _length_beats);
|
||||
_model->set_edited (false);
|
||||
invalidate(lock);
|
||||
invalidate (lock);
|
||||
|
||||
free(buf);
|
||||
free (buf);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -41,22 +41,6 @@ template<typename Time> class EventSink;
|
|||
template<typename Time> class Note;
|
||||
template<typename Time> class Event;
|
||||
|
||||
/** An iterator over (the x axis of) a 2-d double coordinate space.
|
||||
*/
|
||||
class /*LIBEVORAL_API*/ ControlIterator {
|
||||
public:
|
||||
ControlIterator(boost::shared_ptr<const ControlList> al, double ax, double ay)
|
||||
: list(al)
|
||||
, x(ax)
|
||||
, y(ay)
|
||||
{}
|
||||
|
||||
boost::shared_ptr<const ControlList> 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<Evoral::Event<Time> > EventPtr;
|
||||
typedef typename boost::weak_ptr<Evoral::Event<Time> > WeakEventPtr;
|
||||
typedef typename boost::shared_ptr<const Evoral::Event<Time> > constEventPtr;
|
||||
|
||||
struct EventTimeComparator {
|
||||
bool operator() (Event<Time> const & a, Event<Time> const & b) const {
|
||||
return a.time() < b.time();
|
||||
inline bool operator() (const EventPtr a, const EventPtr b) const {
|
||||
return a->time() < b->time();
|
||||
}
|
||||
};
|
||||
|
||||
typedef typename std::multiset<Evoral::Event<Time>,EventTimeComparator> Events;
|
||||
typedef typename std::multiset<EventPtr,EventTimeComparator> Events;
|
||||
typedef typename Events::const_iterator const_iterator;
|
||||
|
||||
private:
|
||||
|
|
@ -122,7 +110,7 @@ class LIBEVORAL_API Sequence : virtual public ControlSet {
|
|||
|
||||
void end_write (StuckNoteOption, Time when = Time());
|
||||
|
||||
void append(const Event<Time>& ev, Evoral::event_id_t evid);
|
||||
void append (EventPtr const & ev, Evoral::event_id_t evid);
|
||||
|
||||
const TypeMap& type_map() const { return _type_map; }
|
||||
|
||||
|
|
@ -222,9 +210,11 @@ private:
|
|||
typedef std::priority_queue<NotePtr, std::deque<NotePtr>, LaterNoteEndComparator> ActiveNotes;
|
||||
public:
|
||||
const_iterator begin () const { return _events.begin(); }
|
||||
|
||||
const const_iterator end() const { return _events.end(); }
|
||||
|
||||
const_iterator lower_bound (Time t) const { Event<Time> ev (0, t, 0, 0, false); return _events.lower_bound (ev); }
|
||||
/* XXX heap allocation for lower-bound ... fix this */
|
||||
const_iterator lower_bound (Time t) const { EventPtr e (new Event<Time> (0, t, 0, 0, false)); return _events.lower_bound (e); }
|
||||
|
||||
// CONST iterator implementations (x3)
|
||||
typename Notes::const_iterator note_lower_bound (Time t) const;
|
||||
|
|
@ -236,9 +226,6 @@ public:
|
|||
typename PatchChanges::iterator patch_change_lower_bound (Time t);
|
||||
typename SysExes::iterator sysex_lower_bound (Time t);
|
||||
|
||||
bool control_to_midi_event(boost::shared_ptr< Event<Time> >& ev,
|
||||
const ControlIterator& iter) const;
|
||||
|
||||
bool edited() const { return _edited; }
|
||||
void set_edited(bool yn) { _edited = yn; }
|
||||
|
||||
|
|
|
|||
|
|
@ -111,82 +111,6 @@ Sequence<Time>::Sequence(const Sequence<Time>& other)
|
|||
DEBUG_TRACE (DEBUG::Sequence, string_compose ("Sequence copied: %1\n", this));
|
||||
}
|
||||
|
||||
/** Write the controller event pointed to by \a iter to \a ev.
|
||||
* The buffer of \a ev will be allocated or resized as necessary.
|
||||
* The event_type of \a ev should be set to the expected output type.
|
||||
* \return true on success
|
||||
*/
|
||||
template<typename Time>
|
||||
bool
|
||||
Sequence<Time>::control_to_midi_event(
|
||||
boost::shared_ptr< Event<Time> >& ev,
|
||||
const ControlIterator& iter) const
|
||||
{
|
||||
assert(iter.list.get());
|
||||
const uint32_t event_type = iter.list->parameter().type();
|
||||
|
||||
// initialize the event pointer with a new event, if necessary
|
||||
if (!ev) {
|
||||
ev = boost::shared_ptr< Event<Time> >(new Event<Time>(event_type, Time(), 3, NULL, true));
|
||||
}
|
||||
|
||||
uint8_t midi_type = _type_map.parameter_midi_type(iter.list->parameter());
|
||||
ev->set_event_type(_type_map.midi_event_type(midi_type));
|
||||
ev->set_id(-1);
|
||||
switch (midi_type) {
|
||||
case MIDI_CMD_CONTROL:
|
||||
assert(iter.list.get());
|
||||
assert(iter.list->parameter().channel() < 16);
|
||||
assert(iter.list->parameter().id() <= INT8_MAX);
|
||||
assert(iter.y <= INT8_MAX);
|
||||
|
||||
ev->set_time(Time(iter.x));
|
||||
ev->realloc(3);
|
||||
ev->buffer()[0] = MIDI_CMD_CONTROL + iter.list->parameter().channel();
|
||||
ev->buffer()[1] = (uint8_t)iter.list->parameter().id();
|
||||
ev->buffer()[2] = (uint8_t)iter.y;
|
||||
break;
|
||||
|
||||
case MIDI_CMD_PGM_CHANGE:
|
||||
assert(iter.list.get());
|
||||
assert(iter.list->parameter().channel() < 16);
|
||||
assert(iter.y <= INT8_MAX);
|
||||
|
||||
ev->set_time(Time(iter.x));
|
||||
ev->realloc(2);
|
||||
ev->buffer()[0] = MIDI_CMD_PGM_CHANGE + iter.list->parameter().channel();
|
||||
ev->buffer()[1] = (uint8_t)iter.y;
|
||||
break;
|
||||
|
||||
case MIDI_CMD_BENDER:
|
||||
assert(iter.list.get());
|
||||
assert(iter.list->parameter().channel() < 16);
|
||||
assert(iter.y < (1<<14));
|
||||
|
||||
ev->set_time(Time(iter.x));
|
||||
ev->realloc(3);
|
||||
ev->buffer()[0] = MIDI_CMD_BENDER + iter.list->parameter().channel();
|
||||
ev->buffer()[1] = uint16_t(iter.y) & 0x7F; // LSB
|
||||
ev->buffer()[2] = (uint16_t(iter.y) >> 7) & 0x7F; // MSB
|
||||
break;
|
||||
|
||||
case MIDI_CMD_CHANNEL_PRESSURE:
|
||||
assert(iter.list.get());
|
||||
assert(iter.list->parameter().channel() < 16);
|
||||
assert(iter.y <= INT8_MAX);
|
||||
|
||||
ev->set_time(Time(iter.x));
|
||||
ev->realloc(2);
|
||||
ev->buffer()[0] = MIDI_CMD_CHANNEL_PRESSURE + iter.list->parameter().channel();
|
||||
ev->buffer()[1] = (uint8_t)iter.y;
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Clear all events from the model.
|
||||
*/
|
||||
|
|
@ -480,25 +404,25 @@ Sequence<Time>::remove_sysex_unlocked (const SysExPtr sysex)
|
|||
/** Append \a ev to model. NOT realtime safe.
|
||||
*
|
||||
* The timestamp of event is expected to be relative to
|
||||
* the start of this model (t=0) and MUST be monotonically increasing
|
||||
* and MUST be >= the latest event currently in the model.
|
||||
* the start of this model (t=0).
|
||||
*/
|
||||
template<typename Time>
|
||||
void
|
||||
Sequence<Time>::append(const Event<Time>& event, event_id_t evid)
|
||||
Sequence<Time>::append(EventPtr const & event, event_id_t evid)
|
||||
{
|
||||
WriteLock lock(write_lock());
|
||||
|
||||
const MIDIEvent<Time>& ev = (const MIDIEvent<Time>&)event;
|
||||
|
||||
assert(_notes.empty() || ev.time() >= (*_notes.rbegin())->time());
|
||||
assert(_writing);
|
||||
assert (_writing);
|
||||
|
||||
if (!midi_event_is_valid(ev.buffer(), ev.size())) {
|
||||
cerr << "WARNING: Sequence ignoring illegal MIDI event" << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
_events.insert (event);
|
||||
|
||||
if (ev.is_note_on() && ev.velocity() > 0) {
|
||||
append_note_on_unlocked (ev, evid);
|
||||
} else if (ev.is_note_off() || (ev.is_note_on() && ev.velocity() == 0)) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue