From dc4247f9bb587a575c440586d555ce0a0cffb02b Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Thu, 3 Feb 2022 03:27:57 +0100 Subject: [PATCH] Consolidate processing prohibited / silent runs This uses the Process-lock when processing is not prohibited, removing the special-case when bouncing audio to a more general case. One downside is that while bouncing, timecode masters no longer run and may loose sync-lock. However transport does not move while Session::write_one_track() runs, and a resume will need to seek/varispeed to catch up anyway. --- libs/ardour/ardour/session.h | 5 ----- libs/ardour/audioengine.cc | 25 ++++++++++++++++--------- libs/ardour/session.cc | 25 ++++++------------------- libs/ardour/session_process.cc | 7 +------ libs/ardour/session_state.cc | 1 - 5 files changed, 23 insertions(+), 40 deletions(-) diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 035ae7f327..601f0ae90e 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -1443,7 +1443,6 @@ private: std::string _missing_file_replacement; - mutable GATOMIC_QUAL gint _processing_prohibited; mutable GATOMIC_QUAL gint _record_status; void add_monitor_section (); @@ -1469,10 +1468,6 @@ private: samplecnt_t calc_preroll_subcycle (samplecnt_t) const; - void block_processing(); - void unblock_processing() { g_atomic_int_set (&_processing_prohibited, 0); } - bool processing_blocked() const { return g_atomic_int_get (&_processing_prohibited); } - static const samplecnt_t bounce_chunk_size; /* Transport master DLL */ diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc index 3762dcb326..917cb9aaea 100644 --- a/libs/ardour/audioengine.cc +++ b/libs/ardour/audioengine.cc @@ -257,7 +257,7 @@ AudioEngine::process_callback (pframes_t nframes) if (!tm.locked()) { /* return having done nothing */ - if (_session) { + if (_session && !_session->bounce_processing ()) { Xrun(); } /* really only JACK requires this @@ -298,7 +298,7 @@ AudioEngine::process_callback (pframes_t nframes) * * Note: this must be done without holding the _process_lock */ - if (_session && !_session->processing_blocked ()) { + if (_session) { bool lp = false; bool lc = false; if (g_atomic_int_compare_and_exchange (&_pending_playback_latency_callback, 1, 0)) { @@ -308,13 +308,11 @@ AudioEngine::process_callback (pframes_t nframes) lc = true; } if (lp || lc) { - /* synchronize with Session::processing_blocked - * This lock is not contended by this thread, but acts - * as barrier for Session::block_processing (Session::write_one_track). + /* The process-lock needs to be released before calling Session::update_latency, + * However latency callbacks may not happen concurrently. */ Glib::Threads::Mutex::Lock ll (_latency_lock, Glib::Threads::TRY_LOCK); - /* re-check after talking latency-lock */ - if (!ll.locked () || _session->processing_blocked ()) { + if (!ll.locked ()) { if (lc) { queue_latency_update (false); } @@ -332,7 +330,16 @@ AudioEngine::process_callback (pframes_t nframes) } /* release latency lock, **before** reacquiring process-lock */ ll.release (); - tm.acquire (); + tm.try_acquire (); + + if (!tm.locked()) { + if (!_session->bounce_processing ()) { + Xrun(); + } + + PortManager::silence_outputs (nframes); + return 0; + } } } } @@ -1493,7 +1500,7 @@ AudioEngine::latency_callback (bool for_playback) * All is fine. */ Glib::Threads::Mutex::Lock ll (_latency_lock, Glib::Threads::TRY_LOCK); - if (!ll.locked () || _session->processing_blocked ()) { + if (!ll.locked ()) { /* Except Session::write_one_track() might just have called block_processing() */ queue_latency_update (for_playback); } else { diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index 3603b7c8c0..b8df31cda3 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -327,7 +327,6 @@ Session::Session (AudioEngine &eng, g_atomic_int_set (&_playback_load, 0); g_atomic_int_set (&_capture_load, 0); g_atomic_int_set (&_post_transport_work, 0); - g_atomic_int_set (&_processing_prohibited, Disabled); g_atomic_int_set (&_record_status, Disabled); g_atomic_int_set (&_punch_or_loop, NoConstraint); g_atomic_int_set (&_current_usecs_per_track, 1000); @@ -847,20 +846,6 @@ Session::destroy () } -void -Session::block_processing() -{ - g_atomic_int_set (&_processing_prohibited, 1); - - /* processing_blocked() is only checked at the beginning - * of the next cycle. So wait until any ongoing - * process-callback returns. - */ - Glib::Threads::Mutex::Lock lm (_engine.process_lock()); - /* latency callback may be in process, wait until it completed */ - Glib::Threads::Mutex::Lock lx (_engine.latency_lock()); -} - void Session::setup_ltc () { @@ -5770,10 +5755,14 @@ Session::write_one_track (Track& track, samplepos_t start, samplepos_t end, /* block all process callback handling, so that thread-buffers * are available here. */ - block_processing (); - + Glib::Threads::Mutex::Lock lm (_engine.process_lock()); _bounce_processing_active = true; + /* prevent concurrent latency callbacks, they must not be called + * concurrently with ::run () + */ + Glib::Threads::Mutex::Lock lx (_engine.latency_lock()); + /* call tree *MUST* hold route_lock */ if ((playlist = track.playlist()) == 0) { @@ -6054,8 +6043,6 @@ Session::write_one_track (Track& track, samplepos_t start, samplepos_t end, track.set_block_size (get_block_size()); } - unblock_processing (); - return result; } diff --git a/libs/ardour/session_process.cc b/libs/ardour/session_process.cc index a48ebd6aa4..ba4722f60a 100644 --- a/libs/ardour/session_process.cc +++ b/libs/ardour/session_process.cc @@ -85,12 +85,7 @@ Session::process (pframes_t nframes) { TimerRAII tr (dsp_stats[OverallProcess]); - if (processing_blocked()) { - _silent = true; - return; - } else { - _silent = false; - } + _silent = false; samplepos_t transport_at_start = _transport_sample; diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index af4a9a1e04..9769ca9be0 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -178,7 +178,6 @@ Session::pre_engine_init (string fullpath) */ timerclear (&last_mmc_step); - g_atomic_int_set (&_processing_prohibited, 0); g_atomic_int_set (&_record_status, Disabled); g_atomic_int_set (&_playback_load, 100); g_atomic_int_set (&_capture_load, 100);