From 8b917c4c1660e4a22d187a676b9dfb562aa06ee2 Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Wed, 14 Jun 2017 02:38:32 +0200 Subject: Add infrastructure to merge ControlLists --- libs/evoral/evoral/ControlList.hpp | 3 ++- libs/evoral/src/ControlList.cpp | 46 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) (limited to 'libs') 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 callback); + void list_merge (ControlList const& other, boost::function 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 @@ -263,6 +263,52 @@ ControlList::y_transform (boost::function callback) maybe_signal_changed (); } +void +ControlList::list_merge (ControlList const& other, boost::function 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) { -- cgit v1.2.3