13
0

Expose compensated port-latency, fix ambig. latency detection

Previously Ardour only announced processor latency.
Routes that had additional latency to compensate for those
have not published this delay.

This is of no concern with internal backends, however with JACK,
Ardour reported incorrect *individual* port-latencies of
routes that perform PDC.

Since public port latency now includes delay-compensation,
some extra work is required to unset it before recalculating
latency of paths that include external ports.
This commit is contained in:
Robin Gareus 2021-09-08 21:43:23 +02:00
parent c342e4bfa9
commit f301e692a7
Signed by: rgareus
GPG Key ID: A090BCE02CF57F04
5 changed files with 67 additions and 17 deletions

View File

@ -355,7 +355,7 @@ public:
virtual void apply_latency_compensation ();
samplecnt_t set_private_port_latencies (bool playback) const;
void set_public_port_latencies (samplecnt_t, bool playback) const;
void set_public_port_latencies (samplecnt_t, bool playback, bool with_latcomp) const;
samplecnt_t signal_latency() const { return _signal_latency; }
samplecnt_t playback_latency (bool incl_downstream = false) const;

View File

@ -1432,6 +1432,7 @@ private:
void remove_monitor_section ();
void update_latency (bool playback);
void set_owned_port_public_latency (bool playback);
bool update_route_latency (bool reverse, bool apply_to_delayline, bool* delayline_update_needed);
void initialize_latencies ();
void set_worst_output_latency ();

View File

@ -367,7 +367,7 @@ Port::set_public_latency_range (LatencyRange const& range, bool playback) const
if (_port_handle) {
LatencyRange r (range);
if (externally_connected () && 0 == (_flags & TransportSyncPort)) {
if (externally_connected () && 0 == (_flags & TransportSyncPort) && sends_output () == playback) {
#if 0
r.min *= _speed_ratio;
r.max *= _speed_ratio;
@ -399,10 +399,6 @@ Port::set_private_latency_range (LatencyRange& range, bool playback)
_private_capture_latency.min,
_private_capture_latency.max));
}
/* push to public (port system) location so that everyone else can see it */
set_public_latency_range (range, playback);
}
const LatencyRange&
@ -426,14 +422,14 @@ Port::private_latency_range (bool playback) const
}
LatencyRange
Port::public_latency_range (bool /*playback*/) const
Port::public_latency_range (bool playback) const
{
/*Note: this method is no longer used. It exists purely for debugging reasons */
LatencyRange r;
if (_port_handle) {
r = port_engine.get_latency_range (_port_handle, sends_output() ? true : false);
if (externally_connected () && 0 == (_flags & TransportSyncPort)) {
r = port_engine.get_latency_range (_port_handle, playback);
if (externally_connected () && 0 == (_flags & TransportSyncPort) && sends_output () == playback) {
#if 0
r.min /= _speed_ratio;
r.max /= _speed_ratio;
@ -450,7 +446,7 @@ Port::public_latency_range (bool /*playback*/) const
DEBUG_TRACE (DEBUG::LatencyIO, string_compose (
"GET PORT %1: %4 PUBLIC latency range %2 .. %3\n",
name(), r.min, r.max,
sends_output() ? "PLAYBACK" : "CAPTURE"));
playback ? "PLAYBACK" : "CAPTURE"));
}
return r;
@ -487,7 +483,7 @@ Port::get_connected_latency_range (LatencyRange& range, bool playback) const
if (remote_port) {
lr = port_engine.get_latency_range (remote_port, playback);
if (externally_connected () && 0 == (_flags & TransportSyncPort)) {
if (externally_connected () && 0 == (_flags & TransportSyncPort) && sends_output () == playback) {
#if 0
lr.min /= _speed_ratio;
lr.max /= _speed_ratio;

View File

@ -4412,7 +4412,12 @@ Route::apply_latency_compensation ()
cout << "ROUTE " << name() << " delay for " << latcomp << " (c: " << latcomp_capt << ")" << endl;
#endif
_delayline->set_delay (latcomp > 0 ? latcomp : 0);
if (_delayline->set_delay (latcomp > 0 ? latcomp : 0)) {
DEBUG_TRACE (DEBUG::LatencyRoute, string_compose ("%1: delay changed to %2\n", _name, latcomp));
/* public port latency update is needed,
* Session::update_latency() calls this->set_public_port_latencies()
*/
}
}
void
@ -4975,7 +4980,7 @@ Route::set_private_port_latencies (bool playback) const
}
void
Route::set_public_port_latencies (samplecnt_t value, bool playback) const
Route::set_public_port_latencies (samplecnt_t value, bool playback, bool with_latcomp) const
{
/* publish private latencies */
Glib::Threads::RWLock::ReaderLock lm (_processor_lock);
@ -4985,9 +4990,10 @@ Route::set_public_port_latencies (samplecnt_t value, bool playback) const
continue;
}
if (iop->input ()) {
assert (iop->input () != _input); // no delivery for Input
iop->input ()->set_public_port_latencies (iop->input()->latency(), true);
}
if (iop->output ()) {
if (iop->output () && iop->output () != _output) {
iop->output ()->set_public_port_latencies (iop->output()->latency(), false);
}
}
@ -4995,8 +5001,20 @@ 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.
*/
_input->set_public_port_latencies (value, playback);
_output->set_public_port_latencies (value, playback);
if (playback) {
_output->set_public_port_latencies (_output->latency (), playback);
if (_delayline && with_latcomp) {
value += _delayline->delay ();
}
_input->set_public_port_latencies (value, playback);
} else {
_input->set_public_port_latencies (_input->latency(), playback);
if (_delayline && with_latcomp) {
value += _delayline->delay ();
}
_output->set_public_port_latencies (value, playback);
}
}
/** Put the invisible processors in the right place in _processors.

View File

@ -6675,6 +6675,21 @@ restart:
return changed;
}
void
Session::set_owned_port_public_latency (bool playback)
{
/* special routes or IO or ports owned by the session */
if (auditioner) {
samplecnt_t latency = auditioner->set_private_port_latencies (playback);
auditioner->set_public_port_latencies (latency, playback, true);
}
_click_io->set_public_port_latencies (_click_io->connected_latency (playback), playback);
if (_midi_ports) {
_midi_ports->set_public_latency (playback);
}
}
void
Session::update_latency (bool playback)
{
@ -6744,10 +6759,18 @@ Session::update_latency (bool playback)
reverse (r->begin(), r->end());
}
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
/* private port latency includes plugin and I/O delay,
* but no latency compensation delaylines.
*/
samplecnt_t latency = (*i)->set_private_port_latencies (playback);
(*i)->set_public_port_latencies (latency, playback);
/* However we also need to reset the latency of connected external
* ports, since those includes latency compensation delaylines.
*/
(*i)->set_public_port_latencies (latency, playback, false);
}
set_owned_port_public_latency (playback);
if (playback) {
/* Processing needs to be blocked while re-configuring delaylines.
*
@ -6773,6 +6796,18 @@ Session::update_latency (bool playback)
update_route_latency (false, false, NULL);
}
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
/* Publish port latency. This includes latency-compensation
* delaylines in the direction of signal flow.
*/
samplecnt_t latency = (*i)->set_private_port_latencies (playback);
(*i)->set_public_port_latencies (latency, playback, true);
}
/* now handle non-route ports that we are responsible for */
set_owned_port_public_latency (playback);
DEBUG_TRACE (DEBUG::LatencyCompensation, "Engine latency callback: DONE\n");
LatencyUpdated (playback); /* EMIT SIGNAL */
}