mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-29 01:47:43 +01:00
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:
parent
cf11764763
commit
87b2c94759
6 changed files with 116 additions and 60 deletions
|
|
@ -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];
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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 ();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue