mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-07 15:25:01 +01:00
Aux-Send Latency compensation, part 2 & code-consolidation
This commit is contained in:
parent
9f9e948d84
commit
2b20f30d81
3 changed files with 126 additions and 118 deletions
|
|
@ -170,7 +170,7 @@ private:
|
||||||
/** Ardour Session */
|
/** Ardour Session */
|
||||||
class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionList, public SessionEventManager
|
class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionList, public SessionEventManager
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
enum SubState {
|
enum SubState {
|
||||||
PendingDeclickIn = 0x1, ///< pending de-click fade-in for start
|
PendingDeclickIn = 0x1, ///< pending de-click fade-in for start
|
||||||
PendingDeclickOut = 0x2, ///< pending de-click fade-out for stop
|
PendingDeclickOut = 0x2, ///< pending de-click fade-out for stop
|
||||||
|
|
@ -180,7 +180,7 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
|
||||||
PendingLocate = 0x20,
|
PendingLocate = 0x20,
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum RecordState {
|
enum RecordState {
|
||||||
Disabled = 0,
|
Disabled = 0,
|
||||||
Enabled = 1,
|
Enabled = 1,
|
||||||
|
|
@ -476,9 +476,7 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
|
||||||
pframes_t get_block_size () const { return current_block_size; }
|
pframes_t get_block_size () const { return current_block_size; }
|
||||||
samplecnt_t worst_output_latency () const { return _worst_output_latency; }
|
samplecnt_t worst_output_latency () const { return _worst_output_latency; }
|
||||||
samplecnt_t worst_input_latency () const { return _worst_input_latency; }
|
samplecnt_t worst_input_latency () const { return _worst_input_latency; }
|
||||||
samplecnt_t worst_track_latency () const { return _worst_track_latency; }
|
samplecnt_t worst_route_latency () const { return _worst_route_latency; }
|
||||||
samplecnt_t worst_track_out_latency () const { return _worst_track_out_latency; }
|
|
||||||
samplecnt_t worst_playback_latency () const { return std::max (_worst_output_latency, _worst_track_latency); }
|
|
||||||
samplecnt_t worst_latency_preroll () const;
|
samplecnt_t worst_latency_preroll () const;
|
||||||
|
|
||||||
struct SaveAs {
|
struct SaveAs {
|
||||||
|
|
@ -1207,7 +1205,7 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
|
||||||
void auto_connect_thread_wakeup ();
|
void auto_connect_thread_wakeup ();
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class AudioEngine;
|
friend class AudioEngine;
|
||||||
void set_block_size (pframes_t nframes);
|
void set_block_size (pframes_t nframes);
|
||||||
void set_sample_rate (samplecnt_t nframes);
|
void set_sample_rate (samplecnt_t nframes);
|
||||||
|
|
@ -1215,12 +1213,11 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
|
||||||
void reconnect_existing_routes (bool withLock, bool reconnect_master = true, bool reconnect_inputs = true, bool reconnect_outputs = true);
|
void reconnect_existing_routes (bool withLock, bool reconnect_master = true, bool reconnect_inputs = true, bool reconnect_outputs = true);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
protected:
|
|
||||||
friend class Route;
|
friend class Route;
|
||||||
void schedule_curve_reallocation ();
|
void schedule_curve_reallocation ();
|
||||||
void update_latency_compensation (bool force = false);
|
void update_latency_compensation (bool force = false);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int create (const std::string& mix_template, BusProfile*);
|
int create (const std::string& mix_template, BusProfile*);
|
||||||
void destroy ();
|
void destroy ();
|
||||||
|
|
||||||
|
|
@ -1263,13 +1260,12 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
|
||||||
|
|
||||||
bool auto_play_legal;
|
bool auto_play_legal;
|
||||||
samplepos_t _last_slave_transport_sample;
|
samplepos_t _last_slave_transport_sample;
|
||||||
samplecnt_t maximum_output_latency;
|
|
||||||
samplepos_t _requested_return_sample;
|
samplepos_t _requested_return_sample;
|
||||||
pframes_t current_block_size;
|
pframes_t current_block_size;
|
||||||
samplecnt_t _worst_output_latency;
|
samplecnt_t _worst_output_latency;
|
||||||
samplecnt_t _worst_input_latency;
|
samplecnt_t _worst_input_latency;
|
||||||
samplecnt_t _worst_track_latency;
|
samplecnt_t _worst_route_latency;
|
||||||
samplecnt_t _worst_track_out_latency;
|
uint32_t _send_latency_changes;
|
||||||
bool _have_captured;
|
bool _have_captured;
|
||||||
bool _non_soloed_outs_muted;
|
bool _non_soloed_outs_muted;
|
||||||
bool _listening;
|
bool _listening;
|
||||||
|
|
@ -1288,16 +1284,15 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
|
||||||
PBD::ScopedConnection ltc_status_connection;
|
PBD::ScopedConnection ltc_status_connection;
|
||||||
|
|
||||||
void initialize_latencies ();
|
void initialize_latencies ();
|
||||||
void set_worst_io_latencies ();
|
void update_latency (bool playback);
|
||||||
void set_worst_playback_latency ();
|
bool update_route_latency (bool reverse, bool apply_to_delayline);
|
||||||
void set_worst_capture_latency ();
|
|
||||||
void set_worst_io_latencies_x (IOChange, void *) {
|
|
||||||
set_worst_io_latencies ();
|
|
||||||
}
|
|
||||||
void post_capture_latency ();
|
|
||||||
void post_playback_latency ();
|
|
||||||
|
|
||||||
void update_latency_compensation_proxy (void* ignored);
|
void set_worst_io_latencies ();
|
||||||
|
void set_worst_output_latency ();
|
||||||
|
void set_worst_input_latency ();
|
||||||
|
|
||||||
|
void send_latency_compensation_change ();
|
||||||
|
void set_worst_io_latencies_x (IOChange, void *);
|
||||||
|
|
||||||
void ensure_buffers (ChanCount howmany = ChanCount::ZERO);
|
void ensure_buffers (ChanCount howmany = ChanCount::ZERO);
|
||||||
|
|
||||||
|
|
@ -1793,15 +1788,13 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
|
||||||
|
|
||||||
mutable Glib::Threads::Mutex source_lock;
|
mutable Glib::Threads::Mutex source_lock;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef std::map<PBD::ID,boost::shared_ptr<Source> > SourceMap;
|
typedef std::map<PBD::ID,boost::shared_ptr<Source> > SourceMap;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void reset_write_sources (bool mark_write_complete, bool force = false);
|
void reset_write_sources (bool mark_write_complete, bool force = false);
|
||||||
SourceMap sources;
|
SourceMap sources;
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
int load_sources (const XMLNode& node);
|
int load_sources (const XMLNode& node);
|
||||||
XMLNode& get_sources_as_xml ();
|
XMLNode& get_sources_as_xml ();
|
||||||
|
|
||||||
|
|
@ -1903,8 +1896,6 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
|
||||||
|
|
||||||
void process_rtop (SessionEvent*);
|
void process_rtop (SessionEvent*);
|
||||||
|
|
||||||
void update_latency (bool playback);
|
|
||||||
|
|
||||||
enum snapshot_t {
|
enum snapshot_t {
|
||||||
NormalSave,
|
NormalSave,
|
||||||
SnapshotKeep,
|
SnapshotKeep,
|
||||||
|
|
|
||||||
|
|
@ -4045,11 +4045,18 @@ Route::add_export_point()
|
||||||
samplecnt_t
|
samplecnt_t
|
||||||
Route::update_signal_latency (bool apply_to_delayline)
|
Route::update_signal_latency (bool apply_to_delayline)
|
||||||
{
|
{
|
||||||
|
// TODO: bail out if !active() and set/assume _signal_latency = 0,
|
||||||
|
// here or in Session::* ? -> also zero send latencies,
|
||||||
|
// and make sure that re-enabling a route updates things again...
|
||||||
|
|
||||||
Glib::Threads::RWLock::ReaderLock lm (_processor_lock);
|
Glib::Threads::RWLock::ReaderLock lm (_processor_lock);
|
||||||
|
|
||||||
samplecnt_t l_in = 0; // _input->latency ();
|
samplecnt_t l_in = 0;
|
||||||
samplecnt_t l_out = _output->user_latency();
|
samplecnt_t l_out = _output->user_latency();
|
||||||
for (ProcessorList::reverse_iterator i = _processors.rbegin(); i != _processors.rend(); ++i) {
|
for (ProcessorList::reverse_iterator i = _processors.rbegin(); i != _processors.rend(); ++i) {
|
||||||
|
if (boost::shared_ptr<Send> snd = boost::dynamic_pointer_cast<Send> (*i)) {
|
||||||
|
snd->set_delay_in (l_out + _output->latency());
|
||||||
|
}
|
||||||
(*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 ();
|
||||||
|
|
@ -4069,7 +4076,6 @@ Route::update_signal_latency (bool apply_to_delayline)
|
||||||
(*i)->set_capture_offset (_input->latency ());
|
(*i)->set_capture_offset (_input->latency ());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
lm.release ();
|
lm.release ();
|
||||||
|
|
||||||
if (apply_to_delayline) {
|
if (apply_to_delayline) {
|
||||||
|
|
|
||||||
|
|
@ -194,13 +194,12 @@ Session::Session (AudioEngine &eng,
|
||||||
, _target_transport_speed (0.0)
|
, _target_transport_speed (0.0)
|
||||||
, auto_play_legal (false)
|
, auto_play_legal (false)
|
||||||
, _last_slave_transport_sample (0)
|
, _last_slave_transport_sample (0)
|
||||||
, maximum_output_latency (0)
|
|
||||||
, _requested_return_sample (-1)
|
, _requested_return_sample (-1)
|
||||||
, current_block_size (0)
|
, current_block_size (0)
|
||||||
, _worst_output_latency (0)
|
, _worst_output_latency (0)
|
||||||
, _worst_input_latency (0)
|
, _worst_input_latency (0)
|
||||||
, _worst_track_latency (0)
|
, _worst_route_latency (0)
|
||||||
, _worst_track_out_latency (0)
|
, _send_latency_changes (0)
|
||||||
, _have_captured (false)
|
, _have_captured (false)
|
||||||
, _non_soloed_outs_muted (false)
|
, _non_soloed_outs_muted (false)
|
||||||
, _listening (false)
|
, _listening (false)
|
||||||
|
|
@ -463,6 +462,8 @@ Session::Session (AudioEngine &eng,
|
||||||
StartTimeChanged.connect_same_thread (*this, boost::bind (&Session::start_time_changed, this, _1));
|
StartTimeChanged.connect_same_thread (*this, boost::bind (&Session::start_time_changed, this, _1));
|
||||||
EndTimeChanged.connect_same_thread (*this, boost::bind (&Session::end_time_changed, this, _1));
|
EndTimeChanged.connect_same_thread (*this, boost::bind (&Session::end_time_changed, this, _1));
|
||||||
|
|
||||||
|
Send::ChangedLatency.connect_same_thread (*this, boost::bind (&Session::send_latency_compensation_change, this));
|
||||||
|
|
||||||
emit_thread_start ();
|
emit_thread_start ();
|
||||||
auto_connect_thread_start ();
|
auto_connect_thread_start ();
|
||||||
|
|
||||||
|
|
@ -5717,13 +5718,9 @@ Session::graph_reordered ()
|
||||||
resort_routes ();
|
resort_routes ();
|
||||||
|
|
||||||
/* force all diskstreams to update their capture offset values to
|
/* force all diskstreams to update their capture offset values to
|
||||||
reflect any changes in latencies within the graph.
|
* reflect any changes in latencies within the graph.
|
||||||
*/
|
*/
|
||||||
|
update_route_latency (false, true);
|
||||||
boost::shared_ptr<RouteList> rl = routes.reader ();
|
|
||||||
for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
|
|
||||||
(*i)->update_signal_latency (true); // XXX
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return Number of samples that there is disk space available to write,
|
/** @return Number of samples that there is disk space available to write,
|
||||||
|
|
@ -6832,10 +6829,77 @@ Session::unknown_processors () const
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Session::set_worst_io_latencies_x (IOChange, void *)
|
||||||
|
{
|
||||||
|
set_worst_io_latencies ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Session::send_latency_compensation_change ()
|
||||||
|
{
|
||||||
|
/* As a result of Send::set_output_latency()
|
||||||
|
* or InternalReturn::set_playback_offset ()
|
||||||
|
* the send's own latency can change (source track
|
||||||
|
* is aligned with target bus).
|
||||||
|
*
|
||||||
|
* This can only happen be triggered by
|
||||||
|
* Route::update_signal_latency ()
|
||||||
|
* when updating the processor latency.
|
||||||
|
*
|
||||||
|
* We need to walk the graph again to take those changes into account
|
||||||
|
* (we should probably recurse or process the graph in a 2 step process).
|
||||||
|
*/
|
||||||
|
++_send_latency_changes;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
Session::update_route_latency (bool playback, bool apply_to_delayline)
|
||||||
|
{
|
||||||
|
/* Note: RouteList is process-graph sorted */
|
||||||
|
boost::shared_ptr<RouteList> r = routes.reader ();
|
||||||
|
|
||||||
|
if (playback) {
|
||||||
|
/* reverse the list so that we work backwards from the last route to run to the first,
|
||||||
|
* this is not needed, but can help to reduce the iterations for aux-sends.
|
||||||
|
*/
|
||||||
|
RouteList* rl = routes.reader().get();
|
||||||
|
r.reset (new RouteList (*rl));
|
||||||
|
reverse (r->begin(), r->end());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool changed = false;
|
||||||
|
int bailout = 0;
|
||||||
|
restart:
|
||||||
|
_send_latency_changes = 0;
|
||||||
|
_worst_route_latency = 0;
|
||||||
|
|
||||||
|
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
|
||||||
|
// if (!(*i)->active()) { continue ; } // TODO
|
||||||
|
samplecnt_t l;
|
||||||
|
if ((*i)->signal_latency () != (l = (*i)->update_signal_latency (apply_to_delayline))) {
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
_worst_route_latency = std::max (l, _worst_route_latency);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_send_latency_changes > 0) {
|
||||||
|
// only 1 extra iteration is needed (we allow only 1 level of aux-sends)
|
||||||
|
// BUT.. jack'n'sends'n'bugs
|
||||||
|
if (++bailout < 5) {
|
||||||
|
cerr << "restarting Session::update_latency. # of send changes: " << _send_latency_changes << " iteration: " << bailout << endl;
|
||||||
|
goto restart;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG_TRACE (DEBUG::Latency, string_compose ("worst signal processing latency: %1 (changed ? %2)\n", _worst_route_latency, (changed ? "yes" : "no")));
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Session::update_latency (bool playback)
|
Session::update_latency (bool playback)
|
||||||
{
|
{
|
||||||
|
|
||||||
DEBUG_TRACE (DEBUG::Latency, string_compose ("JACK latency callback: %1\n", (playback ? "PLAYBACK" : "CAPTURE")));
|
DEBUG_TRACE (DEBUG::Latency, string_compose ("JACK latency callback: %1\n", (playback ? "PLAYBACK" : "CAPTURE")));
|
||||||
|
|
||||||
if ((_state_of_the_state & (InitialConnecting|Deletion)) || _adding_routes_in_progress || _route_deletion_in_progress) {
|
if ((_state_of_the_state & (InitialConnecting|Deletion)) || _adding_routes_in_progress || _route_deletion_in_progress) {
|
||||||
|
|
@ -6861,47 +6925,16 @@ Session::update_latency (bool playback)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (playback) {
|
if (playback) {
|
||||||
post_playback_latency ();
|
set_worst_output_latency ();
|
||||||
|
update_route_latency (true, true);
|
||||||
} else {
|
} else {
|
||||||
post_capture_latency ();
|
set_worst_input_latency ();
|
||||||
|
update_route_latency (false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG_TRACE (DEBUG::Latency, "JACK latency callback: DONE\n");
|
DEBUG_TRACE (DEBUG::Latency, "JACK latency callback: DONE\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
Session::post_playback_latency ()
|
|
||||||
{
|
|
||||||
set_worst_playback_latency ();
|
|
||||||
|
|
||||||
boost::shared_ptr<RouteList> r = routes.reader ();
|
|
||||||
|
|
||||||
_worst_track_out_latency = 0; // XXX remove me
|
|
||||||
|
|
||||||
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
|
|
||||||
assert (!(*i)->is_auditioner()); // XXX remove me
|
|
||||||
_worst_track_latency = max (_worst_track_latency, (*i)->update_signal_latency ());
|
|
||||||
}
|
|
||||||
|
|
||||||
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
|
|
||||||
if (!(*i)->active()) { continue ; }
|
|
||||||
(*i)->apply_latency_compensation ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Session::post_capture_latency ()
|
|
||||||
{
|
|
||||||
set_worst_capture_latency ();
|
|
||||||
|
|
||||||
/* reflect any changes in capture latencies into capture offsets */
|
|
||||||
|
|
||||||
boost::shared_ptr<RouteList> rl = routes.reader();
|
|
||||||
for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
|
|
||||||
(*i)->update_signal_latency ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Session::initialize_latencies ()
|
Session::initialize_latencies ()
|
||||||
{
|
{
|
||||||
|
|
@ -6917,12 +6950,12 @@ Session::initialize_latencies ()
|
||||||
void
|
void
|
||||||
Session::set_worst_io_latencies ()
|
Session::set_worst_io_latencies ()
|
||||||
{
|
{
|
||||||
set_worst_playback_latency ();
|
set_worst_output_latency ();
|
||||||
set_worst_capture_latency ();
|
set_worst_input_latency ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Session::set_worst_playback_latency ()
|
Session::set_worst_output_latency ()
|
||||||
{
|
{
|
||||||
if (_state_of_the_state & (InitialConnecting|Deletion)) {
|
if (_state_of_the_state & (InitialConnecting|Deletion)) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -6946,7 +6979,7 @@ Session::set_worst_playback_latency ()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Session::set_worst_capture_latency ()
|
Session::set_worst_input_latency ()
|
||||||
{
|
{
|
||||||
if (_state_of_the_state & (InitialConnecting|Deletion)) {
|
if (_state_of_the_state & (InitialConnecting|Deletion)) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -6961,10 +6994,6 @@ Session::set_worst_capture_latency ()
|
||||||
boost::shared_ptr<RouteList> r = routes.reader ();
|
boost::shared_ptr<RouteList> r = routes.reader ();
|
||||||
|
|
||||||
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
|
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
|
||||||
boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
|
|
||||||
if (!tr) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
_worst_input_latency = max (_worst_input_latency, (*i)->input()->latency());
|
_worst_input_latency = max (_worst_input_latency, (*i)->input()->latency());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -6974,41 +7003,23 @@ Session::set_worst_capture_latency ()
|
||||||
void
|
void
|
||||||
Session::update_latency_compensation (bool force_whole_graph)
|
Session::update_latency_compensation (bool force_whole_graph)
|
||||||
{
|
{
|
||||||
// TODO: consolidate
|
|
||||||
bool some_track_latency_changed = false;
|
|
||||||
|
|
||||||
if (_state_of_the_state & (InitialConnecting|Deletion)) {
|
if (_state_of_the_state & (InitialConnecting|Deletion)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG_TRACE(DEBUG::Latency, "---------------------------- update latency compensation\n\n");
|
bool some_track_latency_changed = update_route_latency (false, false);
|
||||||
|
|
||||||
_worst_track_latency = 0;
|
|
||||||
|
|
||||||
boost::shared_ptr<RouteList> r = routes.reader ();
|
|
||||||
|
|
||||||
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
|
|
||||||
assert (!(*i)->is_auditioner()); // XXX remove me
|
|
||||||
if ((*i)->active()) {
|
|
||||||
samplecnt_t tl;
|
|
||||||
if ((*i)->signal_latency () != (tl = (*i)->update_signal_latency () /* - (*i)->output()->user_latency()*/)) {
|
|
||||||
some_track_latency_changed = true;
|
|
||||||
}
|
|
||||||
_worst_track_latency = max (tl, _worst_track_latency);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG_TRACE (DEBUG::Latency, string_compose ("worst signal processing latency: %1 (changed ? %2)\n", _worst_track_latency,
|
|
||||||
(some_track_latency_changed ? "yes" : "no")));
|
|
||||||
|
|
||||||
DEBUG_TRACE(DEBUG::Latency, "---------------------------- DONE update latency compensation\n\n");
|
|
||||||
|
|
||||||
if (some_track_latency_changed || force_whole_graph) {
|
if (some_track_latency_changed || force_whole_graph) {
|
||||||
_engine.update_latencies ();
|
_engine.update_latencies ();
|
||||||
}
|
/* above call will ask the backend up update its latencies, which
|
||||||
|
* eventually will trigger AudioEngine::latency_callback () and
|
||||||
|
* call Session::update_latency ()
|
||||||
|
*/
|
||||||
|
} else {
|
||||||
|
boost::shared_ptr<RouteList> r = routes.reader ();
|
||||||
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
|
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
|
||||||
(*i)->update_signal_latency (true);
|
(*i)->apply_latency_compensation ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue