summaryrefslogtreecommitdiff
path: root/libs/ardour/route.cc
diff options
context:
space:
mode:
authorRobin Gareus <robin@gareus.org>2017-09-19 02:10:38 +0200
committerRobin Gareus <robin@gareus.org>2017-09-19 02:11:22 +0200
commit10b76ae631d971611bcb389d18995942300d0404 (patch)
tree8fa12320f177b2745d8acdf6ceb3c37c34133459 /libs/ardour/route.cc
parent013088ca5f5d95654b43037685d835f212e38a8a (diff)
Various updates and fixes for Latency Compensation
* centralize signal_latency_at_***_position to processors * update initial-delay/roll-delay when processor order changes * consolidate signal-latency calculation: use the same method for processor-changes and session's post_playback_latency. * include relative output-delay in roll-delay * fix capture processor position & optimize stem-export latency (roll-delay fixes pending Route:roll() update)
Diffstat (limited to 'libs/ardour/route.cc')
-rw-r--r--libs/ardour/route.cc103
1 files changed, 57 insertions, 46 deletions
diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc
index 029fb99501..f0bd724e44 100644
--- a/libs/ardour/route.cc
+++ b/libs/ardour/route.cc
@@ -94,8 +94,6 @@ Route::Route (Session& sess, string name, PresentationInfo::Flag flag, DataType
, Muteable (sess, name)
, _active (true)
, _signal_latency (0)
- , _signal_latency_at_amp_position (0)
- , _signal_latency_at_trim_position (0)
, _initial_delay (0)
, _roll_delay (0)
, _disk_io_point (DiskIOPreFader)
@@ -332,14 +330,14 @@ Route::process_output_buffers (BufferSet& bufs,
if (gain_automation_ok) {
_amp->set_gain_automation_buffer (_session.gain_automation_buffer ());
_amp->setup_gain_automation (
- start_sample + _signal_latency_at_amp_position,
- end_sample + _signal_latency_at_amp_position,
+ start_sample + _amp->output_latency (),
+ end_sample + _amp->output_latency (),
nframes);
_trim->set_gain_automation_buffer (_session.trim_automation_buffer ());
_trim->setup_gain_automation (
- start_sample + _signal_latency_at_trim_position,
- end_sample + _signal_latency_at_trim_position,
+ start_sample + _trim->output_latency (),
+ end_sample + _trim->output_latency (),
nframes);
} else {
_amp->apply_gain_automation (false);
@@ -1809,8 +1807,6 @@ Route::configure_processors_unlocked (ProcessorStreams* err, Glib::Threads::RWLo
// TODO check for a potential ReaderLock after ReaderLock ??
Glib::Threads::RWLock::ReaderLock lr (_processor_lock);
- samplecnt_t chain_latency = _input->latency ();
-
list< pair<ChanCount,ChanCount> >::iterator c = configuration.begin();
for (ProcessorList::iterator p = _processors.begin(); p != _processors.end(); ++p, ++c) {
@@ -1822,9 +1818,6 @@ Route::configure_processors_unlocked (ProcessorStreams* err, Glib::Threads::RWLo
return -1;
}
- (*p)->set_input_latency (chain_latency);
- chain_latency += (*p)->signal_latency ();
-
processor_max_streams = ChanCount::max(processor_max_streams, c->first);
processor_max_streams = ChanCount::max(processor_max_streams, c->second);
@@ -2104,6 +2097,11 @@ Route::reorder_processors (const ProcessorList& new_order, ProcessorStreams* err
g_atomic_int_set (&_pending_process_reorder, 1);
}
+ /* update processor input/output latency
+ * (total signal_latency does not change)
+ */
+ update_signal_latency (true);
+
return 0;
}
@@ -3679,6 +3677,10 @@ Route::apply_processor_changes_rt ()
}
if (changed) {
set_processor_positions ();
+ /* update processor input/output latency
+ * (total signal_latency does not change)
+ */
+ update_signal_latency (true);
}
if (emissions != 0) {
g_atomic_int_set (&_pending_signals, emissions);
@@ -3851,8 +3853,9 @@ Route::add_export_point()
Glib::Threads::RWLock::WriterLock lw (_processor_lock);
// this aligns all tracks; but not tracks + busses
- assert (_session.worst_track_latency () >= _initial_delay);
- _capturing_processor.reset (new CapturingProcessor (_session, _session.worst_track_latency () - _initial_delay));
+ samplecnt_t latency = _session.worst_track_roll_delay ();
+ assert (latency >= _initial_delay);
+ _capturing_processor.reset (new CapturingProcessor (_session, latency - _initial_delay));
_capturing_processor->activate ();
configure_processors_unlocked (0, &lw);
@@ -3863,40 +3866,40 @@ Route::add_export_point()
}
samplecnt_t
-Route::update_signal_latency ()
+Route::update_signal_latency (bool set_initial_delay)
{
- samplecnt_t l = _output->user_latency();
- samplecnt_t lamp = 0;
- bool before_amp = true;
- samplecnt_t ltrim = 0;
- bool before_trim = true;
+ Glib::Threads::RWLock::ReaderLock lm (_processor_lock);
+
+ samplecnt_t l_in = _input->latency ();
+ samplecnt_t l_out = 0;
for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
if ((*i)->active ()) {
- l += (*i)->signal_latency ();
- }
- if ((*i) == _amp) {
- before_amp = false;
- }
- if ((*i) == _trim) {
- before_amp = false;
- }
- if (before_amp) {
- lamp = l;
- }
- if (before_trim) {
- lamp = l;
+ l_out += (*i)->signal_latency ();
+ l_in += (*i)->signal_latency ();
}
+ (*i)->set_input_latency (l_in);
+ (*i)->set_output_latency (l_out);
+ }
+
+ l_out += _output->user_latency();
+
+ for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
+ (*i)->set_output_latency (l_out - (*i)->output_latency ());
}
- DEBUG_TRACE (DEBUG::Latency, string_compose ("%1: internal signal latency = %2\n", _name, l));
+ DEBUG_TRACE (DEBUG::Latency, string_compose ("%1: internal signal latency = %2\n", _name, l_out));
- // TODO: (lamp - _signal_latency) to sync to output (read-ahed), currently _roll_delay shifts this around
- _signal_latency_at_amp_position = lamp;
- _signal_latency_at_trim_position = ltrim;
+ _signal_latency = l_out;
- if (_signal_latency != l) {
- _signal_latency = l;
+ lm.release ();
+
+ if (set_initial_delay) {
+ /* see also Session::post_playback_latency() */
+ set_latency_compensation (_session.worst_track_latency () + _session.worst_track_out_latency () - output ()->latency ());
+ }
+
+ if (_signal_latency != l_out) {
signal_latency_changed (); /* EMIT SIGNAL */
}
@@ -3914,9 +3917,10 @@ void
Route::set_latency_compensation (samplecnt_t longest_session_latency)
{
samplecnt_t old = _initial_delay;
+ assert (!_disk_reader || _disk_reader->output_latency () <= _signal_latency);
- if (_signal_latency < longest_session_latency) {
- _initial_delay = longest_session_latency - _signal_latency;
+ if (_disk_reader && _signal_latency < longest_session_latency) {
+ _initial_delay = longest_session_latency - (_signal_latency - _disk_reader->input_latency ());
} else {
_initial_delay = 0;
}
@@ -4651,7 +4655,7 @@ Route::setup_invisible_processors ()
ProcessorList::iterator trim = new_processors.end();
- if (_trim && _trim->active()) {
+ if (_trim->active()) {
assert (!_trim->display_to_user ());
new_processors.push_front (_trim);
trim = new_processors.begin();
@@ -4670,11 +4674,6 @@ Route::setup_invisible_processors ()
/* EXPORT PROCESSOR */
- if (_capturing_processor) {
- assert (!_capturing_processor->display_to_user ());
- new_processors.push_front (_capturing_processor);
- }
-
/* DISK READER & WRITER (for Track objects) */
if (_disk_reader || _disk_writer) {
@@ -4714,6 +4713,18 @@ Route::setup_invisible_processors ()
}
}
+ if (_capturing_processor) {
+ assert (!_capturing_processor->display_to_user ());
+ ProcessorList::iterator reader_pos = find (new_processors.begin(), new_processors.end(), _disk_reader);
+ if (reader_pos != new_processors.end()) {
+ /* insert after disk-reader */
+ new_processors.insert (++reader_pos, _capturing_processor);
+ } else {
+ new_processors.push_front (_capturing_processor);
+ }
+ }
+
+
_processors = new_processors;
for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {