mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-16 19:56:31 +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.
|
MidiSource one, so these are no-ops.
|
||||||
*/
|
*/
|
||||||
void append_event_beats(const Lock& lock,
|
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,
|
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) {}
|
framepos_t source_start) {}
|
||||||
void mark_streaming_midi_write_started (const Lock& lock, NoteMode mode) {}
|
void mark_streaming_midi_write_started (const Lock& lock, NoteMode mode) {}
|
||||||
void mark_streaming_write_started (const Lock& lock) {}
|
void mark_streaming_write_started (const Lock& lock) {}
|
||||||
|
|
|
||||||
|
|
@ -45,8 +45,8 @@ public:
|
||||||
XMLNode& get_state ();
|
XMLNode& get_state ();
|
||||||
int set_state (const XMLNode&, int version);
|
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_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, const Evoral::Event<framepos_t>& ev, framepos_t source_start);
|
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 load_model(const Glib::Threads::Mutex::Lock& lock, bool force_reload=false);
|
||||||
void destroy_model(const Glib::Threads::Mutex::Lock& lock);
|
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.
|
* Caller must ensure that the event is later than the last written event.
|
||||||
*/
|
*/
|
||||||
virtual void append_event_beats(const Lock& lock,
|
virtual void append_event_beats(Lock const & lock, boost::shared_ptr<Evoral::Event<Evoral::Beats> > const & ev) = 0;
|
||||||
const Evoral::Event<Evoral::Beats>& ev) = 0;
|
|
||||||
|
|
||||||
/** Append a single event with a timestamp in frames.
|
/** Append a single event with a timestamp in frames.
|
||||||
*
|
*
|
||||||
* Caller must ensure that the event is later than the last written event.
|
* Caller must ensure that the event is later than the last written event.
|
||||||
*/
|
*/
|
||||||
virtual void append_event_frames(const Lock& lock,
|
virtual void append_event_frames(Lock const & lock, const boost::shared_ptr <Evoral::Event<framepos_t> > & ev, framepos_t source_start) = 0;
|
||||||
const Evoral::Event<framepos_t>& ev,
|
|
||||||
framepos_t source_start) = 0;
|
|
||||||
|
|
||||||
virtual bool empty () const;
|
virtual bool empty () const;
|
||||||
virtual framecnt_t length (framepos_t pos) const;
|
virtual framecnt_t length (framepos_t pos) const;
|
||||||
|
|
|
||||||
|
|
@ -51,8 +51,8 @@ public:
|
||||||
return safe_midi_file_extension(path);
|
return safe_midi_file_extension(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
void append_event_beats (const Lock& lock, const Evoral::Event<Evoral::Beats>& ev);
|
void append_event_beats (const Lock& lock, boost::shared_ptr<Evoral::Event<Evoral::Beats> > const & ev);
|
||||||
void append_event_frames (const Lock& lock, const Evoral::Event<framepos_t>& ev, framepos_t source_start);
|
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_midi_write_started (const Lock& lock, NoteMode mode);
|
||||||
void mark_streaming_write_completed (const Lock& lock);
|
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;
|
first = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
smfs->append_event_beats(
|
smfs->append_event_beats (source_lock,
|
||||||
source_lock,
|
boost::shared_ptr<Evoral::Event<Evoral::Beats> > (
|
||||||
Evoral::Event<Evoral::Beats>(
|
new Evoral::Event<Evoral::Beats> (
|
||||||
0,
|
0,
|
||||||
Evoral::Beats::ticks_at_rate(t, source->ppqn()),
|
Evoral::Beats::ticks_at_rate(t, source->ppqn()),
|
||||||
size,
|
size,
|
||||||
buf));
|
buf)));
|
||||||
|
|
||||||
if (status.progress < 0.99) {
|
if (status.progress < 0.99) {
|
||||||
status.progress += 0.01;
|
status.progress += 0.01;
|
||||||
|
|
@ -629,4 +629,3 @@ Session::import_files (ImportStatus& status)
|
||||||
|
|
||||||
status.done = true;
|
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());
|
source->mark_streaming_midi_write_started (source_lock, note_mode());
|
||||||
|
|
||||||
for (Evoral::Sequence<TimeType>::const_iterator i = begin (); i != end(); ++i) {
|
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);
|
set_percussive(old_percussive);
|
||||||
source->mark_streaming_write_completed(source_lock);
|
source->mark_streaming_write_completed (source_lock);
|
||||||
|
|
||||||
set_edited(false);
|
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());
|
source->mark_streaming_midi_write_started (source_lock, note_mode());
|
||||||
|
|
||||||
for (Evoral::Sequence<TimeType>::const_iterator i = begin (); i != end(); ++i) {
|
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) {
|
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
|
/* the matching note-on was outside the
|
||||||
time range we were given, so just
|
time range we were given, so just
|
||||||
ignore this note-off.
|
ignore this note-off.
|
||||||
|
|
@ -1521,10 +1521,10 @@ MidiModel::write_section_to (boost::shared_ptr<MidiSource> source,
|
||||||
}
|
}
|
||||||
|
|
||||||
source->append_event_beats (source_lock, mev);
|
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()) {
|
} else if (mev->is_note_on()) {
|
||||||
mst.add (mev.note(), mev.channel());
|
mst.add (mev->note(), mev->channel());
|
||||||
source->append_event_beats(source_lock, mev);
|
source->append_event_beats(source_lock, mev);
|
||||||
} else {
|
} else {
|
||||||
source->append_event_beats(source_lock, mev);
|
source->append_event_beats(source_lock, mev);
|
||||||
|
|
|
||||||
|
|
@ -152,14 +152,14 @@ MidiPlaylistSource::write_unlocked (const Lock&,
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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;
|
fatal << string_compose (_("programming error: %1"), "MidiPlaylistSource::append_event_beats() called - should be impossible") << endmsg;
|
||||||
abort(); /*NOTREACHED*/
|
abort(); /*NOTREACHED*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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;
|
fatal << string_compose (_("programming error: %1"), "MidiPlaylistSource::append_event_frames() called - should be impossible") << endmsg;
|
||||||
abort(); /*NOTREACHED*/
|
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",
|
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));
|
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 0
|
||||||
if (filter && filter->filter(i->buffer(), i->size())) {
|
if (filter && filter->filter((*i)->buffer(), (*i)->size())) {
|
||||||
DEBUG_TRACE (DEBUG::MidiSourceIO,
|
DEBUG_TRACE (DEBUG::MidiSourceIO,
|
||||||
string_compose ("%1: filter event @ %2 type %3 size %4\n",
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -243,18 +243,18 @@ MidiSource::midi_read (const Lock& lm,
|
||||||
// time_frames = loop_range->squish (time_frames);
|
// 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
|
#ifndef NDEBUG
|
||||||
if (DEBUG_ENABLED(DEBUG::MidiSourceIO)) {
|
if (DEBUG_ENABLED(DEBUG::MidiSourceIO)) {
|
||||||
DEBUG_STR_DECL(a);
|
DEBUG_STR_DECL(a);
|
||||||
DEBUG_STR_APPEND(a, string_compose ("%1 added event @ %2 sz %3 within %4 .. %5 ",
|
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));
|
start + source_start, start + cnt + source_start));
|
||||||
for (size_t n=0; n < i->size(); ++n) {
|
for (size_t n=0; n < i->size(); ++n) {
|
||||||
DEBUG_STR_APPEND(a,hex);
|
DEBUG_STR_APPEND(a,hex);
|
||||||
DEBUG_STR_APPEND(a,"0x");
|
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,' ');
|
||||||
}
|
}
|
||||||
DEBUG_STR_APPEND(a,'\n');
|
DEBUG_STR_APPEND(a,'\n');
|
||||||
|
|
@ -264,7 +264,7 @@ MidiSource::midi_read (const Lock& lm,
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
if (tracker) {
|
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 channel = 0; channel < 16; ++channel) {
|
||||||
for (int note = 0; note < 128; ++note) {
|
for (int note = 0; note < 128; ++note) {
|
||||||
while (_active_notes[note + 128 * channel]) {
|
while (_active_notes[note + 128 * channel]) {
|
||||||
Evoral::MIDIEvent<Evoral::Beats> ev ((MIDI_CMD_NOTE_OFF|channel), time, 3, 0, true);
|
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_type (MIDI_CMD_NOTE_OFF);
|
||||||
ev.set_channel (channel);
|
ev->set_channel (channel);
|
||||||
ev.set_note (note);
|
ev->set_note (note);
|
||||||
ev.set_velocity (0);
|
ev->set_velocity (0);
|
||||||
src.append_event_beats (lock, ev);
|
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",
|
DEBUG_TRACE (PBD::DEBUG::MidiTrackers, string_compose ("%1: MS-resolved note %2/%3 at %4\n",
|
||||||
this, (int) note, (int) channel, time));
|
this, (int) note, (int) channel, time));
|
||||||
_active_notes[note + 128 * channel]--;
|
_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();
|
boost::shared_ptr<MidiModel> new_model = new_src->model();
|
||||||
new_model->start_write();
|
new_model->start_write();
|
||||||
|
|
||||||
/* Note: pass true into force_discrete for the begin() iterator so that the model doesn't
|
for (Evoral::Sequence<MidiModel::TimeType>::const_iterator i = old_model->begin (); i != old_model->end(); ++i) {
|
||||||
* do interpolation of controller data when we stretch.
|
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
|
boost::shared_ptr<Evoral::Event<MidiModel::TimeType> > ev (new Evoral::Event<MidiModel::TimeType> (**i, true));
|
||||||
Evoral::Event<MidiModel::TimeType> ev(*i, true);
|
ev->set_time (new_time);
|
||||||
ev.set_time(new_time);
|
new_model->append (ev, Evoral::next_event_id());
|
||||||
new_model->append(ev, Evoral::next_event_id());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
new_model->end_write (Evoral::Sequence<Evoral::Beats>::DeleteStuckNotes);
|
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);
|
const MidiBuffer& buf = buffers.get_midi(0);
|
||||||
for (MidiBuffer::const_iterator i = buf.begin(); i != buf.end(); ++i) {
|
for (MidiBuffer::const_iterator i = buf.begin(); i != buf.end(); ++i) {
|
||||||
Evoral::Event<framepos_t> ev = *i;
|
boost::shared_ptr<Evoral::Event<framepos_t> > ev (new Evoral::Event<framepos_t> (*i));
|
||||||
ev.set_time(ev.time() - position);
|
ev->set_time (ev->time() - position);
|
||||||
ms->append_event_frames(lock, ev, ms->timeline_position());
|
ms->append_event_frames(lock, ev, ms->timeline_position());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -334,7 +334,7 @@ SMFSource::write_unlocked (const Lock& lock,
|
||||||
_model->start_write();
|
_model->start_write();
|
||||||
}
|
}
|
||||||
|
|
||||||
Evoral::MIDIEvent<framepos_t> ev;
|
boost::shared_ptr<Evoral::MIDIEvent<framepos_t> > ev;
|
||||||
while (true) {
|
while (true) {
|
||||||
/* Get the event time, in frames since session start but ignoring looping. */
|
/* Get the event time, in frames since session start but ignoring looping. */
|
||||||
bool ret;
|
bool ret;
|
||||||
|
|
@ -376,15 +376,14 @@ SMFSource::write_unlocked (const Lock& lock,
|
||||||
}
|
}
|
||||||
time -= position;
|
time -= position;
|
||||||
|
|
||||||
ev.set(buf, size, time);
|
ev.reset (new Evoral::MIDIEvent<framepos_t> (midi_parameter_type (buf[0]), time, size, buf));
|
||||||
ev.set_event_type(midi_parameter_type(ev.buffer()[0]));
|
ev->set_id (Evoral::next_event_id());
|
||||||
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
append_event_frames(lock, ev, position);
|
append_event_frames (lock, ev, position);
|
||||||
}
|
}
|
||||||
|
|
||||||
Evoral::SMF::flush ();
|
Evoral::SMF::flush ();
|
||||||
|
|
@ -396,19 +395,19 @@ SMFSource::write_unlocked (const Lock& lock,
|
||||||
/** Append an event with a timestamp in beats */
|
/** Append an event with a timestamp in beats */
|
||||||
void
|
void
|
||||||
SMFSource::append_event_beats (const Glib::Threads::Mutex::Lock& lock,
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
printf("SMFSource: %s - append_event_beats ID = %d time = %lf, size = %u, data = ",
|
printf("SMFSource: %s - append_event_beats ID = %d time = %lf, size = %u, data = ",
|
||||||
name().c_str(), ev.id(), ev.time(), ev.size());
|
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");
|
for (size_t i = 0; i < ev->size(); ++i) printf("%X ", ev->buffer()[i]); printf("\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Evoral::Beats time = ev.time();
|
Evoral::Beats time = ev->time();
|
||||||
if (time < _last_ev_time_beats) {
|
if (time < _last_ev_time_beats) {
|
||||||
const Evoral::Beats difference = _last_ev_time_beats - time;
|
const Evoral::Beats difference = _last_ev_time_beats - time;
|
||||||
if (difference.to_double() / (double)ppqn() < 1.0) {
|
if (difference.to_double() / (double)ppqn() < 1.0) {
|
||||||
|
|
@ -420,7 +419,7 @@ SMFSource::append_event_beats (const Glib::Threads::Mutex::Lock& lock,
|
||||||
} else {
|
} else {
|
||||||
/* Out of order by more than a tick. */
|
/* 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)"),
|
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;
|
<< endmsg;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -428,10 +427,10 @@ SMFSource::append_event_beats (const Glib::Threads::Mutex::Lock& lock,
|
||||||
|
|
||||||
Evoral::event_id_t event_id;
|
Evoral::event_id_t event_id;
|
||||||
|
|
||||||
if (ev.id() < 0) {
|
if (ev->id() < 0) {
|
||||||
event_id = Evoral::next_event_id();
|
event_id = Evoral::next_event_id();
|
||||||
} else {
|
} else {
|
||||||
event_id = ev.id();
|
event_id = ev->id();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_model) {
|
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 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(), event_id);
|
||||||
_last_ev_time_beats = time;
|
_last_ev_time_beats = time;
|
||||||
_flags = Source::Flag (_flags & ~Empty);
|
_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) */
|
/** Append an event with a timestamp in frames (framepos_t) */
|
||||||
void
|
void
|
||||||
SMFSource::append_event_frames (const Glib::Threads::Mutex::Lock& lock,
|
SMFSource::append_event_frames (const Glib::Threads::Mutex::Lock& lock,
|
||||||
const Evoral::Event<framepos_t>& ev,
|
boost::shared_ptr <Evoral::Event<framepos_t> > const & ev,
|
||||||
framepos_t position)
|
framepos_t position)
|
||||||
{
|
{
|
||||||
if (!_writing || ev.size() == 0) {
|
if (!_writing || ev->size() == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// printf("SMFSource: %s - append_event_frames ID = %d time = %u, size = %u, data = ",
|
// printf("SMFSource: %s - append_event_frames ID = %d time = %u, size = %u, data = ",
|
||||||
// name().c_str(), ev.id(), ev.time(), ev.size());
|
// 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");
|
// 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"),
|
warning << string_compose(_("Skipping event with unordered frame time %1 < %2"),
|
||||||
ev.time(), _last_ev_time_frames)
|
ev->time(), _last_ev_time_frames)
|
||||||
<< endmsg;
|
<< endmsg;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
Evoral::event_id_t event_id;
|
||||||
|
|
||||||
if (ev.id() < 0) {
|
if (ev->id() < 0) {
|
||||||
event_id = Evoral::next_event_id();
|
event_id = Evoral::next_event_id();
|
||||||
} else {
|
} else {
|
||||||
event_id = ev.id();
|
event_id = ev->id();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_model) {
|
if (_model) {
|
||||||
const Evoral::Event<Evoral::Beats> beat_ev (ev.event_type(),
|
boost::shared_ptr<Evoral::Event<Evoral::Beats> > beat_ev
|
||||||
ev_time_beats,
|
(new Evoral::Event<Evoral::Beats> (ev->event_type(), ev_time_beats, ev->size(), const_cast<uint8_t*>(ev->buffer())));
|
||||||
ev.size(),
|
|
||||||
const_cast<uint8_t*>(ev.buffer()));
|
|
||||||
_model->append (beat_ev, event_id);
|
_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 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(), event_id);
|
||||||
_last_ev_time_frames = ev.time();
|
_last_ev_time_frames = ev->time();
|
||||||
_flags = Source::Flag (_flags & ~Empty);
|
_flags = Source::Flag (_flags & ~Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -603,12 +600,6 @@ SMFSource::safe_midi_file_extension (const string& file)
|
||||||
return true;
|
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
|
void
|
||||||
SMFSource::load_model (const Glib::Threads::Mutex::Lock& lock, bool force_reload)
|
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;
|
std::list< std::pair< Evoral::Event<Evoral::Beats>*, gint > > eventlist;
|
||||||
|
|
||||||
for (unsigned i = 1; i <= num_tracks(); ++i) {
|
for (unsigned i = 1; i <= num_tracks(); ++i) {
|
||||||
if (seek_to_track(i)) continue;
|
|
||||||
|
if (seek_to_track(i)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
time = 0;
|
time = 0;
|
||||||
have_event_id = false;
|
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()));
|
delta_t, time, size, ss , event_type, event_id, name()));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
eventlist.push_back(make_pair (
|
boost::shared_ptr<Evoral::Event<Evoral::Beats> > ev (
|
||||||
new Evoral::Event<Evoral::Beats> (
|
new Evoral::Event<Evoral::Beats> (event_type, event_time, size, buf, true));
|
||||||
event_type, event_time,
|
_model->append (ev, event_id);
|
||||||
size, buf, true)
|
|
||||||
, event_id));
|
|
||||||
|
|
||||||
// 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);
|
||||||
size = scratch_size;
|
size = scratch_size;
|
||||||
|
|
||||||
_length_beats = max(_length_beats, event_time);
|
_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";
|
// cerr << "----SMF-SRC-----\n";
|
||||||
// _playback_buf->dump (cerr);
|
// _playback_buf->dump (cerr);
|
||||||
// cerr << "----------------\n";
|
// cerr << "----------------\n";
|
||||||
|
|
||||||
_model->end_write (Evoral::Sequence<Evoral::Beats>::ResolveStuckNotes, _length_beats);
|
_model->end_write (Evoral::Sequence<Evoral::Beats>::ResolveStuckNotes, _length_beats);
|
||||||
_model->set_edited (false);
|
_model->set_edited (false);
|
||||||
invalidate(lock);
|
invalidate (lock);
|
||||||
|
|
||||||
free(buf);
|
free (buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
|
|
@ -41,22 +41,6 @@ template<typename Time> class EventSink;
|
||||||
template<typename Time> class Note;
|
template<typename Time> class Note;
|
||||||
template<typename Time> class Event;
|
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
|
/** This is a higher level view of events, with separate representations for
|
||||||
* notes (instead of just unassociated note on/off events) and controller data.
|
* notes (instead of just unassociated note on/off events) and controller data.
|
||||||
* Controller data is represented as a list of time-stamped float values. */
|
* Controller data is represented as a list of time-stamped float values. */
|
||||||
|
|
@ -80,13 +64,17 @@ class LIBEVORAL_API Sequence : virtual public ControlSet {
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
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 {
|
struct EventTimeComparator {
|
||||||
bool operator() (Event<Time> const & a, Event<Time> const & b) const {
|
inline bool operator() (const EventPtr a, const EventPtr b) const {
|
||||||
return a.time() < b.time();
|
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;
|
typedef typename Events::const_iterator const_iterator;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
@ -122,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(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; }
|
const TypeMap& type_map() const { return _type_map; }
|
||||||
|
|
||||||
|
|
@ -222,9 +210,11 @@ 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(); }
|
||||||
|
|
||||||
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)
|
// CONST iterator implementations (x3)
|
||||||
typename Notes::const_iterator note_lower_bound (Time t) const;
|
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 PatchChanges::iterator patch_change_lower_bound (Time t);
|
||||||
typename SysExes::iterator sysex_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; }
|
bool edited() const { return _edited; }
|
||||||
void set_edited(bool yn) { _edited = yn; }
|
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));
|
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.
|
/** 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.
|
/** Append \a ev to model. NOT realtime safe.
|
||||||
*
|
*
|
||||||
* The timestamp of event is expected to be relative to
|
* The timestamp of event is expected to be relative to
|
||||||
* the start of this model (t=0) and MUST be monotonically increasing
|
* the start of this model (t=0).
|
||||||
* and MUST be >= the latest event currently in the model.
|
|
||||||
*/
|
*/
|
||||||
template<typename Time>
|
template<typename Time>
|
||||||
void
|
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());
|
WriteLock lock(write_lock());
|
||||||
|
|
||||||
const MIDIEvent<Time>& ev = (const MIDIEvent<Time>&)event;
|
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())) {
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_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, evid);
|
||||||
} 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)) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue