Separate ChannelInfo for disk reader and writer

This allows to use different types for write and read buffers, in
preparation for a dedicated reader-buffer.
This commit is contained in:
Robin Gareus 2018-05-22 21:35:27 +02:00
parent cf11764763
commit 87b2c94759
6 changed files with 116 additions and 60 deletions

View file

@ -56,6 +56,7 @@ public:
static const std::string state_node_name;
DiskIOProcessor (Session&, const std::string& name, Flag f);
virtual ~DiskIOProcessor ();
void set_route (boost::shared_ptr<Route>);
void drop_route ();
@ -150,28 +151,33 @@ protected:
struct ChannelInfo : public boost::noncopyable {
ChannelInfo (samplecnt_t buffer_size);
~ChannelInfo ();
virtual ~ChannelInfo ();
/** A ringbuffer for data to be played back, written to in the
butler thread, read from in the process thread.
*/
/** Ringbuffer for data to be played back.
* written to in the butler thread, read from in the process thread.
*/
PBD::RingBufferNPT<Sample>* buf;
/** A ringbuffer for data to be recorded back, written to in the
* process thread, read from in the butler thread.
*/
PBD::RingBufferNPT<Sample>* wbuf;
PBD::RingBufferNPT<Sample>::rw_vector rw_vector;
/* used only by capture */
boost::shared_ptr<AudioFileSource> write_source;
PBD::RingBufferNPT<CaptureTransition> * capture_transition_buf;
PBD::RingBufferNPT<CaptureTransition>* capture_transition_buf;
/* used in the butler thread only */
samplecnt_t curr_capture_cnt;
void resize (samplecnt_t);
virtual void resize (samplecnt_t) = 0;
};
typedef std::vector<ChannelInfo*> ChannelList;
SerializedRCUManager<ChannelList> channels;
int add_channel_to (boost::shared_ptr<ChannelList>, uint32_t how_many);
virtual int add_channel_to (boost::shared_ptr<ChannelList>, uint32_t how_many) = 0;
int remove_channel_from (boost::shared_ptr<ChannelList>, uint32_t how_many);
boost::shared_ptr<Playlist> _playlists[DataType::num_types];

View file

@ -102,6 +102,15 @@ protected:
friend class Track;
friend class MidiTrack;
struct ReaderChannelInfo : public DiskIOProcessor::ChannelInfo {
ReaderChannelInfo (samplecnt_t buffer_size)
: DiskIOProcessor::ChannelInfo::ChannelInfo (buffer_size)
{
resize (buffer_size);
}
void resize (samplecnt_t);
};
XMLNode& state ();
void resolve_tracker (Evoral::EventSink<samplepos_t>& buffer, samplepos_t time);
@ -110,6 +119,8 @@ protected:
int use_playlist (DataType, boost::shared_ptr<Playlist>);
void playlist_ranges_moved (std::list< Evoral::RangeMove<samplepos_t> > const &, bool);
int add_channel_to (boost::shared_ptr<ChannelList>, uint32_t how_many);
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.

View file

@ -133,6 +133,15 @@ public:
protected:
friend class Track;
struct WriterChannelInfo : public DiskIOProcessor::ChannelInfo {
WriterChannelInfo (samplecnt_t buffer_size)
: DiskIOProcessor::ChannelInfo::ChannelInfo (buffer_size)
{
resize (buffer_size);
}
void resize (samplecnt_t);
};
virtual XMLNode& state ();
int do_flush (RunContext context, bool force = false);
@ -143,6 +152,8 @@ protected:
void setup_destructive_playlist ();
void use_destructive_playlist ();
int add_channel_to (boost::shared_ptr<ChannelList>, uint32_t how_many);
void engage_record_enable ();
void disengage_record_enable ();
void engage_record_safe ();

View file

@ -63,6 +63,23 @@ DiskIOProcessor::DiskIOProcessor (Session& s, string const & str, Flag f)
set_display_to_user (false);
}
DiskIOProcessor::~DiskIOProcessor ()
{
{
RCUWriter<ChannelList> writer (channels);
boost::shared_ptr<ChannelList> c = writer.get_copy();
for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) {
delete *chan;
}
c->clear();
}
channels.flush ();
}
void
DiskIOProcessor::init ()
{
@ -218,20 +235,6 @@ DiskIOProcessor::set_state (const XMLNode& node, int version)
return 0;
}
int
DiskIOProcessor::add_channel_to (boost::shared_ptr<ChannelList> c, uint32_t how_many)
{
while (how_many--) {
c->push_back (new ChannelInfo (_session.butler()->audio_diskstream_playback_buffer_size()));
DEBUG_TRACE (DEBUG::DiskIO, string_compose ("%1: new channel, write space = %2 read = %3\n",
name(),
c->back()->buf->write_space(),
c->back()->buf->read_space()));
}
return 0;
}
int
DiskIOProcessor::add_channel (uint32_t how_many)
{
@ -329,32 +332,20 @@ DiskIOProcessor::use_playlist (DataType dt, boost::shared_ptr<Playlist> playlist
}
DiskIOProcessor::ChannelInfo::ChannelInfo (samplecnt_t bufsize)
: buf (new RingBufferNPT<Sample> (bufsize))
: buf (0)
, wbuf (0)
, capture_transition_buf (0)
, curr_capture_cnt (0)
{
/* touch the ringbuffer buffer, which will cause
them to be mapped into locked physical RAM if
we're running with mlockall(). this doesn't do
much if we're not.
*/
memset (buf->buffer(), 0, sizeof (Sample) * buf->bufsize());
capture_transition_buf = new RingBufferNPT<CaptureTransition> (256);
}
void
DiskIOProcessor::ChannelInfo::resize (samplecnt_t bufsize)
{
delete buf;
buf = new RingBufferNPT<Sample> (bufsize);
memset (buf->buffer(), 0, sizeof (Sample) * buf->bufsize());
}
DiskIOProcessor::ChannelInfo::~ChannelInfo ()
{
delete buf;
buf = 0;
delete wbuf;
delete capture_transition_buf;
buf = 0;
wbuf = 0;
capture_transition_buf = 0;
}

View file

@ -70,21 +70,30 @@ DiskReader::~DiskReader ()
_playlists[n]->release ();
}
}
delete _midi_buf;
}
{
RCUWriter<ChannelList> writer (channels);
boost::shared_ptr<ChannelList> c = writer.get_copy();
void
DiskReader::ReaderChannelInfo::resize (samplecnt_t bufsize)
{
delete buf;
/* touch memory to lock it */
buf = new RingBufferNPT<Sample> (bufsize);
memset (buf->buffer(), 0, sizeof (Sample) * buf->bufsize());
}
for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) {
delete *chan;
}
c->clear();
int
DiskReader::add_channel_to (boost::shared_ptr<ChannelList> c, uint32_t how_many)
{
while (how_many--) {
c->push_back (new ReaderChannelInfo (_session.butler()->audio_diskstream_playback_buffer_size()));
DEBUG_TRACE (DEBUG::DiskIO, string_compose ("%1: new reader channel, write space = %2 read = %3\n",
name(),
c->back()->buf->write_space(),
c->back()->buf->read_space()));
}
channels.flush ();
delete _midi_buf;
return 0;
}
void

View file

@ -78,6 +78,34 @@ DiskWriter::default_chunk_samples ()
return 65536;
}
void
DiskWriter::WriterChannelInfo::resize (samplecnt_t bufsize)
{
if (!capture_transition_buf) {
capture_transition_buf = new RingBufferNPT<CaptureTransition> (256);
}
delete wbuf;
wbuf = new RingBufferNPT<Sample> (bufsize);
/* touch memory to lock it */
memset (wbuf->buffer(), 0, sizeof (Sample) * wbuf->bufsize());
}
int
DiskWriter::add_channel_to (boost::shared_ptr<ChannelList> c, uint32_t how_many)
{
while (how_many--) {
c->push_back (new WriterChannelInfo (_session.butler()->audio_diskstream_capture_buffer_size()));
DEBUG_TRACE (DEBUG::DiskIO, string_compose ("%1: new writer channel, write space = %2 read = %3\n",
name(),
c->back()->wbuf->write_space(),
c->back()->wbuf->read_space()));
}
return 0;
}
bool
DiskWriter::set_write_source_name (string const & str)
{
@ -453,7 +481,7 @@ DiskWriter::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp
ChannelInfo* chaninfo (*chan);
AudioBuffer& buf (bufs.get_audio (n%n_buffers));
chaninfo->buf->get_write_vector (&chaninfo->rw_vector);
chaninfo->wbuf->get_write_vector (&chaninfo->rw_vector);
if (rec_nframes <= (samplecnt_t) chaninfo->rw_vector.len[0]) {
@ -478,7 +506,7 @@ DiskWriter::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp
memcpy (chaninfo->rw_vector.buf[1], incoming + first, sizeof (Sample) * (rec_nframes - first));
}
chaninfo->buf->increment_write_ptr (rec_nframes);
chaninfo->wbuf->increment_write_ptr (rec_nframes);
}
@ -581,7 +609,7 @@ DiskWriter::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp
/* AUDIO BUTLER REQUIRED CODE */
if (_playlists[DataType::AUDIO] && !c->empty()) {
if (((samplecnt_t) c->front()->buf->read_space() >= _chunk_samples)) {
if (((samplecnt_t) c->front()->wbuf->read_space() >= _chunk_samples)) {
_need_butler = true;
}
}
@ -757,8 +785,8 @@ DiskWriter::buffer_load () const
return 1.0;
}
return (float) ((double) c->front()->buf->write_space()/
(double) c->front()->buf->bufsize());
return (float) ((double) c->front()->wbuf->write_space()/
(double) c->front()->wbuf->bufsize());
}
void
@ -784,7 +812,7 @@ DiskWriter::seek (samplepos_t sample, bool complete_refill)
boost::shared_ptr<ChannelList> c = channels.reader();
for (n = 0, chan = c->begin(); chan != c->end(); ++chan, ++n) {
(*chan)->buf->reset ();
(*chan)->wbuf->reset ();
}
_midi_buf->reset ();
@ -819,7 +847,7 @@ DiskWriter::do_flush (RunContext ctxt, bool force_flush)
boost::shared_ptr<ChannelList> c = channels.reader();
for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) {
(*chan)->buf->get_read_vector (&vector);
(*chan)->wbuf->get_read_vector (&vector);
total = vector.len[0] + vector.len[1];
@ -899,7 +927,7 @@ DiskWriter::do_flush (RunContext ctxt, bool force_flush)
return -1;
}
(*chan)->buf->increment_read_ptr (to_write);
(*chan)->wbuf->increment_read_ptr (to_write);
(*chan)->curr_capture_cnt += to_write;
if ((to_write == vector.len[0]) && (total > to_write) && (to_write < _chunk_samples) && !destructive()) {
@ -918,7 +946,7 @@ DiskWriter::do_flush (RunContext ctxt, bool force_flush)
return -1;
}
(*chan)->buf->increment_read_ptr (to_write);
(*chan)->wbuf->increment_read_ptr (to_write);
(*chan)->curr_capture_cnt += to_write;
}
}