diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2019-12-08 22:37:07 -0700 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2019-12-08 22:39:31 -0700 |
commit | cf7bfae926d1a3f48b4b2e9a3a9d72974f031def (patch) | |
tree | 381959d76a4397227e3969604e9eb5021ec0a52f | |
parent | b1b29a631719cbf5238af3818e7707e869d3f87d (diff) |
fix error when continuing to refill audio playback buffers after a buffer switch
The file_sample[AUDIO] member was not updated to reflect the last-read sample in the
switched-to buffer.
Also move several methods and members from DiskIO to DiskReader where they belong.
-rw-r--r-- | libs/ardour/ardour/disk_io.h | 8 | ||||
-rw-r--r-- | libs/ardour/ardour/disk_reader.h | 13 | ||||
-rw-r--r-- | libs/ardour/disk_io.cc | 29 | ||||
-rw-r--r-- | libs/ardour/disk_reader.cc | 49 |
4 files changed, 50 insertions, 49 deletions
diff --git a/libs/ardour/ardour/disk_io.h b/libs/ardour/ardour/disk_io.h index 867a5e89d1..65486febf4 100644 --- a/libs/ardour/ardour/disk_io.h +++ b/libs/ardour/ardour/disk_io.h @@ -111,10 +111,6 @@ public: virtual void adjust_buffering() = 0; - Glib::Threads::Mutex rbuf_lock; - void queue_switch_rbuf (); - void switch_rbufs (); - protected: friend class Auditioner; virtual int seek (samplepos_t which_sample, bool complete_refill = false) = 0; @@ -147,10 +143,6 @@ protected: samplepos_t capture_val; ///< The start or end file sample position }; - bool _switch_rbuf; - int process_rbuf; - int other_rbuf; - /** Information about one audio channel, playback or capture * (depending on the derived class) */ diff --git a/libs/ardour/ardour/disk_reader.h b/libs/ardour/ardour/disk_reader.h index 970295b6c2..e43192f0ff 100644 --- a/libs/ardour/ardour/disk_reader.h +++ b/libs/ardour/ardour/disk_reader.h @@ -117,6 +117,10 @@ public: static void reset_loop_declick (Location*, samplecnt_t sample_rate); 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; friend class MidiTrack; @@ -182,10 +186,11 @@ protected: }; private: - /** The number of samples by which this diskstream's output should be delayed - with respect to the transport sample. This is used for latency compensation. - */ + bool _switch_rbuf; + int process_rbuf; + int other_rbuf; samplepos_t overwrite_sample; + samplepos_t new_file_sample; mutable gint _pending_overwrite; bool overwrite_queued; bool run_must_resolve; @@ -228,6 +233,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*); + + }; } // namespace diff --git a/libs/ardour/disk_io.cc b/libs/ardour/disk_io.cc index d6d076099e..7d153661b9 100644 --- a/libs/ardour/disk_io.cc +++ b/libs/ardour/disk_io.cc @@ -55,9 +55,6 @@ DiskIOProcessor::DiskIOProcessor (Session& s, string const & str, Flag f) , in_set_state (false) , playback_sample (0) , _need_butler (false) - , _switch_rbuf (false) - , process_rbuf (0) - , other_rbuf (1) , channels (new ChannelList) , _midi_buf (0) , _samples_written_to_ringbuffer (0) @@ -348,32 +345,6 @@ DiskIOProcessor::ChannelInfo::~ChannelInfo () } void -DiskIOProcessor::queue_switch_rbuf () -{ - /* must hold _rbuf_lock */ - _switch_rbuf = true; -} - -void -DiskIOProcessor::switch_rbufs () -{ - /* must hold _rbuf_lock */ - assert (_switch_rbuf); - - std::swap (process_rbuf, other_rbuf); - - boost::shared_ptr<ChannelList> 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; - cerr << "switched, pbuf now " << process_rbuf << " size " << c->front()->rbuf[process_rbuf]->bufsize() << " other " << other_rbuf << " size " << c->front()->rbuf[other_rbuf]->bufsize() << endl; -} - -void DiskIOProcessor::drop_track () { _track.reset (); diff --git a/libs/ardour/disk_reader.cc b/libs/ardour/disk_reader.cc index bd94e1556b..304cf7d461 100644 --- a/libs/ardour/disk_reader.cc +++ b/libs/ardour/disk_reader.cc @@ -60,6 +60,9 @@ 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) @@ -349,6 +352,7 @@ 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); } } @@ -573,29 +577,27 @@ DiskReader::overwrite_existing_buffers () boost::scoped_array<Sample> mixdown_buffer (new Sample[size]); boost::scoped_array<float> gain_buffer (new float[size]); - /* reduce size so that we can fill the buffer correctly (ringbuffers - * can only handle size-1, otherwise they appear to be empty) - */ - size--; - - uint32_t n=0; + samplecnt_t to_read = c->front()->rbuf[other_rbuf]->write_space(); + uint32_t n = 0; for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan, ++n) { samplepos_t start = overwrite_sample; - samplecnt_t to_read = size; ReaderChannelInfo* rci = dynamic_cast<ReaderChannelInfo*> (*chan); PlaybackBuffer<Sample>* rbuf = (*chan)->rbuf[other_rbuf]; + cerr << name() << ' ' << n << " overwrite read into " << other_rbuf << " @ " << overwrite_sample << " tr " << to_read << " ws " << (*chan)->rbuf[other_rbuf]->write_space() << endl; + 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; } - } + new_file_sample = overwrite_sample + to_read; + queue_switch_rbuf (); } @@ -850,7 +852,7 @@ DiskReader::audio_read (PBD::PlaybackBuffer<Sample>*rb, samplecnt_t written; if ((written = rb->write (sum_buffer, this_read)) != this_read) { - cerr << owner()->name() << " Ringbuffer Write overrun (tried " << this_read << " wrote " << written << ')' << endl; + cerr << owner()->name() << " Ringbuffer Write overrun on (tried " << this_read << " wrote " << written << ')' << endl; } cnt -= this_read; @@ -1040,6 +1042,7 @@ DiskReader::refill_audio (Sample* sum_buffer, Sample* mixdown_buffer, float* gai if (to_read) { ReaderChannelInfo* rci = dynamic_cast<ReaderChannelInfo*> (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; @@ -1658,3 +1661,31 @@ 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<ChannelList> 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; +} + |