summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authorRobin Gareus <robin@gareus.org>2020-04-14 03:57:26 +0200
committerRobin Gareus <robin@gareus.org>2020-04-14 03:57:26 +0200
commitea2bda666813ed7b8963ee2884f7a496b8284b08 (patch)
treeb6bddc9e65df364163f86e7390c981dc6c6c1d8e /libs
parentd5f25f998bb5a5cb8aefbba8679e63ffa0062d55 (diff)
Fix playback alignment when adding/removing channels
The disk-reader assumes that all playback ringbuffers are in sync and have the same fill_level.
Diffstat (limited to 'libs')
-rw-r--r--libs/ardour/ardour/disk_io.h1
-rw-r--r--libs/ardour/ardour/disk_reader.h2
-rw-r--r--libs/ardour/ardour/disk_writer.h2
-rw-r--r--libs/ardour/disk_io.cc2
-rw-r--r--libs/ardour/disk_reader.cc24
-rw-r--r--libs/ardour/disk_writer.cc8
-rw-r--r--libs/pbd/pbd/playback_buffer.h12
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<ReaderChannelInfo*> (*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;