summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
Diffstat (limited to 'libs')
-rw-r--r--libs/ardour/ardour/automation_event.h2
-rw-r--r--libs/ardour/ardour/configuration_vars.h1
-rw-r--r--libs/ardour/automation_event.cc142
-rw-r--r--libs/ardour/io.cc4
4 files changed, 96 insertions, 53 deletions
diff --git a/libs/ardour/ardour/automation_event.h b/libs/ardour/ardour/automation_event.h
index 909a39ef26..45227dc040 100644
--- a/libs/ardour/ardour/automation_event.h
+++ b/libs/ardour/ardour/automation_event.h
@@ -134,7 +134,7 @@ class AutomationList : public PBD::StatefulDestructible
}
void start_touch (double when);
- void stop_touch (bool mark, double when);
+ void stop_touch (bool mark, double when, double value);
bool touching() const { return g_atomic_int_get (&_touching); }
void set_yrange (double min, double max) {
diff --git a/libs/ardour/ardour/configuration_vars.h b/libs/ardour/ardour/configuration_vars.h
index 31a2ae9140..8b95ecfd85 100644
--- a/libs/ardour/ardour/configuration_vars.h
+++ b/libs/ardour/ardour/configuration_vars.h
@@ -159,6 +159,7 @@ CONFIG_VARIABLE (bool, use_overlap_equivalency, "use-overlap-equivalency", false
CONFIG_VARIABLE (bool, periodic_safety_backups, "periodic-safety-backups", true)
CONFIG_VARIABLE (uint32_t, periodic_safety_backup_interval, "periodic-safety-backup-interval", 120)
CONFIG_VARIABLE (float, automation_interval, "automation-interval", 50)
+CONFIG_VARIABLE (float, automation_thinning_strength, "automation-thinning-strength", 10)
CONFIG_VARIABLE (bool, sync_all_route_ordering, "sync-all-route-ordering", true)
CONFIG_VARIABLE (bool, only_copy_imported_files, "only-copy-imported-files", false)
CONFIG_VARIABLE (bool, new_plugins_active, "new-plugins-active", true)
diff --git a/libs/ardour/automation_event.cc b/libs/ardour/automation_event.cc
index dd2930a1a6..e17f9fb91b 100644
--- a/libs/ardour/automation_event.cc
+++ b/libs/ardour/automation_event.cc
@@ -248,7 +248,7 @@ AutomationList::start_touch (double when)
}
void
-AutomationList::stop_touch (bool mark, double when)
+AutomationList::stop_touch (bool mark, double when, double value)
{
g_atomic_int_set (&_touching, 0);
@@ -268,6 +268,11 @@ AutomationList::stop_touch (bool mark, double when)
delete ninfo;
}
}
+
+ //if no automation yet
+ if (events.empty()) {
+ default_value = value;
+ }
}
void
@@ -313,12 +318,30 @@ void AutomationList::_x_scale (double factor)
void
AutomationList::write_pass_finished (double when)
{
- merge_nascent (when);
+ //if fader is in Write, we need to put an automation point to mark the last place we rolled.
+ if ( (_state & Auto_Write) ) {
+ if ( nascent.back() && !nascent.back()->events.empty() ) {
+ rt_add( when, nascent.back()->events.back()->value );
+ }
+ }
+
+ merge_nascent (when);
}
void
AutomationList::rt_add (double when, double value)
{
+ //for now, automation only writes during forward motion
+ //if transport goes in reverse, start a new nascent pass and ignore this change
+ float last_when = 0;
+ if (!nascent.back()->events.empty())
+ last_when = nascent.back()->events.back()->when;
+ if ( (when < last_when) ) {
+ Glib::Mutex::Lock lm (lock);
+ nascent.push_back (new NascentInfo (false));
+ return;
+ }
+
/* this is for automation recording */
if ((_state & Auto_Touch) && !touching()) {
@@ -329,10 +352,11 @@ AutomationList::rt_add (double when, double value)
if (lm.locked()) {
assert (!nascent.empty());
- if (!nascent.back()->events.empty()) {
- assert (when > nascent.back()->events.back()->when);
- }
- nascent.back()->events.push_back (point_factory (when, value));
+ if (nascent.back()->events.empty() ){
+ nascent.back()->events.push_back (point_factory (when, value));
+ } else if (when > nascent.back()->events.back()->when) {
+ nascent.back()->events.push_back (point_factory (when, value));
+ }
}
}
@@ -346,14 +370,48 @@ AutomationList::merge_nascent (double when)
return;
}
- for (list<NascentInfo*>::iterator n = nascent.begin(); n != nascent.end(); ++n) {
+ //thin automation data in each nascent packet
+ for (list<NascentInfo*>::iterator n = nascent.begin(); n != nascent.end(); ++n) {
+ ControlEvent *next = NULL;
+ ControlEvent *cur = NULL;
+ ControlEvent *prev = NULL;
+ int counter = 0;
+ AutomationEventList delete_list;
+ for (AutomationEventList::iterator x = (*n)->events.begin(); x != (*n)->events.end(); x++) {
+ next = *x;
+ counter++;
+ if (counter > 2) { //wait for the third iteration so "cur" & "prev" are initialized
+
+ float area = fabs(
+ 0.5 * (
+ prev->when*(cur->value - next->value) +
+ cur->when*(next->value - prev->value) +
+ next->when*(prev->value - cur->value) )
+ );
+
+//printf( "area: %3.16f\n", area);
+ if (area < ( Config->get_automation_thinning_strength() ) )
+ delete_list.push_back(cur);
+ }
+ prev = cur;
+ cur = next;
+ }
+
+ for (AutomationEventList::iterator x = delete_list.begin(); x != delete_list.end(); ++x) {
+ (*n)->events.remove(*x);
+ delete *x;
+ }
+
+ }
+
+ for (list<NascentInfo*>::iterator n = nascent.begin(); n != nascent.end(); ++n) {
NascentInfo* ninfo = *n;
AutomationEventList& nascent_events (ninfo->events);
bool need_adjacent_start_clamp;
bool need_adjacent_end_clamp;
- if (nascent_events.empty()) {
+ if (nascent_events.size() < 2) {
delete ninfo;
continue;
}
@@ -363,27 +421,15 @@ AutomationList::merge_nascent (double when)
}
if (ninfo->end_time < 0.0) {
- ninfo->end_time = when;
+ ninfo->end_time = nascent_events.back()->when;
}
- bool preexisting = !events.empty();
+ bool preexisting = !events.empty();
if (!preexisting) {
events = nascent_events;
- } else if (ninfo->end_time < events.front()->when) {
-
- /* all points in nascent are before the first existing point */
-
- events.insert (events.begin(), nascent_events.begin(), nascent_events.end());
-
- } else if (ninfo->start_time > events.back()->when) {
-
- /* all points in nascent are after the last existing point */
-
- events.insert (events.end(), nascent_events.begin(), nascent_events.end());
-
} else {
/* find the range that overaps with nascent events,
@@ -393,7 +439,7 @@ AutomationList::merge_nascent (double when)
iterator i;
iterator range_begin = events.end();
iterator range_end = events.end();
- double end_value = unlocked_eval (ninfo->end_time);
+ double end_value = unlocked_eval (ninfo->end_time + 1);
double start_value = unlocked_eval (ninfo->start_time - 1);
need_adjacent_end_clamp = true;
@@ -435,25 +481,25 @@ AutomationList::merge_nascent (double when)
}
}
}
-
- assert (range_begin != events.end());
-
- if (range_begin != events.begin()) {
- /* clamp point before */
- if (need_adjacent_start_clamp) {
- events.insert (range_begin, point_factory (ninfo->start_time, start_value));
- }
- }
-
- events.insert (range_begin, nascent_events.begin(), nascent_events.end());
-
- if (range_end != events.end()) {
- /* clamp point after */
- if (need_adjacent_end_clamp) {
- events.insert (range_begin, point_factory (ninfo->end_time, end_value));
- }
- }
-
+
+ //if you write past the end of existing automation,
+ //then treat it as virgin territory
+ if (range_end == events.end()) {
+ need_adjacent_end_clamp = false;
+ }
+
+ /* clamp point before */
+ if (need_adjacent_start_clamp) {
+ events.insert (range_begin, point_factory (ninfo->start_time-1, start_value));
+ }
+
+ events.insert (range_begin, nascent_events.begin(), nascent_events.end());
+
+ /* clamp point after */
+ if (need_adjacent_end_clamp) {
+ events.insert (range_begin, point_factory (ninfo->end_time+1, end_value));
+ }
+
events.erase (range_begin, range_end);
}
@@ -474,7 +520,8 @@ void
AutomationList::fast_simple_add (double when, double value)
{
/* to be used only for loading pre-sorted data from saved state */
- events.insert (events.end(), point_factory (when, value));
+ if ( events.empty() || (when > events.back()->when) )
+ events.insert (events.end(), point_factory (when, value));
}
void
@@ -983,12 +1030,7 @@ AutomationList::shared_eval (double x)
return default_value;
case 1:
- if (x >= events.front()->when) {
- return events.front()->value;
- } else {
- // return default_value;
- return events.front()->value;
- }
+ return events.front()->value;
case 2:
if (x >= events.back()->when) {
@@ -1022,7 +1064,7 @@ AutomationList::shared_eval (double x)
return events.front()->value;
}
- return multipoint_eval (x);
+ return AutomationList::multipoint_eval (x); //switch to plain linear for now.
break;
}
diff --git a/libs/ardour/io.cc b/libs/ardour/io.cc
index f41cf6c691..be03df7926 100644
--- a/libs/ardour/io.cc
+++ b/libs/ardour/io.cc
@@ -2683,7 +2683,7 @@ IO::end_gain_touch ()
when = _session.transport_frame();
}
- _gain_automation_curve.stop_touch (mark, when);
+ _gain_automation_curve.stop_touch (mark, when, gain());
}
void
@@ -2706,7 +2706,7 @@ IO::end_pan_touch (uint32_t which)
when = _session.transport_frame();
}
- (*_panner)[which]->automation().stop_touch(mark, when);
+ (*_panner)[which]->automation().stop_touch(mark, when, 0);
}
}