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.
This commit is contained in:
parent
f149fd2653
commit
e02952a26c
@ -474,27 +474,6 @@ Route::process_output_buffers (BufferSet& bufs,
|
|||||||
}
|
}
|
||||||
#endif
|
#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;
|
bool re_inject_oob_data = false;
|
||||||
if ((*i) == _disk_reader) {
|
if ((*i) == _disk_reader) {
|
||||||
/* Well now, we've made it past the disk-writer and to the 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,
|
// here or in Session::* ? -> also zero send latencies,
|
||||||
// and make sure that re-enabling a route updates things again...
|
// 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);
|
Glib::Threads::RWLock::ReaderLock lm (_processor_lock);
|
||||||
|
|
||||||
samplecnt_t l_in = 0;
|
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)) {
|
if (boost::shared_ptr<Send> snd = boost::dynamic_pointer_cast<Send> (*i)) {
|
||||||
snd->set_delay_in (l_out + _output->latency());
|
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);
|
(*i)->set_output_latency (l_out);
|
||||||
if ((*i)->active ()) {
|
if ((*i)->active ()) {
|
||||||
l_out += (*i)->signal_latency ();
|
l_out += (*i)->signal_latency ();
|
||||||
@ -4008,6 +3998,27 @@ Route::update_signal_latency (bool apply_to_delayline)
|
|||||||
_signal_latency = l_out;
|
_signal_latency = l_out;
|
||||||
|
|
||||||
for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
|
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_input_latency (l_in);
|
||||||
(*i)->set_playback_offset (_signal_latency + _output->latency ());
|
(*i)->set_playback_offset (_signal_latency + _output->latency ());
|
||||||
(*i)->set_capture_offset (_input->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) {
|
for (ProcessorList::const_iterator i = _processors.begin(); i != _processors.end(); ++i) {
|
||||||
|
|
||||||
if ((*i)->active ()) {
|
if ((*i)->active ()) {
|
||||||
own_latency += (*i)->signal_latency ();
|
own_latency += (*i)->signal_latency ();
|
||||||
}
|
}
|
||||||
@ -4607,28 +4619,26 @@ Route::set_private_port_latencies (bool playback) const
|
|||||||
void
|
void
|
||||||
Route::set_public_port_latencies (samplecnt_t value, bool playback) const
|
Route::set_public_port_latencies (samplecnt_t value, bool playback) const
|
||||||
{
|
{
|
||||||
|
/* 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;
|
||||||
|
}
|
||||||
|
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
|
/* this is called to set the JACK-visible port latencies, which take
|
||||||
latency compensation into account.
|
* latency compensation into account.
|
||||||
*/
|
*/
|
||||||
|
_input->set_public_port_latencies (value, playback);
|
||||||
LatencyRange range;
|
_output->set_public_port_latencies (value, playback);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
const PortSet& ports (_output->ports());
|
|
||||||
for (PortSet::const_iterator p = ports.begin(); p != ports.end(); ++p) {
|
|
||||||
p->set_public_latency_range (range, playback);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Put the invisible processors in the right place in _processors.
|
/** Put the invisible processors in the right place in _processors.
|
||||||
|
Loading…
Reference in New Issue
Block a user