Collect and postpone send delayline updates

In order to detect if route delaylines need to be updated,
aux-send delaylines need to be updated first. This was previously
done directly in the latency-callback, which may be concurrent
with processing.

Now only the information (pending_delay) is set, and the actual
change happens later at the end of process().
This commit is contained in:
Robin Gareus 2022-02-07 04:30:48 +01:00
parent 31b7e18d7d
commit 2328df23e5
Signed by: rgareus
GPG Key ID: A090BCE02CF57F04
7 changed files with 54 additions and 9 deletions

View File

@ -199,6 +199,8 @@ public:
void emit_pending_signals ();
MeterPoint meter_point() const { return _pending_meter_point; }
void update_send_delaylines ();
void set_meter_type (MeterType t);
MeterType meter_type () const;

View File

@ -54,8 +54,10 @@ public:
* (via Route::update_signal_latency)
*/
virtual void set_delay_out (samplecnt_t, size_t bus = 0) = 0;
virtual void update_delaylines (bool rt_ok) = 0;
static PBD::Signal0<void> ChangedLatency;
static PBD::Signal0<void> QueueUpdate;
protected:
samplecnt_t _delay_in;
@ -105,6 +107,8 @@ public:
void activate ();
void deactivate ();
void update_delaylines (bool rt_ok);
bool set_name (const std::string& str);
static std::string name_and_id_new_send (Session&, Delivery::Role r, uint32_t&, bool);
@ -127,8 +131,6 @@ private:
void pannable_changed ();
void snd_output_changed (IOChange, void*);
void update_delaylines ();
int set_state_2X (XMLNode const &, int);
bool _remove_on_disconnect;

View File

@ -1428,6 +1428,7 @@ private:
samplecnt_t _worst_route_latency;
samplecnt_t _io_latency;
uint32_t _send_latency_changes;
bool _update_send_delaylines;
bool _have_captured;
samplecnt_t _capture_duration;
unsigned int _capture_xruns;
@ -1457,6 +1458,7 @@ private:
void set_worst_input_latency ();
void send_latency_compensation_change ();
void update_send_delaylines ();
void ensure_buffers (ChanCount howmany = ChanCount::ZERO);

View File

@ -4034,6 +4034,17 @@ Route::silent_roll (pframes_t nframes, samplepos_t /*start_sample*/, samplepos_t
return 0;
}
void
Route::update_send_delaylines ()
{
Glib::Threads::RWLock::ReaderLock lm (_processor_lock);
for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
if (boost::shared_ptr<LatentSend> snd = boost::dynamic_pointer_cast<LatentSend> (*i)) {
snd->update_delaylines (true);
}
}
}
#ifdef __clang__
__attribute__((annotate("realtime")))
#endif

View File

@ -26,6 +26,7 @@
#include "pbd/xml++.h"
#include "ardour/amp.h"
#include "ardour/audioengine.h"
#include "ardour/boost_debug.h"
#include "ardour/buffer_set.h"
#include "ardour/debug.h"
@ -51,6 +52,7 @@ using namespace PBD;
using namespace std;
PBD::Signal0<void> LatentSend::ChangedLatency;
PBD::Signal0<void> LatentSend::QueueUpdate;
LatentSend::LatentSend ()
: _delay_in (0)
@ -152,7 +154,7 @@ Send::signal_latency () const
}
void
Send::update_delaylines ()
Send::update_delaylines (bool rt_ok)
{
if (_role == Listen) {
/* Don't align monitor-listen (just yet).
@ -166,6 +168,19 @@ Send::update_delaylines ()
return;
}
if (!rt_ok && AudioEngine::instance()->running() && AudioEngine::instance()->in_process_thread ()) {
if (_delay_out > _delay_in) {
if (_send_delay->delay () != 0 || _thru_delay->delay () != _delay_out - _delay_in) {
QueueUpdate (); /* EMIT SIGNAL */
}
}else {
if (_thru_delay->delay () != 0 || _send_delay->delay () != _delay_in - _delay_out) {
QueueUpdate (); /* EMIT SIGNAL */
}
}
return;
}
bool changed;
if (_delay_out > _delay_in) {
changed = _thru_delay->set_delay(_delay_out - _delay_in);
@ -175,10 +190,7 @@ Send::update_delaylines ()
_send_delay->set_delay(_delay_in - _delay_out);
}
if (changed) {
// TODO -- ideally postpone for effective no-op changes
// (in case both _delay_out and _delay_in are changed by the
// same amount in a single latency-update cycle).
if (changed && !AudioEngine::instance()->in_process_thread ()) {
ChangedLatency (); /* EMIT SIGNAL */
}
}
@ -195,7 +207,7 @@ Send::set_delay_in (samplecnt_t delay)
string_compose ("Send::set_delay_in %1: (%2) - %3 = %4\n",
name (), _delay_in, _delay_out, _delay_in - _delay_out));
update_delaylines ();
update_delaylines (false);
}
void
@ -209,7 +221,7 @@ Send::set_delay_out (samplecnt_t delay, size_t /*bus*/)
string_compose ("Send::set_delay_out %1: %2 - (%3) = %4\n",
name (), _delay_in, _delay_out, _delay_in - _delay_out));
update_delaylines ();
update_delaylines (true);
}
void

View File

@ -204,6 +204,7 @@ Session::Session (AudioEngine &eng,
, _worst_route_latency (0)
, _io_latency (0)
, _send_latency_changes (0)
, _update_send_delaylines (false)
, _have_captured (false)
, _capture_duration (0)
, _capture_xruns (0)
@ -484,6 +485,7 @@ Session::Session (AudioEngine &eng,
EndTimeChanged.connect_same_thread (*this, boost::bind (&Session::end_time_changed, this, _1));
LatentSend::ChangedLatency.connect_same_thread (*this, boost::bind (&Session::send_latency_compensation_change, this));
LatentSend::QueueUpdate.connect_same_thread (*this, boost::bind (&Session::update_send_delaylines, this));
Latent::DisableSwitchChanged.connect_same_thread (*this, boost::bind (&Session::queue_latency_recompute, this));
Controllable::ControlTouched.connect_same_thread (*this, boost::bind (&Session::controllable_touched, this, _1));
@ -6665,6 +6667,13 @@ Session::send_latency_compensation_change ()
++_send_latency_changes;
}
void
Session::update_send_delaylines ()
{
/* called in rt-thread, if send latency changed */
_update_send_delaylines = true;
}
bool
Session::update_route_latency (bool playback, bool apply_to_delayline, bool* delayline_update_needed)
{

View File

@ -130,6 +130,13 @@ Session::process (pframes_t nframes)
}
}
if (_update_send_delaylines) {
boost::shared_ptr<RouteList> r = routes.reader ();
for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
(*i)->update_send_delaylines ();
}
}
if (_rt_emit_pending) {
if (!_rt_thread_active) {
emit_route_signals ();