From ea2bda666813ed7b8963ee2884f7a496b8284b08 Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Tue, 14 Apr 2020 03:57:26 +0200 Subject: [PATCH] Fix playback alignment when adding/removing channels The disk-reader assumes that all playback ringbuffers are in sync and have the same fill_level. --- libs/ardour/ardour/disk_io.h | 1 + libs/ardour/ardour/disk_reader.h | 2 ++ libs/ardour/ardour/disk_writer.h | 2 ++ libs/ardour/disk_io.cc | 2 +- libs/ardour/disk_reader.cc | 24 ++++++++++++++++++++++++ libs/ardour/disk_writer.cc | 8 +++++++- libs/pbd/pbd/playback_buffer.h | 12 +++++++++++- 7 files changed, 48 insertions(+), 3 deletions(-) diff --git a/libs/ardour/ardour/disk_io.h b/libs/ardour/ardour/disk_io.h index 83e5dd3f9b..39c8b16ec4 100644 --- a/libs/ardour/ardour/disk_io.h +++ b/libs/ardour/ardour/disk_io.h @@ -113,6 +113,7 @@ public: protected: friend class Auditioner; virtual int seek (samplepos_t which_sample, bool complete_refill = false) = 0; + virtual void configuration_changed () = 0; protected: Flag _flags; diff --git a/libs/ardour/ardour/disk_reader.h b/libs/ardour/ardour/disk_reader.h index 2e1ab6aec6..9db4266daa 100644 --- a/libs/ardour/ardour/disk_reader.h +++ b/libs/ardour/ardour/disk_reader.h @@ -223,6 +223,8 @@ private: void get_midi_playback (MidiBuffer& dst, samplepos_t start_sample, samplepos_t end_sample, MonitorState, BufferSet&, double speed, samplecnt_t distance); void maybe_xfade_loop (Sample*, samplepos_t read_start, samplepos_t read_end, ReaderChannelInfo*); + void configuration_changed (); + bool overwrite_existing_audio (); bool overwrite_existing_midi (); }; diff --git a/libs/ardour/ardour/disk_writer.h b/libs/ardour/ardour/disk_writer.h index 31a64cd0e8..2bd753a006 100644 --- a/libs/ardour/ardour/disk_writer.h +++ b/libs/ardour/ardour/disk_writer.h @@ -145,6 +145,8 @@ protected: int do_flush (RunContext context, bool force = false); + void configuration_changed (); + private: static samplecnt_t _chunk_samples; diff --git a/libs/ardour/disk_io.cc b/libs/ardour/disk_io.cc index 49e0ef1297..b6badf8c0d 100644 --- a/libs/ardour/disk_io.cc +++ b/libs/ardour/disk_io.cc @@ -193,7 +193,7 @@ DiskIOProcessor::configure_io (ChanCount in, ChanCount out) } if (changed) { - seek (_session.transport_sample()); + configuration_changed (); } return Processor::configure_io (in, out); diff --git a/libs/ardour/disk_reader.cc b/libs/ardour/disk_reader.cc index 666f8a1e6a..4e687c7962 100644 --- a/libs/ardour/disk_reader.cc +++ b/libs/ardour/disk_reader.cc @@ -507,6 +507,12 @@ DiskReader::declick_in_progress () const return (_declick_amp.gain () != 0); // declick-out } +void +DiskReader::configuration_changed () +{ + _session.request_overwrite_buffer (_track, LoopDisabled); +} + bool DiskReader::pending_overwrite () const { @@ -521,6 +527,24 @@ DiskReader::set_pending_overwrite (OverwriteReason why) /* called from audio thread, so we can use the read ptr and playback sample as we wish */ if (!c->empty ()) { + + if (c->size () > 1) { + /* Align newly added buffers. + * + * overwrite_sample and file_sample[] are are maintained + * per DiskReader, not per channel. + * ::refill_audio() and ::overwrite_existing_audio() expect + * that read-pointers and fill_level of all buffers are in sync. + */ + ChannelList::iterator chan = c->begin (); + for (++chan; chan != c->end (); ++chan) { + ReaderChannelInfo* chaninfo = dynamic_cast (*chan); + if (!chaninfo->initialized) { + (*chan)->rbuf->align_to (*(c->front ()->rbuf)); + } + } + } + const samplecnt_t reserved_size = c->front ()->rbuf->reserved_size (); const samplecnt_t bufsize = c->front ()->rbuf->bufsize (); diff --git a/libs/ardour/disk_writer.cc b/libs/ardour/disk_writer.cc index d61d0f23f7..51588b844a 100644 --- a/libs/ardour/disk_writer.cc +++ b/libs/ardour/disk_writer.cc @@ -798,8 +798,14 @@ DiskWriter::set_note_mode (NoteMode m) _midi_write_source->model()->set_note_mode(m); } +void +DiskWriter::configuration_changed () +{ + seek (_session.transport_sample(), false); +} + int -DiskWriter::seek (samplepos_t sample, bool complete_refill) +DiskWriter::seek (samplepos_t sample, bool /*complete_refill*/) { uint32_t n; ChannelList::iterator chan; diff --git a/libs/pbd/pbd/playback_buffer.h b/libs/pbd/pbd/playback_buffer.h index 4b0b900217..75a30bc86f 100644 --- a/libs/pbd/pbd/playback_buffer.h +++ b/libs/pbd/pbd/playback_buffer.h @@ -65,10 +65,20 @@ public: /* writer, when seeking, may block */ Glib::Threads::Mutex::Lock lm (_reset_lock); SpinLock sl (_reservation_lock); - g_atomic_int_set (&write_idx, g_atomic_int_get (&read_idx)); + g_atomic_int_set (&read_idx, 0); + g_atomic_int_set (&write_idx, 0); g_atomic_int_set (&reserved, 0); } + /* called from rt (reader) thread for new buffers */ + void align_to (PlaybackBuffer const& other) { + Glib::Threads::Mutex::Lock lm (_reset_lock); + write_idx = other.write_idx; + read_idx = other.read_idx; + reserved = other.reserved; + memset (buf, 0, size * sizeof (T)); + } + /* write-thread */ guint write_space () const { guint w, r;