Fix playback alignment when adding/removing channels

The disk-reader assumes that all playback ringbuffers are in sync
and have the same fill_level.
This commit is contained in:
Robin Gareus
2020-04-14 03:57:26 +02:00
parent d5f25f998b
commit ea2bda6668
7 changed files with 48 additions and 3 deletions

View File

@@ -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;

View File

@@ -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 ();
};

View File

@@ -145,6 +145,8 @@ protected:
int do_flush (RunContext context, bool force = false);
void configuration_changed ();
private:
static samplecnt_t _chunk_samples;

View File

@@ -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);

View File

@@ -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 ();

View File

@@ -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;

View File

@@ -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;