summaryrefslogtreecommitdiff
path: root/libs/ardour/slavable_automation_control.cc
diff options
context:
space:
mode:
authorRobin Gareus <robin@gareus.org>2017-06-03 13:18:31 +0200
committerRobin Gareus <robin@gareus.org>2017-06-03 13:55:14 +0200
commit9581cb26e444229301d5fdafadd14ca5c0a83a18 (patch)
tree9b11e817aa385f4120f3d671c1d666abae842f7c /libs/ardour/slavable_automation_control.cc
parentd662e6e0bfc4f541be2424cfe4d42b32b20c898c (diff)
Add infrastructure for evaluating VCA automation curves
Diffstat (limited to 'libs/ardour/slavable_automation_control.cc')
-rw-r--r--libs/ardour/slavable_automation_control.cc55
1 files changed, 55 insertions, 0 deletions
diff --git a/libs/ardour/slavable_automation_control.cc b/libs/ardour/slavable_automation_control.cc
index 6df2dd2720..40f4cb486f 100644
--- a/libs/ardour/slavable_automation_control.cc
+++ b/libs/ardour/slavable_automation_control.cc
@@ -24,6 +24,8 @@
#include "pbd/types_convert.h"
#include "pbd/i18n.h"
+#include "evoral/Curve.hpp"
+
#include "ardour/audioengine.h"
#include "ardour/slavable_automation_control.h"
#include "ardour/session.h"
@@ -110,6 +112,59 @@ SlavableAutomationControl::get_value() const
}
}
+bool
+SlavableAutomationControl::get_masters_curve_locked (framepos_t, framepos_t, float*, framecnt_t) const
+{
+ /* Every AutomationControl needs to implement this as-needed.
+ *
+ * This class also provides some convenient methods which
+ * could be used as defaults here (depending on AutomationType)
+ * e.g. masters_curve_multiply()
+ */
+ return false;
+}
+
+bool
+SlavableAutomationControl::masters_curve_multiply (framepos_t start, framepos_t end, float* vec, framecnt_t veclen) const
+{
+ bool rv = list()->curve().rt_safe_get_vector (start, end, vec, veclen);
+ if (_masters.empty()) {
+ return rv;
+ }
+ gain_t* scratch = _session.scratch_automation_buffer ();
+ for (Masters::const_iterator mr = _masters.begin(); mr != _masters.end(); ++mr) {
+ boost::shared_ptr<AutomationControl> ac (mr->second.master());
+ bool got_curve;
+
+ boost::shared_ptr<SlavableAutomationControl> sc
+ = boost::dynamic_pointer_cast<SlavableAutomationControl>(ac);
+ if (sc) {
+ got_curve = sc->get_masters_curve_locked (start, end, scratch, veclen);
+ } else {
+ got_curve = ac->list()->curve().rt_safe_get_vector (start, end, scratch, veclen);
+ }
+ if (got_curve) {
+ // TODO use SSE/AVX methods, e.g. ARDOUR::apply_gain_to_buffer, mix_buffers_no_gain
+ // which works as long as automation _types_ gain_t == ARDOUR::Sample type == float
+ if (!rv) {
+ // TODO optimize this, in case rv is false, direcly use "vec" above.
+ rv = true;
+ memcpy (vec, scratch, sizeof (float) * veclen);
+ } else {
+ for (framecnt_t i = 0; i < veclen; ++i) {
+ vec[i] *= scratch[i];
+ }
+ }
+ } else if (rv) {
+ const float v = get_masters_value ();
+ for (framecnt_t i = 0; i < veclen; ++i) {
+ vec[i] *= v;
+ }
+ }
+ }
+ return rv;
+}
+
void
SlavableAutomationControl::actually_set_value (double value, PBD::Controllable::GroupControlDisposition gcd)
{