summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Gareus <robin@gareus.org>2017-06-14 02:38:32 +0200
committerRobin Gareus <robin@gareus.org>2017-06-14 02:40:09 +0200
commit8b917c4c1660e4a22d187a676b9dfb562aa06ee2 (patch)
tree3db34bbb13e94d841fdc091467d6bd2610df9e30
parent9c0f6ea9480cf22fefc17fdca93e3d5b1d5bebe3 (diff)
Add infrastructure to merge ControlLists
-rw-r--r--libs/evoral/evoral/ControlList.hpp3
-rw-r--r--libs/evoral/src/ControlList.cpp46
2 files changed, 48 insertions, 1 deletions
diff --git a/libs/evoral/evoral/ControlList.hpp b/libs/evoral/evoral/ControlList.hpp
index 515067de04..109124162b 100644
--- a/libs/evoral/evoral/ControlList.hpp
+++ b/libs/evoral/evoral/ControlList.hpp
@@ -124,6 +124,7 @@ public:
void shift (double before, double distance);
void y_transform (boost::function<double(double)> callback);
+ void list_merge (ControlList const& other, boost::function<double(double, double)> callback);
/** add automation events
* @param when absolute time in samples
@@ -217,7 +218,7 @@ public:
* @param where absolute time in samples
* @returns parameter value
*/
- double eval (double where) {
+ double eval (double where) const {
Glib::Threads::RWLock::ReaderLock lm (_lock);
return unlocked_eval (where);
}
diff --git a/libs/evoral/src/ControlList.cpp b/libs/evoral/src/ControlList.cpp
index 92234a6ea7..0ec9cad814 100644
--- a/libs/evoral/src/ControlList.cpp
+++ b/libs/evoral/src/ControlList.cpp
@@ -264,6 +264,52 @@ ControlList::y_transform (boost::function<double(double)> callback)
}
void
+ControlList::list_merge (ControlList const& other, boost::function<double(double, double)> callback)
+{
+ {
+ Glib::Threads::RWLock::WriterLock lm (_lock);
+ EventList nel;
+ /* First scale existing events, copy into a new list.
+ * The original list is needed later to interpolate
+ * for new events only present in the master list.
+ */
+ for (iterator i = _events.begin(); i != _events.end(); ++i) {
+ float val = callback ((*i)->value, other.eval ((*i)->when));
+ nel.push_back (new ControlEvent ((*i)->when , val));
+ }
+ /* Now add events which are only present in the master-list. */
+ const EventList& evl (other.events());
+ for (const_iterator i = evl.begin(); i != evl.end(); ++i) {
+ bool found = false;
+ // TODO: optimize, remember last matching iterator (lists are sorted)
+ for (iterator j = _events.begin(); j != _events.end(); ++j) {
+ if ((*i)->when == (*j)->when) {
+ found = true;
+ break;
+ }
+ }
+ /* skip events that have already been merge in the first pass */
+ if (found) {
+ continue;
+ }
+ float val = callback (unlocked_eval ((*i)->when), (*i)->value);
+ nel.push_back (new ControlEvent ((*i)->when, val));
+ }
+ nel.sort (event_time_less_than);
+
+ for (EventList::iterator x = _events.begin(); x != _events.end(); ++x) {
+ delete (*x);
+ }
+ _events.clear ();
+ _events = nel;
+
+ unlocked_invalidate_insert_iterator ();
+ mark_dirty ();
+ }
+ maybe_signal_changed ();
+}
+
+void
ControlList::_x_scale (double factor)
{
for (iterator i = _events.begin(); i != _events.end(); ++i) {