summaryrefslogtreecommitdiff
path: root/libs/ardour/route.cc
diff options
context:
space:
mode:
authorRobin Gareus <robin@gareus.org>2017-11-26 09:48:54 +0100
committerRobin Gareus <robin@gareus.org>2017-11-26 09:51:00 +0100
commite02952a26c28876ea81440ee98e46f28483b91d6 (patch)
tree2c27e0e5f06b2657dd12c6d9db825d9c8619545b /libs/ardour/route.cc
parentf149fd265315fc47488e56dd19e74ae45c7dbd96 (diff)
Sidechain latency compensation - part one
This properly sets the port-latencies of PluginInsert owned ports as well as handles external sends (send-target playback latency). NB. This needs more work to ensure that Sidechain input port playback latency is set before the feeding send queries it the connected latency. Re-ordering process may change sidechain or external-send latencies, but since re-ordering does not change the route's latency, engine.update_latency() may not be called.
Diffstat (limited to 'libs/ardour/route.cc')
-rw-r--r--libs/ardour/route.cc90
1 files changed, 50 insertions, 40 deletions
diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc
index c379158801..639a0e19bc 100644
--- a/libs/ardour/route.cc
+++ b/libs/ardour/route.cc
@@ -474,27 +474,6 @@ Route::process_output_buffers (BufferSet& bufs,
}
#endif
- if (boost::dynamic_pointer_cast<PluginInsert>(*i) != 0) {
- /* set potential sidechain ports, capture and playback latency.
- * This effectively sets jack port latency which should include
- * up/downstream latencies.
- *
- * However, the value is not used by Ardour (2017-09-20) and calling
- * IO::latency() is expensive, so we punt.
- *
- * capture should be
- * input()->latenct + latency,
- * playback should be
- * output->latency() + _signal_latency - latency
- *
- * Also see note below, _signal_latency may be smaller than latency
- * if a plugin's latency increases while it's running.
- */
- const samplecnt_t playback_latency = std::max ((samplecnt_t)0, _signal_latency - latency);
- boost::dynamic_pointer_cast<PluginInsert>(*i)->set_sidechain_latency (
- /* input->latency() + */ latency, /* output->latency() + */ playback_latency);
- }
-
bool re_inject_oob_data = false;
if ((*i) == _disk_reader) {
/* Well now, we've made it past the disk-writer and to the disk-reader.
@@ -3989,6 +3968,9 @@ Route::update_signal_latency (bool apply_to_delayline)
// here or in Session::* ? -> also zero send latencies,
// and make sure that re-enabling a route updates things again...
+ samplecnt_t capt_lat_in = _input->connected_latency (false);
+ samplecnt_t play_lat_out = _output->connected_latency (true);
+
Glib::Threads::RWLock::ReaderLock lm (_processor_lock);
samplecnt_t l_in = 0;
@@ -3997,6 +3979,14 @@ Route::update_signal_latency (bool apply_to_delayline)
if (boost::shared_ptr<Send> snd = boost::dynamic_pointer_cast<Send> (*i)) {
snd->set_delay_in (l_out + _output->latency());
}
+
+ if (boost::shared_ptr<PluginInsert> pi = boost::dynamic_pointer_cast<PluginInsert> (*i)) {
+ if (boost::shared_ptr<IO> pio = pi->sidechain_input ()) {
+ samplecnt_t lat = l_out + _output->latency();
+ pio->set_private_port_latencies (lat, true);
+ pio->set_public_port_latencies (lat, true);
+ }
+ }
(*i)->set_output_latency (l_out);
if ((*i)->active ()) {
l_out += (*i)->signal_latency ();
@@ -4008,6 +3998,27 @@ Route::update_signal_latency (bool apply_to_delayline)
_signal_latency = l_out;
for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
+
+ /* set sidechain, send and insert port latencies */
+ if (boost::shared_ptr<PortInsert> pi = boost::dynamic_pointer_cast<PortInsert> (*i)) {
+ if (pi->input ()) {
+ /* propagate playback latency from output to input */
+ pi->input ()->set_private_port_latencies (play_lat_out + l_in, true);
+ }
+ if (pi->output ()) {
+ /* propagate capture latency from input to output */
+ pi->output ()->set_private_port_latencies (capt_lat_in + l_in, false);
+ }
+
+ } else if (boost::shared_ptr<Send> snd = boost::dynamic_pointer_cast<Send> (*i)) {
+ if (snd->output ()) {
+ /* set capture latency */
+ snd->output ()->set_private_port_latencies (capt_lat_in + l_in, false);
+ /* take send-target's playback latency into account */
+ snd->set_delay_out (snd->output ()->connected_latency (true));
+ }
+ }
+
(*i)->set_input_latency (l_in);
(*i)->set_playback_offset (_signal_latency + _output->latency ());
(*i)->set_capture_offset (_input->latency ());
@@ -4590,6 +4601,7 @@ Route::set_private_port_latencies (bool playback) const
*/
for (ProcessorList::const_iterator i = _processors.begin(); i != _processors.end(); ++i) {
+
if ((*i)->active ()) {
own_latency += (*i)->signal_latency ();
}
@@ -4607,28 +4619,26 @@ Route::set_private_port_latencies (bool playback) const
void
Route::set_public_port_latencies (samplecnt_t value, bool playback) const
{
- /* this is called to set the JACK-visible port latencies, which take
- latency compensation into account.
- */
-
- LatencyRange range;
-
- range.min = value;
- range.max = value;
-
- {
- const PortSet& ports (_input->ports());
- for (PortSet::const_iterator p = ports.begin(); p != ports.end(); ++p) {
- p->set_public_latency_range (range, playback);
+ /* publish private latencies */
+ Glib::Threads::RWLock::ReaderLock lm (_processor_lock);
+ for (ProcessorList::const_iterator i = _processors.begin(); i != _processors.end(); ++i) {
+ boost::shared_ptr<IOProcessor> iop = boost::dynamic_pointer_cast<IOProcessor>(*i);
+ if (!iop) {
+ continue;
}
- }
-
- {
- const PortSet& ports (_output->ports());
- for (PortSet::const_iterator p = ports.begin(); p != ports.end(); ++p) {
- p->set_public_latency_range (range, playback);
+ if (iop->input ()) {
+ iop->input ()->set_public_port_latencies (iop->input()->latency(), true);
+ }
+ if (iop->output ()) {
+ iop->output ()->set_public_port_latencies (iop->output()->latency(), false);
}
}
+
+ /* this is called to set the JACK-visible port latencies, which take
+ * latency compensation into account.
+ */
+ _input->set_public_port_latencies (value, playback);
+ _output->set_public_port_latencies (value, playback);
}
/** Put the invisible processors in the right place in _processors.