From c3e3930f149667666a2e5b851d02a4bed1cfb9d9 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Tue, 10 Dec 2019 09:28:41 -0700 Subject: [PATCH] revert to single buffer for disk playback, and 5.x-style overwrite Also address issues with MIDI and also atomicity of _pending_overwrite --- libs/ardour/ardour/disk_io.h | 6 +- libs/ardour/ardour/disk_reader.h | 26 ++- libs/ardour/ardour/session.h | 4 +- libs/ardour/ardour/session_event.h | 1 + libs/ardour/ardour/track.h | 2 +- libs/ardour/ardour/types.h | 6 + libs/ardour/disk_io.cc | 11 +- libs/ardour/disk_reader.cc | 285 +++++++++++++++-------------- libs/ardour/session.cc | 2 +- libs/ardour/session_butler.cc | 9 +- libs/ardour/session_process.cc | 2 +- libs/ardour/session_transport.cc | 2 +- libs/ardour/track.cc | 4 +- libs/pbd/pbd/playback_buffer.h | 10 + 14 files changed, 190 insertions(+), 180 deletions(-) diff --git a/libs/ardour/ardour/disk_io.h b/libs/ardour/ardour/disk_io.h index 65486febf4..1ae7cbfa94 100644 --- a/libs/ardour/ardour/disk_io.h +++ b/libs/ardour/ardour/disk_io.h @@ -151,13 +151,11 @@ protected: ChannelInfo (samplecnt_t buffer_size); virtual ~ChannelInfo (); - /** A pair of random-access ringbuffers for data to be played back. + /** A semi-random-access ringbuffers for data to be played back. * written to in the butler thread, read from in the process * thread. - * - * */ - PBD::PlaybackBuffer* rbuf[2]; + PBD::PlaybackBuffer* rbuf; /** A ringbuffer for data to be recorded back, written to in the * process thread, read from in the butler thread. diff --git a/libs/ardour/ardour/disk_reader.h b/libs/ardour/ardour/disk_reader.h index e43192f0ff..dbe639d5c6 100644 --- a/libs/ardour/ardour/disk_reader.h +++ b/libs/ardour/ardour/disk_reader.h @@ -54,7 +54,7 @@ public: void realtime_handle_transport_stopped (); void realtime_locate (bool); bool overwrite_existing_buffers (); - void set_pending_overwrite (); + void set_pending_overwrite (OverwriteReason); void set_loop (Location *); int set_state (const XMLNode&, int version); @@ -118,8 +118,6 @@ public: static void alloc_loop_declick (samplecnt_t sample_rate); Glib::Threads::Mutex rbuf_lock; - void queue_switch_rbuf (); - void switch_rbufs (); protected: friend class Track; @@ -186,10 +184,8 @@ protected: }; private: - bool _switch_rbuf; - int process_rbuf; - int other_rbuf; samplepos_t overwrite_sample; + sampleoffset_t overwrite_offset; samplepos_t new_file_sample; mutable gint _pending_overwrite; bool overwrite_queued; @@ -211,14 +207,13 @@ private: static Declicker loop_declick_out; static samplecnt_t loop_fade_length; - int audio_read (PBD::PlaybackBuffer*, - Sample* sum_buffer, - Sample* mixdown_buffer, - float* gain_buffer, - samplepos_t& start, samplecnt_t cnt, - ReaderChannelInfo* rci, - int channel, - bool reversed); + samplecnt_t audio_read (Sample* sum_buffer, + Sample* mixdown_buffer, + float* gain_buffer, + samplepos_t& start, samplecnt_t cnt, + ReaderChannelInfo* rci, + int channel, + bool reversed); static Sample* _sum_buffer; static Sample* _mixdown_buffer; @@ -234,7 +229,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*); - + bool overwrite_existing_audio (); + bool overwrite_existing_midi (); }; } // namespace diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 6c34a1b93f..5491f49df4 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -456,7 +456,7 @@ public: void allow_auto_play (bool yn); void request_transport_speed (double speed, bool as_default = true, TransportRequestSource origin = TRS_UI); void request_transport_speed_nonzero (double, bool as_default = true, TransportRequestSource origin = TRS_UI); - void request_overwrite_buffer (boost::shared_ptr); + void request_overwrite_buffer (boost::shared_ptr, OverwriteReason); void adjust_playback_buffering(); void adjust_capture_buffering(); @@ -1685,7 +1685,7 @@ private: void set_play_loop (bool yn, bool change_transport_state); void unset_play_loop (bool change_transport_state = false); - void overwrite_some_buffers (boost::shared_ptr); + void overwrite_some_buffers (boost::shared_ptr, OverwriteReason); void flush_all_inserts (); int micro_locate (samplecnt_t distance); diff --git a/libs/ardour/ardour/session_event.h b/libs/ardour/ardour/session_event.h index da6a0505f2..ddf7210617 100644 --- a/libs/ardour/ardour/session_event.h +++ b/libs/ardour/ardour/session_event.h @@ -83,6 +83,7 @@ public: union { bool yes_or_no; samplepos_t target2_sample; + OverwriteReason overwrite; }; boost::shared_ptr track; diff --git a/libs/ardour/ardour/track.h b/libs/ardour/ardour/track.h index 0b6462fbc3..fbac03edf0 100644 --- a/libs/ardour/ardour/track.h +++ b/libs/ardour/ardour/track.h @@ -137,7 +137,7 @@ public: float capture_buffer_load () const; int do_refill (); int do_flush (RunContext, bool force = false); - void set_pending_overwrite (); + void set_pending_overwrite (OverwriteReason); int seek (samplepos_t, bool complete_refill = false); bool can_internal_playback_seek (samplecnt_t); void internal_playback_seek (samplecnt_t); diff --git a/libs/ardour/ardour/types.h b/libs/ardour/ardour/types.h index 7cd3759a88..26da1cf9e1 100644 --- a/libs/ardour/ardour/types.h +++ b/libs/ardour/ardour/types.h @@ -792,6 +792,12 @@ enum LoopFadeChoice { XFadeLoop, }; +enum OverwriteReason { + PlaylistModified, + LoopDisabled, + LoopChanged, +}; + typedef std::vector CaptureInfos; } // namespace ARDOUR diff --git a/libs/ardour/disk_io.cc b/libs/ardour/disk_io.cc index 7d153661b9..a55e2c559b 100644 --- a/libs/ardour/disk_io.cc +++ b/libs/ardour/disk_io.cc @@ -324,22 +324,19 @@ DiskIOProcessor::use_playlist (DataType dt, boost::shared_ptr playlist } DiskIOProcessor::ChannelInfo::ChannelInfo (samplecnt_t bufsize) - : wbuf (0) + : rbuf (0) + , wbuf (0) , capture_transition_buf (0) , curr_capture_cnt (0) { - rbuf[0] = 0; - rbuf[1] = 0; } DiskIOProcessor::ChannelInfo::~ChannelInfo () { - delete rbuf[0]; - delete rbuf[1]; + delete rbuf; delete wbuf; delete capture_transition_buf; - rbuf[0] = 0; - rbuf[1] = 0; + rbuf = 0; wbuf = 0; capture_transition_buf = 0; } diff --git a/libs/ardour/disk_reader.cc b/libs/ardour/disk_reader.cc index 304cf7d461..0672741fa3 100644 --- a/libs/ardour/disk_reader.cc +++ b/libs/ardour/disk_reader.cc @@ -60,9 +60,6 @@ samplecnt_t DiskReader::loop_fade_length (0); DiskReader::DiskReader (Session& s, string const & str, DiskIOProcessor::Flag f) : DiskIOProcessor (s, str, f) - , _switch_rbuf (false) - , process_rbuf (0) - , other_rbuf (1) , overwrite_sample (0) , overwrite_queued (false) , run_must_resolve (false) @@ -84,15 +81,11 @@ DiskReader::ReaderChannelInfo::resize (samplecnt_t bufsize) { /* caller must hold rbuf lock */ - delete rbuf[0]; rbuf[0] = 0; - delete rbuf[1]; rbuf[1] = 0; + delete rbuf; rbuf = 0; - rbuf[0] = new PlaybackBuffer (bufsize); + rbuf = new PlaybackBuffer (bufsize); /* touch memory to lock it */ - memset (rbuf[0]->buffer(), 0, sizeof (Sample) * rbuf[0]->bufsize()); - rbuf[1] = new PlaybackBuffer (bufsize); - /* touch memory to lock it */ - memset (rbuf[1]->buffer(), 0, sizeof (Sample) * rbuf[1]->bufsize()); + memset (rbuf->buffer(), 0, sizeof (Sample) * rbuf->bufsize()); } void @@ -116,8 +109,8 @@ DiskReader::add_channel_to (boost::shared_ptr c, uint32_t how_many) c->push_back (new ReaderChannelInfo (_session.butler()->audio_diskstream_playback_buffer_size(), loop_fade_length)); DEBUG_TRACE (DEBUG::DiskIO, string_compose ("%1: new reader channel, write space = %2 read = %3\n", name(), - c->back()->rbuf[process_rbuf]->write_space(), - c->back()->rbuf[process_rbuf]->read_space())); + c->back()->rbuf->write_space(), + c->back()->rbuf->read_space())); } return 0; @@ -226,7 +219,7 @@ DiskReader::buffer_load () const return 1.0; } - PBD::PlaybackBuffer* b = c->front()->rbuf[process_rbuf]; + PBD::PlaybackBuffer* b = c->front()->rbuf; return (float) ((double) b->read_space() / (double) b->bufsize()); } @@ -239,17 +232,13 @@ DiskReader::adjust_buffering () for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) { (*chan)->resize (_session.butler()->audio_diskstream_playback_buffer_size()); } - - process_rbuf = 0; - other_rbuf = 1; - _switch_rbuf = false; } void DiskReader::playlist_modified () { if (!overwrite_queued) { - _session.request_overwrite_buffer (_track); + _session.request_overwrite_buffer (_track, PlaylistModified); overwrite_queued = true; } } @@ -273,7 +262,7 @@ DiskReader::use_playlist (DataType dt, boost::shared_ptr playlist) */ if (!overwrite_queued && (prior_playlist || _session.loading())) { - _session.request_overwrite_buffer (_track); + _session.request_overwrite_buffer (_track, PlaylistModified); overwrite_queued = true; } @@ -352,8 +341,8 @@ DiskReader::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp if (!still_locating || _no_disk_output) { for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) { - assert ((*chan)->rbuf[process_rbuf]); - (*chan)->rbuf[process_rbuf]->increment_read_ptr (disk_samples_to_consume); + assert ((*chan)->rbuf); + (*chan)->rbuf->increment_read_ptr (disk_samples_to_consume); } } @@ -380,20 +369,6 @@ DiskReader::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp const float initial_declick_gain = _declick_amp.gain (); const sampleoffset_t declick_offs = _declick_offs; - Glib::Threads::Mutex::Lock lm (rbuf_lock, Glib::Threads::TRY_LOCK); - samplecnt_t skip_for_switch = 0; - - if (lm.locked()) { - if (_switch_rbuf) { - cerr << name() << " switching buffers\n"; - switch_rbufs (); - if (playback_sample > overwrite_sample) { - skip_for_switch = playback_sample - overwrite_sample; - cerr << name() << " will skip " << skip_for_switch << " to align new buffer @ " << overwrite_sample << " to " << playback_sample << endl; - } - } - } - for (n = 0, chan = c->begin(); chan != c->end(); ++chan, ++n) { ChannelInfo* chaninfo (*chan); @@ -402,6 +377,7 @@ DiskReader::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp AudioBuffer& disk_buf ((ms & MonitoringInput) ? scratch_bufs.get_audio(n) : output); if (start_sample != playback_sample && target_gain != 0) { + cerr << name() << " Not at start (" << start_sample << ") ps = " << playback_sample << " iseek (" << start_sample - playback_sample << endl; if (can_internal_playback_seek (start_sample - playback_sample)) { internal_playback_seek (start_sample - playback_sample); } else { @@ -415,13 +391,9 @@ DiskReader::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp } - if (skip_for_switch) { - chaninfo->rbuf[process_rbuf]->increment_read_ptr (skip_for_switch); - } - if (!declick_out) { - const samplecnt_t total = chaninfo->rbuf[process_rbuf]->read (disk_buf.data(), disk_samples_to_consume); + const samplecnt_t total = chaninfo->rbuf->read (disk_buf.data(), disk_samples_to_consume); if (disk_samples_to_consume > total) { cerr << _name << " Need " << total << " have only " << disk_samples_to_consume << endl; @@ -445,7 +417,7 @@ DiskReader::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp to ::run() */ - const samplecnt_t total = chaninfo->rbuf[process_rbuf]->read (disk_buf.data(), nframes, false, declick_offs); + const samplecnt_t total = chaninfo->rbuf->read (disk_buf.data(), nframes, false, declick_offs); if (n == 0) { _declick_offs += total; @@ -470,6 +442,8 @@ DiskReader::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp midi: /* MIDI data handling */ + const bool midi_data_available = !(pending_overwrite() & PlaylistModified); + if (bufs.count().n_midi()) { MidiBuffer& dst (bufs.get_midi (0)); @@ -486,7 +460,7 @@ DiskReader::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp /* decide if we need the butler */ - if (!still_locating) { + if (!still_locating && midi_data_available) { bool butler_required = false; @@ -505,13 +479,13 @@ DiskReader::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp if (_playlists[DataType::AUDIO]) { if (!c->empty()) { if (_slaved) { - if (c->front()->rbuf[process_rbuf]->write_space() >= c->front()->rbuf[process_rbuf]->bufsize() / 2) { - DEBUG_TRACE (DEBUG::Butler, string_compose ("%1: slaved, write space = %2 of %3\n", name(), c->front()->rbuf[process_rbuf]->write_space(), c->front()->rbuf[process_rbuf]->bufsize())); + if (c->front()->rbuf->write_space() >= c->front()->rbuf->bufsize() / 2) { + DEBUG_TRACE (DEBUG::Butler, string_compose ("%1: slaved, write space = %2 of %3\n", name(), c->front()->rbuf->write_space(), c->front()->rbuf->bufsize())); butler_required = true; } } else { - if ((samplecnt_t) c->front()->rbuf[process_rbuf]->write_space() >= _chunk_samples) { - DEBUG_TRACE (DEBUG::Butler, string_compose ("%1: write space = %2 of %3\n", name(), c->front()->rbuf[process_rbuf]->write_space(), + if ((samplecnt_t) c->front()->rbuf->write_space() >= _chunk_samples) { + DEBUG_TRACE (DEBUG::Butler, string_compose ("%1: write space = %2 of %3\n", name(), c->front()->rbuf->write_space(), _chunk_samples)); butler_required = true; } @@ -536,73 +510,96 @@ DiskReader::declick_in_progress () const } bool -DiskReader::pending_overwrite () const { +DiskReader::pending_overwrite () const +{ return g_atomic_int_get (&_pending_overwrite) != 0; } void -DiskReader::set_pending_overwrite () +DiskReader::set_pending_overwrite (OverwriteReason why) { /* called from audio thread, so we can use the read ptr and playback sample as we wish */ overwrite_sample = playback_sample; - g_atomic_int_set (&_pending_overwrite, 1); + boost::shared_ptr c = channels.reader (); + if (!c->empty ()) { + overwrite_offset = c->front()->rbuf->read_ptr(); + } + + while (true) { + OverwriteReason current = OverwriteReason (g_atomic_int_get (&_pending_overwrite)); + OverwriteReason next = OverwriteReason (current | why); + if (g_atomic_int_compare_and_exchange (&_pending_overwrite, current, next)) { + break; + } + } + run_must_resolve = true; } bool -DiskReader::overwrite_existing_buffers () +DiskReader::overwrite_existing_audio () { - /* called from butler thread */ - - Glib::Threads::Mutex::Lock lm (rbuf_lock); + boost::shared_ptr c = channels.reader(); - DEBUG_TRACE (DEBUG::DiskIO, string_compose ("%1 overwriting existing buffers at %2\n", name(), overwrite_sample)); - cerr << string_compose ("%1 overwriting existing buffers at %2\n", name(), overwrite_sample) << endl; + if (c->empty ()) { + return true; + } - boost::shared_ptr c = channels.reader(); + const bool reversed = _session.transport_speed() < 0.0f; - if (!c->empty ()) { + /* assume all are the same size */ - /* AUDIO */ + samplecnt_t size = c->front()->rbuf->bufsize () - c->front()->rbuf->reserved_size() - 1; + assert (size > 0); - const bool reversed = _session.transport_speed() < 0.0f; + boost::scoped_array mixdown_buffer (new Sample[size]); + boost::scoped_array gain_buffer (new float[size]); + uint32_t n = 0; + bool ret = true; - /* assume all are the same size */ + for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan, ++n) { - samplecnt_t size = c->front()->rbuf[process_rbuf]->bufsize (); - assert (size > 0); + samplepos_t start = overwrite_sample; - boost::scoped_array sum_buffer (new Sample[size]); - boost::scoped_array mixdown_buffer (new Sample[size]); - boost::scoped_array gain_buffer (new float[size]); + /* to fill the buffer without resetting the playback sample, we need to + do it one or two chunks (normally two). - samplecnt_t to_read = c->front()->rbuf[other_rbuf]->write_space(); - uint32_t n = 0; + |----------------------------------------------------------------------| + ^ ^ + RESERVED overwrite_offset (old read_ptr) + |<- second chunk->|<-------------><---- first chunk ------------------>| - for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan, ++n) { + */ - samplepos_t start = overwrite_sample; + samplecnt_t to_read = size - overwrite_offset; + Sample* buf = (*chan)->rbuf->buffer(); + ReaderChannelInfo* rci = dynamic_cast (*chan); + samplecnt_t nread; - ReaderChannelInfo* rci = dynamic_cast (*chan); + if ((nread = audio_read (buf + overwrite_offset, mixdown_buffer.get(), gain_buffer.get(), start, to_read, rci, n, reversed)) != to_read) { + error << string_compose(_("DiskReader %1: when overwriting(1), cannot read %2 from playlist at sample %3"), id(), to_read, overwrite_sample) << endmsg; + ret = false; + continue; + } - PlaybackBuffer* rbuf = (*chan)->rbuf[other_rbuf]; + if (size > to_read) { - cerr << name() << ' ' << n << " overwrite read into " << other_rbuf << " @ " << overwrite_sample << " tr " << to_read << " ws " << (*chan)->rbuf[other_rbuf]->write_space() << endl; + to_read = size - to_read; - if (audio_read (rbuf, sum_buffer.get(), mixdown_buffer.get(), gain_buffer.get(), start, to_read, rci, n, reversed)) { - error << string_compose(_("DiskReader %1: when refilling, cannot read %2 from playlist at sample %3"), id(), size, overwrite_sample) << endmsg; - goto midi; + if ((nread = audio_read (buf, mixdown_buffer.get(), gain_buffer.get(), start, to_read, rci, n, reversed)) != to_read) { + error << string_compose(_("DiskReader %1: when overwriting(2), cannot read %2 from playlist at sample %3"), id(), to_read, overwrite_sample) << endmsg; + ret = false; } } - - new_file_sample = overwrite_sample + to_read; - - queue_switch_rbuf (); } - midi: + return ret; +} +bool +DiskReader::overwrite_existing_midi () +{ RTMidiBuffer* mbuf = rt_midibuffer (); if (mbuf) { @@ -619,10 +616,34 @@ DiskReader::overwrite_existing_buffers () cerr << "Reading " << name() << " took " << minsert.elapsed() << " microseconds, final size = " << midi_playlist()->rendered()->size() << endl; } - g_atomic_int_set (&_pending_overwrite, 0); return true; } +bool +DiskReader::overwrite_existing_buffers () +{ + /* called from butler thread */ + + DEBUG_TRACE (DEBUG::DiskIO, string_compose ("%1 overwriting existing buffers at %2\n", owner()->name(), overwrite_sample)); + bool ret = true; + + if (g_atomic_int_get (&_pending_overwrite) & (PlaylistModified|LoopDisabled|LoopChanged)) { + if (!overwrite_existing_audio ()) { + ret = false; + } + } + + if (g_atomic_int_get (&_pending_overwrite) & (LoopChanged|LoopDisabled)) { + if (!overwrite_existing_midi ()) { + ret = false; + } + } + + g_atomic_int_set (&_pending_overwrite, 0); + + return ret; +} + int DiskReader::seek (samplepos_t sample, bool complete_refill) { @@ -648,7 +669,7 @@ DiskReader::seek (samplepos_t sample, bool complete_refill) } for (n = 0, chan = c->begin(); chan != c->end(); ++chan, ++n) { - (*chan)->rbuf[process_rbuf]->reset (); + (*chan)->rbuf->reset (); } playback_sample = sample; @@ -679,7 +700,7 @@ DiskReader::can_internal_playback_seek (sampleoffset_t distance) boost::shared_ptr c = channels.reader(); for (chan = c->begin(); chan != c->end(); ++chan) { - if (!(*chan)->rbuf[process_rbuf]->can_seek (distance)) { + if (!(*chan)->rbuf->can_seek (distance)) { return false; } } @@ -702,9 +723,9 @@ DiskReader::internal_playback_seek (sampleoffset_t distance) boost::shared_ptr c = channels.reader(); for (chan = c->begin(); chan != c->end(); ++chan) { if (distance < 0) { - off = 0 - (sampleoffset_t) (*chan)->rbuf[process_rbuf]->decrement_read_ptr (::llabs (distance)); + off = 0 - (sampleoffset_t) (*chan)->rbuf->decrement_read_ptr (::llabs (distance)); } else { - off = (*chan)->rbuf[process_rbuf]->increment_read_ptr (distance); + off = (*chan)->rbuf->increment_read_ptr (distance); } } @@ -728,25 +749,22 @@ void swap_by_ptr (Sample *first, Sample *last) * @param cnt Count of samples to read. * @param reversed true if we are running backwards, otherwise false. */ -int -DiskReader::audio_read (PBD::PlaybackBuffer*rb, - Sample* sum_buffer, +samplecnt_t +DiskReader::audio_read (Sample* sum_buffer, Sample* mixdown_buffer, float* gain_buffer, - samplepos_t& start, samplecnt_t cnt, + samplepos_t& start, + samplecnt_t cnt, ReaderChannelInfo* rci, - int channel, bool reversed) + int channel, + bool reversed) { samplecnt_t this_read = 0; bool reloop = false; samplepos_t loop_end = 0; samplepos_t loop_start = 0; Location *loc = 0; - - if (!_playlists[DataType::AUDIO]) { - rb->write_zero (cnt); - return 0; - } + const samplecnt_t rcnt = cnt; /* XXX we don't currently play loops in reverse. not sure why */ @@ -811,7 +829,7 @@ DiskReader::audio_read (PBD::PlaybackBuffer*rb, if (audio_playlist()->read (sum_buffer, mixdown_buffer, gain_buffer, start, this_read, channel) != this_read) { error << string_compose(_("DiskReader %1: cannot read %2 from playlist at sample %3"), id(), this_read, start) << endmsg; - return -1; + return 0; } if (loc) { @@ -849,16 +867,11 @@ DiskReader::audio_read (PBD::PlaybackBuffer*rb, } } - samplecnt_t written; - - if ((written = rb->write (sum_buffer, this_read)) != this_read) { - cerr << owner()->name() << " Ringbuffer Write overrun on (tried " << this_read << " wrote " << written << ')' << endl; - } - cnt -= this_read; + sum_buffer += this_read; } - return 0; + return rcnt; } int @@ -926,7 +939,7 @@ DiskReader::refill_audio (Sample* sum_buffer, Sample* mixdown_buffer, float* gai assert(mixdown_buffer); assert(gain_buffer); - samplecnt_t total_space = c->front()->rbuf[process_rbuf]->write_space(); + samplecnt_t total_space = c->front()->rbuf->write_space(); if (total_space == 0) { DEBUG_TRACE (DEBUG::DiskIO, string_compose ("%1: no space to refill\n", name())); @@ -964,7 +977,7 @@ DiskReader::refill_audio (Sample* sum_buffer, Sample* mixdown_buffer, float* gai work with. */ - if (_slaved && total_space < (samplecnt_t) (c->front()->rbuf[process_rbuf]->bufsize() / 2)) { + if (_slaved && total_space < (samplecnt_t) (c->front()->rbuf->bufsize() / 2)) { DEBUG_TRACE (DEBUG::DiskIO, string_compose ("%1: not enough to refill while slaved\n", this)); return 0; } @@ -977,7 +990,7 @@ DiskReader::refill_audio (Sample* sum_buffer, Sample* mixdown_buffer, float* gai /* at start: nothing to do but fill with silence */ for (chan_n = 0, i = c->begin(); i != c->end(); ++i, ++chan_n) { ChannelInfo* chan (*i); - chan->rbuf[process_rbuf]->write_zero (chan->rbuf[process_rbuf]->write_space ()); + chan->rbuf->write_zero (chan->rbuf->write_space ()); } return 0; } @@ -996,7 +1009,7 @@ DiskReader::refill_audio (Sample* sum_buffer, Sample* mixdown_buffer, float* gai /* at end: nothing to do but fill with silence */ for (chan_n = 0, i = c->begin(); i != c->end(); ++i, ++chan_n) { ChannelInfo* chan (*i); - chan->rbuf[process_rbuf]->write_zero (chan->rbuf[process_rbuf]->write_space ()); + chan->rbuf->write_zero (chan->rbuf->write_space ()); } return 0; } @@ -1030,11 +1043,12 @@ DiskReader::refill_audio (Sample* sum_buffer, Sample* mixdown_buffer, float* gai samplepos_t file_sample_tmp = ffa; for (chan_n = 0, i = c->begin(); i != c->end(); ++i, ++chan_n) { + ChannelInfo* chan (*i); file_sample_tmp = ffa; samplecnt_t ts = total_space; - samplecnt_t to_read = min (ts, (samplecnt_t) chan->rbuf[process_rbuf]->write_space ()); + samplecnt_t to_read = min (ts, (samplecnt_t) chan->rbuf->write_space ()); to_read = min (to_read, samples_to_read); assert (to_read >= 0); @@ -1042,11 +1056,26 @@ DiskReader::refill_audio (Sample* sum_buffer, Sample* mixdown_buffer, float* gai if (to_read) { ReaderChannelInfo* rci = dynamic_cast (chan); - cerr << name() << ' ' << chan_n << " refill read into " << process_rbuf << " @ " << file_sample_tmp << " tr " << to_read << " ts was " << ts << "scnt " << samples_to_read << " ws " << chan->rbuf[process_rbuf]->write_space() << endl; - if (audio_read (chan->rbuf[process_rbuf], sum_buffer, mixdown_buffer, gain_buffer, file_sample_tmp, to_read, rci, chan_n, reversed)) { - error << string_compose(_("DiskReader %1: when refilling, cannot read %2 from playlist at sample %3"), id(), to_read, ffa) << endmsg; - ret = -1; - goto out; + samplecnt_t nread; + + cerr << name() << ' ' << chan_n << " refill read @ " << file_sample_tmp << " tr " << to_read << " ts was " << ts << "scnt " << samples_to_read << " ws " << chan->rbuf->write_space() << endl; + + if (!_playlists[DataType::AUDIO]) { + + chan->rbuf->write_zero (to_read); + + } else { + + if ((nread = audio_read (sum_buffer, mixdown_buffer, gain_buffer, file_sample_tmp, to_read, rci, chan_n, reversed)) != to_read) { + error << string_compose(_("DiskReader %1: when refilling, cannot read %2 from playlist at sample %3"), name(), to_read, ffa) << endmsg; + ret = -1; + goto out; + } + + if (chan->rbuf->write (sum_buffer, nread) != nread) { + error << string_compose(_("DiskReader %1: when refilling, cannot write %2 into buffer"), name(), nread) << endmsg; + ret = -1; + } } } @@ -1054,7 +1083,7 @@ DiskReader::refill_audio (Sample* sum_buffer, Sample* mixdown_buffer, float* gai /* not sure if action is needed, * we'll later hit the "to close to the end" case */ - //chan->rbuf[process_rbuf]->write_zero (zero_fill); + //chan->rbuf->write_zero (zero_fill); } } @@ -1661,31 +1690,3 @@ DiskReader::reload_loop () } } -void -DiskReader::queue_switch_rbuf () -{ - /* must hold _rbuf_lock */ - _switch_rbuf = true; -} - -void -DiskReader::switch_rbufs () -{ - /* must hold _rbuf_lock */ - assert (_switch_rbuf); - - std::swap (process_rbuf, other_rbuf); - - boost::shared_ptr c = channels.reader(); - - for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) { - (*chan)->rbuf[other_rbuf]->reset (); - cerr << name() << " after switch/reset, other has " << (*chan)->rbuf[other_rbuf]->write_space() << " of " << (*chan)->rbuf[other_rbuf]->bufsize() << endl; - } - - _switch_rbuf = false; - file_sample[DataType::AUDIO] = new_file_sample; - - cerr << "switched, pbuf now " << process_rbuf << " size " << c->front()->rbuf[process_rbuf]->bufsize() << " other " << other_rbuf << " size " << c->front()->rbuf[other_rbuf]->bufsize() << endl; -} - diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index ad5079ee85..5e33891aa8 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -1448,7 +1448,7 @@ Session::auto_loop_changed (Location* location) // schedule a buffer overwrite to refill buffers with the new loop. - request_overwrite_buffer (boost::shared_ptr()); + request_overwrite_buffer (boost::shared_ptr(), LoopChanged); } } diff --git a/libs/ardour/session_butler.cc b/libs/ardour/session_butler.cc index e7c250833e..0744df6233 100644 --- a/libs/ardour/session_butler.cc +++ b/libs/ardour/session_butler.cc @@ -78,15 +78,16 @@ Session::schedule_capture_buffering_adjustment () } void -Session::request_overwrite_buffer (boost::shared_ptr t) +Session::request_overwrite_buffer (boost::shared_ptr t, OverwriteReason why) { SessionEvent *ev = new SessionEvent (SessionEvent::Overwrite, SessionEvent::Add, SessionEvent::Immediate, 0, 0, 0.0); ev->set_track (t); + ev->overwrite = why; queue_event (ev); } void -Session::overwrite_some_buffers (boost::shared_ptr r) +Session::overwrite_some_buffers (boost::shared_ptr r, OverwriteReason why) { /* this is called from the process thread while handling queued * SessionEvents. Therefore neither playback sample or read offsets in @@ -102,7 +103,7 @@ Session::overwrite_some_buffers (boost::shared_ptr r) if (r) { boost::shared_ptr t = boost::dynamic_pointer_cast (r); assert (t); - t->set_pending_overwrite (); + t->set_pending_overwrite (why); } else { @@ -110,7 +111,7 @@ Session::overwrite_some_buffers (boost::shared_ptr r) for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) { boost::shared_ptr tr = boost::dynamic_pointer_cast (*i); if (tr) { - tr->set_pending_overwrite (); + tr->set_pending_overwrite (why); } } } diff --git a/libs/ardour/session_process.cc b/libs/ardour/session_process.cc index fee4145f2a..8345c3c79b 100644 --- a/libs/ardour/session_process.cc +++ b/libs/ardour/session_process.cc @@ -934,7 +934,7 @@ Session::process_event (SessionEvent* ev) break; case SessionEvent::Overwrite: - overwrite_some_buffers (ev->track); + overwrite_some_buffers (ev->track, ev->overwrite); break; case SessionEvent::Audition: diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc index 13d99a9b11..2c93e10d47 100644 --- a/libs/ardour/session_transport.cc +++ b/libs/ardour/session_transport.cc @@ -1647,7 +1647,7 @@ Session::unset_play_loop (bool change_transport_state) TFSM_EVENT (TransportFSM::StopTransport); } - overwrite_some_buffers (boost::shared_ptr()); + overwrite_some_buffers (boost::shared_ptr(), LoopDisabled); TransportStateChange (); /* EMIT SIGNAL */ } diff --git a/libs/ardour/track.cc b/libs/ardour/track.cc index e9c29ffa83..f2cb9a5b3a 100644 --- a/libs/ardour/track.cc +++ b/libs/ardour/track.cc @@ -503,9 +503,9 @@ Track::do_flush (RunContext c, bool force) } void -Track::set_pending_overwrite () +Track::set_pending_overwrite (OverwriteReason why) { - _disk_reader->set_pending_overwrite (); + _disk_reader->set_pending_overwrite (why); } int diff --git a/libs/pbd/pbd/playback_buffer.h b/libs/pbd/pbd/playback_buffer.h index 932f9224b3..1981adcdd8 100644 --- a/libs/pbd/pbd/playback_buffer.h +++ b/libs/pbd/pbd/playback_buffer.h @@ -119,6 +119,13 @@ public: guint write (T const * src, guint cnt); /* write-thead */ guint write_zero (guint cnt); + /* read-thead */ + guint increment_write_ptr (guint cnt) + { + cnt = std::min (cnt, write_space ()); + g_atomic_int_set (&write_idx, (g_atomic_int_get (&write_idx) + cnt) & size_mask); + return cnt; + } /* read-thead */ void read_flush () @@ -171,6 +178,9 @@ public: } } + guint read_ptr() const { return read_idx; } + guint reserved_size() const { return reserved; } + private: T *buf; guint reservation; -- 2.30.2