From d13f02e65a3d321c7596deec737a51498c1e37f5 Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Sun, 30 Nov 2025 16:55:49 +0100 Subject: [PATCH] Fix artifacts with concurrent region read / shared playlists --- libs/ardour/ardour/audioregion.h | 1 + libs/ardour/audioregion.cc | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/libs/ardour/ardour/audioregion.h b/libs/ardour/ardour/audioregion.h index bb078ef2f7..c5e41276c1 100644 --- a/libs/ardour/ardour/audioregion.h +++ b/libs/ardour/ardour/audioregion.h @@ -274,6 +274,7 @@ class LIBARDOUR_API AudioRegion : public Region, public AudioReadable pframes_t _fx_block_size; mutable bool _fx_latent_read; + mutable Glib::Threads::Mutex _read_lock; mutable Glib::Threads::Mutex _cache_lock; mutable BufferSet _readcache; mutable samplepos_t _cache_start; diff --git a/libs/ardour/audioregion.cc b/libs/ardour/audioregion.cc index e5846b4cca..8817011125 100644 --- a/libs/ardour/audioregion.cc +++ b/libs/ardour/audioregion.cc @@ -725,6 +725,25 @@ AudioRegion::read_at (Sample* buf, } } + /* Prevent concurrent reads for the same region + * which can happen with shared playlists, or + * after unfreeze of a copied playlist. + * + * Concurrent calls will cause issues when + * * evaluating gain/fade curves (ControlList lookup_cache) + * * evaulating regionFX + * + * This lock is not usually contended, since usually + * regions are unique. + * + * Note that AudioSource::read is also exclusive + * since libsndfile is not thread-safe either. + * So a more fine-grained lock strategy below + * (envelope/fades/regionFX) will not make a + * significant difference. + */ + Glib::Threads::Mutex::Lock crl (_read_lock); + Glib::Threads::Mutex::Lock cl (_cache_lock); if (chan_n == 0 && _invalidated.exchange (false)) { _cache_start = _cache_end = -1; @@ -1039,6 +1058,8 @@ endread: } } + crl.release (); + /* MIX OR COPY THE REGION BODY FROM mixdown_buffer INTO buf */ samplecnt_t const N = to_read - fade_in_limit - fade_out_limit;