13
0

Fix underruns when looping/locating and changing region content

Previously loop-wrap around asked the butler to perform
a unnecessary seek operation next time it is summoned.

If the butler is then summoned for a PostTransportOverWrite
event, the seek causes a DR::Underrun.
This commit is contained in:
Robin Gareus 2024-09-25 20:03:48 +02:00
parent 5af023c70b
commit 18e0cba1cb
Signed by: rgareus
GPG Key ID: A090BCE02CF57F04
2 changed files with 14 additions and 6 deletions

View File

@ -560,6 +560,7 @@ DiskReader::pending_overwrite () const
void
DiskReader::set_pending_overwrite (OverwriteReason why)
{
DEBUG_TRACE (DEBUG::DiskIO, string_compose ("%1 set_pending_overwrite because %3%4%5\n", owner ()->name (), std::hex, why, std::dec));
std::shared_ptr<ChannelList const> c = channels.reader ();
/* called from audio thread, so we can use the read ptr and playback sample as we wish */
@ -862,9 +863,10 @@ DiskReader::seek (samplepos_t sample, bool complete_refill)
}
}
_pending_overwrite.store (OverwriteReason (0));
DEBUG_TRACE (DEBUG::DiskIO, string_compose ("DiskReader::seek %1 %2 -> %3 refill=%4 pending_overwrite = %5\n",
owner ()->name (), playback_sample, sample, complete_refill, _pending_overwrite.load ()));
DEBUG_TRACE (DEBUG::DiskIO, string_compose ("DiskReader::seek %1 %2 -> %3 refill=%4\n", owner ()->name ().c_str (), playback_sample, sample, complete_refill));
_pending_overwrite.store (OverwriteReason (0));
const samplecnt_t distance = sample - playback_sample;
if (!complete_refill && can_internal_playback_seek (distance)) {

View File

@ -202,9 +202,12 @@ Session::locate (samplepos_t target_sample, bool for_loop_end, bool force, bool
// Update Timecode time
_transport_sample = target_sample;
_nominal_jack_transport_sample = boost::none;
// Bump seek counter so that any in-process locate in the butler
// thread(s?) can restart.
_seek_counter.fetch_add (1);
/* Note that loop wrap-around locates do not need to call "seek" */
if (force || !for_loop_end) {
/* Bump seek counter so that any in-process locate in the butler can restart */
_seek_counter.fetch_add (1);
}
_last_roll_or_reversal_location = target_sample;
if (!for_loop_end && !_exporting) {
_remaining_latency_preroll = worst_latency_preroll_buffer_size_ceil ();
@ -1206,7 +1209,10 @@ Session::butler_transport_work (bool have_process_lock)
non_realtime_locate ();
}
if (ptw & PostTransportOverWrite) {
/* if we just performed a locate, buffers have been refilled.
* This effectively has done the work of "PostTransportOverWrite" already.
*/
else if (ptw & PostTransportOverWrite) {
non_realtime_overwrite (on_entry, finished, (ptw & PostTransportLoopChanged));
if (!finished) {
(void) PBD::atomic_dec_and_test (_butler->should_do_transport_work);