summaryrefslogtreecommitdiff
path: root/libs/ardour
diff options
context:
space:
mode:
authorRobin Gareus <robin@gareus.org>2015-12-06 13:49:16 +0100
committerRobin Gareus <robin@gareus.org>2015-12-06 14:27:24 +0100
commit065d7c852a1586a3020affd6905f108abf252119 (patch)
treea89c10785b7ae940204930f797200979b0817e49 /libs/ardour
parentbc15146560abb7694e8e06735445f437d3ad40eb (diff)
outline a "NoSampleAccurateControl" LV2 feature:
Since control-ports have a fixed value for the current process-block, Ardour splits a plugin's run() process cycle on every automation event to facilitate sample-accurate automation. Since automation is interpolated between events, this ensures that each explicit automation point is reached (not interpolated). Plugins where this is not required and which favor a fixed block-size, can now specify an optional Feature: NoSampleAccurateControl. One example: a convolution plugin with smoothed gain control.
Diffstat (limited to 'libs/ardour')
-rw-r--r--libs/ardour/ardour/lv2_plugin.h2
-rw-r--r--libs/ardour/lv2_plugin.cc30
2 files changed, 32 insertions, 0 deletions
diff --git a/libs/ardour/ardour/lv2_plugin.h b/libs/ardour/ardour/lv2_plugin.h
index fcbf8b90cc..a0572b5af7 100644
--- a/libs/ardour/ardour/lv2_plugin.h
+++ b/libs/ardour/ardour/lv2_plugin.h
@@ -97,6 +97,7 @@ class LIBARDOUR_API LV2Plugin : public ARDOUR::Plugin, public ARDOUR::Workee
void cleanup ();
int set_block_size (pframes_t);
+ bool requires_fixed_sized_buffers () const;
int connect_and_run (BufferSet& bufs,
ChanMapping in, ChanMapping out,
@@ -178,6 +179,7 @@ class LIBARDOUR_API LV2Plugin : public ARDOUR::Plugin, public ARDOUR::Workee
uint32_t _patch_port_in_index;
uint32_t _patch_port_out_index;
URIMap& _uri_map;
+ bool _no_sample_accurate_ctrl;
friend const void* lv2plugin_get_port_value(const char* port_symbol,
void* user_data,
diff --git a/libs/ardour/lv2_plugin.cc b/libs/ardour/lv2_plugin.cc
index 47e1053a2c..940ec8ae03 100644
--- a/libs/ardour/lv2_plugin.cc
+++ b/libs/ardour/lv2_plugin.cc
@@ -155,6 +155,7 @@ public:
LilvNode* units_midiNote;
LilvNode* patch_writable;
LilvNode* patch_Message;
+ LilvNode* lv2_noSampleAccurateCtrl;
#ifdef HAVE_LV2_1_2_0
LilvNode* bufz_powerOf2BlockLength;
LilvNode* bufz_fixedBlockLength;
@@ -286,6 +287,7 @@ LV2Plugin::LV2Plugin (AudioEngine& engine,
, _patch_port_in_index((uint32_t)-1)
, _patch_port_out_index((uint32_t)-1)
, _uri_map(URIMap::instance())
+ , _no_sample_accurate_ctrl (false)
{
init(c_plugin, rate);
}
@@ -300,6 +302,7 @@ LV2Plugin::LV2Plugin (const LV2Plugin& other)
, _patch_port_in_index((uint32_t)-1)
, _patch_port_out_index((uint32_t)-1)
, _uri_map(URIMap::instance())
+ , _no_sample_accurate_ctrl (false)
{
init(other._impl->plugin, other._sample_rate);
@@ -481,6 +484,12 @@ LV2Plugin::init(const void* c_plugin, framecnt_t rate)
throw failed_constructor();
}
lilv_nodes_free(required_features);
+
+ LilvNodes* optional_features = lilv_plugin_get_optional_features (plugin);
+ if (lilv_nodes_contains (optional_features, _world.lv2_noSampleAccurateCtrl)) {
+ _no_sample_accurate_ctrl = true;
+ }
+ lilv_nodes_free(optional_features);
#endif
#ifdef HAVE_LILV_0_16_0
@@ -685,6 +694,25 @@ LV2Plugin::set_block_size (pframes_t nframes)
return 0;
}
+bool
+LV2Plugin::requires_fixed_sized_buffers () const
+{
+ /* This controls if Ardour will split the plugin's run()
+ * on automation events in order to pass sample-accurate automation
+ * via standard control-ports.
+ *
+ * When returning true Ardour will *not* sub-divide the process-cycle.
+ * Automation events that happen between cycle-start and cycle-end will be
+ * ignored (ctrl values are interpolated to cycle-start).
+ * NB. Atom Sequences are still sample accurate.
+ *
+ * Note: This does not guarantee a fixed block-size.
+ * e.g The process cycle may be split when looping, also
+ * the period-size may change any time: see set_block_size()
+ */
+ return _no_sample_accurate_ctrl;
+}
+
LV2Plugin::~LV2Plugin ()
{
DEBUG_TRACE(DEBUG::LV2, string_compose("%1 destroy\n", name()));
@@ -2448,6 +2476,7 @@ LV2World::LV2World()
units_db = lilv_new_uri(world, LV2_UNITS__db);
patch_writable = lilv_new_uri(world, LV2_PATCH__writable);
patch_Message = lilv_new_uri(world, LV2_PATCH__Message);
+ lv2_noSampleAccurateCtrl = lilv_new_uri(world, LV2_CORE_PREFIX "NoSampleAccurateCtrl"); // XXX
#ifdef HAVE_LV2_1_2_0
bufz_powerOf2BlockLength = lilv_new_uri(world, LV2_BUF_SIZE__powerOf2BlockLength);
bufz_fixedBlockLength = lilv_new_uri(world, LV2_BUF_SIZE__fixedBlockLength);
@@ -2463,6 +2492,7 @@ LV2World::~LV2World()
lilv_node_free(bufz_fixedBlockLength);
lilv_node_free(bufz_powerOf2BlockLength);
#endif
+ lilv_node_free(lv2_noSampleAccurateCtrl);
lilv_node_free(patch_Message);
lilv_node_free(patch_writable);
lilv_node_free(units_hz);