From 7b3cbaf68f9b171352c32f87b1d525438c75eca1 Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Mon, 26 Dec 2022 13:29:39 +0100 Subject: [PATCH] Inform User when audio-read failed (debug builds) Previously AudioPlaylist::read always returned the timecnt that it was supposed to read into the buffer, regardless if the given number of samples was read. The check in DiskReader::refill_audio `if (nread != to_read)` never triggered. This can happen when changing an audio-region's time-domain to music-time (glue to bars/beats). Region-length (beats converted to samples) can exceed the actual audio-source length (in samples). --- libs/ardour/audio_playlist.cc | 21 +++++++++++++++++++-- libs/ardour/audioregion.cc | 3 +++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/libs/ardour/audio_playlist.cc b/libs/ardour/audio_playlist.cc index cbc334cc32..aa67bca868 100644 --- a/libs/ardour/audio_playlist.cc +++ b/libs/ardour/audio_playlist.cc @@ -178,6 +178,8 @@ AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, ti DEBUG_TRACE (DEBUG::AudioPlayback, string_compose ("Playlist %1 read @ %2 for %3, channel %4, regions %5 mixdown @ %6 gain @ %7\n", name(), start, cnt, chan_n, regions.size(), mixdown_buffer, gain_buffer)); + samplecnt_t const scnt (cnt.samples ()); + /* optimizing this memset() away involves a lot of conditionals that may well cause more of a hit due to cache misses and related stuff than just doing this here. @@ -191,7 +193,7 @@ AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, ti zeroed. */ - memset (buf, 0, sizeof (Sample) * cnt.samples()); + memset (buf, 0, sizeof (Sample) * scnt); /* this function is never called from a realtime thread, so its OK to block (for short intervals). @@ -271,7 +273,22 @@ AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, ti i->range.length(), (int) chan_n, buf, i->range.start().earlier (start))); - i->region->read_at (buf + start.distance (i->range.start()).samples(), mixdown_buffer, gain_buffer, i->range.start().samples(), i->range.start().distance (i->range.end()).samples(), chan_n); + samplepos_t read_pos (i->range.start().samples()); + samplecnt_t read_cnt (i->range.start().distance (i->range.end()).samples()); + assert (start.distance (i->range.start()).samples() < scnt); + assert (start.distance (i->range.start()).samples() + read_cnt <= scnt); + samplecnt_t nread = i->region->read_at (buf + start.distance (i->range.start()).samples(), mixdown_buffer, gain_buffer, read_pos, read_cnt, chan_n); + if (nread != read_cnt) { +#ifndef NDEBUG + /* forward error to DiskReader::audio_read. This does 2 things: + * - error "DiskReader %1: when refilling, cannot read ..." + * - emit Underrun() - "Disk is too slow" + * (ideally only the first would happen) + * Since the buffer is zero'ed above, failed reads are not an issue. + */ + return timecnt_t (0); +#endif + } } return cnt; diff --git a/libs/ardour/audioregion.cc b/libs/ardour/audioregion.cc index 0db62eac45..b9b33c93de 100644 --- a/libs/ardour/audioregion.cc +++ b/libs/ardour/audioregion.cc @@ -1444,6 +1444,9 @@ AudioRegion::maximum_amplitude (Progress* p) const /* read it in */ if (read_raw_internal (buf, fpos, to_read, n) != to_read) { +#ifndef NDEBUG + cerr << "AudioRegion::maximum_amplitude read failed for '" << _name << "'\n"; +#endif return 0; }