mirror of
https://github.com/Ardour/ardour.git
synced 2026-01-03 12:19:33 +01:00
addd more DEBUG_TRACE for DiskIO; set DiskIOProcess::_need_butler more appropriately; other minor adjustments
This commit is contained in:
parent
480ebd2c55
commit
560ca0569f
8 changed files with 126 additions and 90 deletions
|
|
@ -429,7 +429,7 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
|
|||
void allow_auto_play (bool yn);
|
||||
void request_transport_speed (double speed, bool as_default = true);
|
||||
void request_transport_speed_nonzero (double, bool as_default = true);
|
||||
void request_overwrite_buffer (Track *);
|
||||
void request_overwrite_buffer (boost::shared_ptr<Route>);
|
||||
void adjust_playback_buffering();
|
||||
void adjust_capture_buffering();
|
||||
void request_track_speed (Track *, double speed);
|
||||
|
|
|
|||
|
|
@ -259,6 +259,10 @@ AudioTrack::roll (pframes_t nframes, framepos_t start_frame, framepos_t end_fram
|
|||
|
||||
process_output_buffers (bufs, start_frame, end_frame, nframes, declick, (!_disk_writer->record_enabled() && _session.transport_rolling()));
|
||||
|
||||
if (_disk_reader->need_butler() || _disk_writer->need_butler()) {
|
||||
need_butler = true;
|
||||
}
|
||||
|
||||
flush_processor_buffers_locked (nframes);
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -293,6 +293,10 @@ DiskIOProcessor::add_channel_to (boost::shared_ptr<ChannelList> c, uint32_t how_
|
|||
while (how_many--) {
|
||||
c->push_back (new ChannelInfo (_session.butler()->audio_diskstream_playback_buffer_size()));
|
||||
interpolation.add_channel_to (_session.butler()->audio_diskstream_playback_buffer_size(), speed_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;
|
||||
|
|
|
|||
|
|
@ -224,8 +224,8 @@ DiskReader::use_playlist (DataType dt, boost::shared_ptr<Playlist> playlist)
|
|||
take care of the buffer refill.
|
||||
*/
|
||||
|
||||
if (!overwrite_queued && prior_playlist) {
|
||||
// !!! _session.request_overwrite_buffer (this);
|
||||
if (!overwrite_queued && (prior_playlist || _session.loading())) {
|
||||
_session.request_overwrite_buffer (_route);
|
||||
overwrite_queued = true;
|
||||
}
|
||||
|
||||
|
|
@ -242,6 +242,8 @@ DiskReader::run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame,
|
|||
framecnt_t playback_distance = 0;
|
||||
const bool need_disk_signal = result_required || _monitoring_choice == MonitorDisk || _monitoring_choice == MonitorCue;
|
||||
|
||||
_need_butler = false;
|
||||
|
||||
if (fabsf (_actual_speed) != 1.0f) {
|
||||
midi_interpolation.set_speed (_target_speed);
|
||||
interpolation.set_speed (_target_speed);
|
||||
|
|
@ -358,73 +360,80 @@ DiskReader::run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame,
|
|||
}
|
||||
}
|
||||
|
||||
_need_butler = false;
|
||||
|
||||
if (_actual_speed < 0.0) {
|
||||
playback_sample -= playback_distance;
|
||||
} else {
|
||||
playback_sample += playback_distance;
|
||||
}
|
||||
|
||||
if (!c->empty()) {
|
||||
if (_slaved) {
|
||||
if (c->front()->buf->write_space() >= c->front()->buf->bufsize() / 2) {
|
||||
if (_playlists[DataType::AUDIO]) {
|
||||
if (!c->empty()) {
|
||||
if (_slaved) {
|
||||
if (c->front()->buf->write_space() >= c->front()->buf->bufsize() / 2) {
|
||||
DEBUG_TRACE (DEBUG::Butler, string_compose ("%1: slaved, write space = %2 of %3\n", name(), c->front()->buf->write_space(),
|
||||
c->front()->buf->bufsize()));
|
||||
_need_butler = true;
|
||||
}
|
||||
} else {
|
||||
if ((framecnt_t) c->front()->buf->write_space() >= _chunk_frames) {
|
||||
DEBUG_TRACE (DEBUG::Butler, string_compose ("%1: write space = %2 of %3\n", name(), c->front()->buf->write_space(),
|
||||
_chunk_frames));
|
||||
_need_butler = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_playlists[DataType::MIDI]) {
|
||||
/* MIDI butler needed part */
|
||||
|
||||
uint32_t frames_read = g_atomic_int_get(const_cast<gint*>(&_frames_read_from_ringbuffer));
|
||||
uint32_t frames_written = g_atomic_int_get(const_cast<gint*>(&_frames_written_to_ringbuffer));
|
||||
|
||||
/*
|
||||
cerr << name() << " MDS written: " << frames_written << " - read: " << frames_read <<
|
||||
" = " << frames_written - frames_read
|
||||
<< " + " << playback_distance << " < " << midi_readahead << " = " << need_butler << ")" << endl;
|
||||
*/
|
||||
|
||||
/* frames_read will generally be less than frames_written, but
|
||||
* immediately after an overwrite, we can end up having read some data
|
||||
* before we've written any. we don't need to trip an assert() on this,
|
||||
* but we do need to check so that the decision on whether or not we
|
||||
* need the butler is done correctly.
|
||||
*/
|
||||
|
||||
/* furthermore..
|
||||
*
|
||||
* Doing heavy GUI operations[1] can stall also the butler.
|
||||
* The RT-thread meanwhile will happily continue and
|
||||
* ‘frames_read’ (from buffer to output) will become larger
|
||||
* than ‘frames_written’ (from disk to buffer).
|
||||
*
|
||||
* The disk-stream is now behind..
|
||||
*
|
||||
* In those cases the butler needs to be summed to refill the buffer (done now)
|
||||
* AND we need to skip (frames_read - frames_written). ie remove old events
|
||||
* before playback_sample from the rinbuffer.
|
||||
*
|
||||
* [1] one way to do so is described at #6170.
|
||||
* For me just popping up the context-menu on a MIDI-track header
|
||||
* of a track with a large (think beethoven :) midi-region also did the
|
||||
* trick. The playhead stalls for 2 or 3 sec, until the context-menu shows.
|
||||
*
|
||||
* In both cases the root cause is that redrawing MIDI regions on the GUI is still very slow
|
||||
* and can stall
|
||||
*/
|
||||
if (frames_read <= frames_written) {
|
||||
if ((frames_written - frames_read) + playback_distance < midi_readahead) {
|
||||
_need_butler = true;
|
||||
}
|
||||
} else {
|
||||
if ((framecnt_t) c->front()->buf->write_space() >= _chunk_frames) {
|
||||
_need_butler = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* MIDI butler needed part */
|
||||
|
||||
uint32_t frames_read = g_atomic_int_get(const_cast<gint*>(&_frames_read_from_ringbuffer));
|
||||
uint32_t frames_written = g_atomic_int_get(const_cast<gint*>(&_frames_written_to_ringbuffer));
|
||||
|
||||
/*
|
||||
cerr << name() << " MDS written: " << frames_written << " - read: " << frames_read <<
|
||||
" = " << frames_written - frames_read
|
||||
<< " + " << playback_distance << " < " << midi_readahead << " = " << need_butler << ")" << endl;
|
||||
*/
|
||||
|
||||
/* frames_read will generally be less than frames_written, but
|
||||
* immediately after an overwrite, we can end up having read some data
|
||||
* before we've written any. we don't need to trip an assert() on this,
|
||||
* but we do need to check so that the decision on whether or not we
|
||||
* need the butler is done correctly.
|
||||
*/
|
||||
|
||||
/* furthermore..
|
||||
*
|
||||
* Doing heavy GUI operations[1] can stall also the butler.
|
||||
* The RT-thread meanwhile will happily continue and
|
||||
* ‘frames_read’ (from buffer to output) will become larger
|
||||
* than ‘frames_written’ (from disk to buffer).
|
||||
*
|
||||
* The disk-stream is now behind..
|
||||
*
|
||||
* In those cases the butler needs to be summed to refill the buffer (done now)
|
||||
* AND we need to skip (frames_read - frames_written). ie remove old events
|
||||
* before playback_sample from the rinbuffer.
|
||||
*
|
||||
* [1] one way to do so is described at #6170.
|
||||
* For me just popping up the context-menu on a MIDI-track header
|
||||
* of a track with a large (think beethoven :) midi-region also did the
|
||||
* trick. The playhead stalls for 2 or 3 sec, until the context-menu shows.
|
||||
*
|
||||
* In both cases the root cause is that redrawing MIDI regions on the GUI is still very slow
|
||||
* and can stall
|
||||
*/
|
||||
if (frames_read <= frames_written) {
|
||||
if ((frames_written - frames_read) + playback_distance < midi_readahead) {
|
||||
_need_butler = true;
|
||||
}
|
||||
} else {
|
||||
_need_butler = true;
|
||||
}
|
||||
|
||||
DEBUG_TRACE (DEBUG::Butler, string_compose ("%1 reader run, needs butler = %2\n", name(), _need_butler));
|
||||
/* make sure bufs shows whatever data we had available */
|
||||
|
||||
ChanCount cnt;
|
||||
|
|
@ -480,6 +489,8 @@ DiskReader::overwrite_existing_buffers ()
|
|||
|
||||
overwrite_queued = false;
|
||||
|
||||
DEBUG_TRACE (DEBUG::DiskIO, string_compose ("%1 overwriting existing buffers at %2\n", overwrite_frame));
|
||||
|
||||
if (!c->empty ()) {
|
||||
|
||||
/* AUDIO */
|
||||
|
|
@ -679,6 +690,11 @@ DiskReader::audio_read (Sample* buf, Sample* mixdown_buffer, float* gain_buffer,
|
|||
framecnt_t offset = 0;
|
||||
Location *loc = 0;
|
||||
|
||||
if (!_playlists[DataType::AUDIO]) {
|
||||
memset (buf, 0, sizeof (Sample) * cnt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* XXX we don't currently play loops in reverse. not sure why */
|
||||
|
||||
if (!reversed) {
|
||||
|
|
@ -811,7 +827,11 @@ DiskReader::refill (Sample* mixdown_buffer, float* gain_buffer, framecnt_t fill_
|
|||
int
|
||||
DiskReader::refill_audio (Sample* mixdown_buffer, float* gain_buffer, framecnt_t fill_level)
|
||||
{
|
||||
if (_session.state_of_the_state() & Session::Loading) {
|
||||
/* do not read from disk while session is marked as Loading, to avoid
|
||||
useless redundant I/O.
|
||||
*/
|
||||
|
||||
if (_session.loading()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -826,10 +846,6 @@ DiskReader::refill_audio (Sample* mixdown_buffer, float* gain_buffer, framecnt_t
|
|||
boost::shared_ptr<ChannelList> c = channels.reader();
|
||||
framecnt_t ts;
|
||||
|
||||
/* do not read from disk while session is marked as Loading, to avoid
|
||||
useless redundant I/O.
|
||||
*/
|
||||
|
||||
if (c->empty()) {
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -845,6 +861,7 @@ DiskReader::refill_audio (Sample* mixdown_buffer, float* gain_buffer, framecnt_t
|
|||
c->front()->buf->get_write_vector (&vector);
|
||||
|
||||
if ((total_space = vector.len[0] + vector.len[1]) == 0) {
|
||||
DEBUG_TRACE (DEBUG::DiskIO, string_compose ("%1: no space to refill\n", name()));
|
||||
/* nowhere to write to */
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -869,6 +886,7 @@ DiskReader::refill_audio (Sample* mixdown_buffer, float* gain_buffer, framecnt_t
|
|||
the playback buffer is empty.
|
||||
*/
|
||||
|
||||
DEBUG_TRACE (DEBUG::DiskIO, string_compose ("%1: space to refill %2 vs. chunk %3 (speed = %4)\n", name(), total_space, _chunk_frames, _actual_speed));
|
||||
if ((total_space < _chunk_frames) && fabs (_actual_speed) < 2.0f) {
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -879,6 +897,7 @@ DiskReader::refill_audio (Sample* mixdown_buffer, float* gain_buffer, framecnt_t
|
|||
*/
|
||||
|
||||
if (_slaved && total_space < (framecnt_t) (c->front()->buf->bufsize() / 2)) {
|
||||
DEBUG_TRACE (DEBUG::DiskIO, string_compose ("%1: not enough to refill while slaved\n", this));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -965,9 +984,7 @@ DiskReader::refill_audio (Sample* mixdown_buffer, float* gain_buffer, framecnt_t
|
|||
|
||||
framecnt_t samples_to_read = byte_size_for_read / (bits_per_sample / 8);
|
||||
|
||||
//cerr << name() << " will read " << byte_size_for_read << " out of total bytes " << total_bytes << " in buffer of "
|
||||
// << c->front()->buf->bufsize() * bits_per_sample / 8 << " bps = " << bits_per_sample << endl;
|
||||
// cerr << name () << " read samples = " << samples_to_read << " out of total space " << total_space << " in buffer of " << c->front()->buf->bufsize() << " samples\n";
|
||||
DEBUG_TRACE (DEBUG::DiskIO, string_compose ("%1: will refill %2 channels with %3 samples\n", name(), c->size(), total_space));
|
||||
|
||||
// uint64_t before = g_get_monotonic_time ();
|
||||
// uint64_t elapsed;
|
||||
|
|
@ -1378,12 +1395,15 @@ DiskReader::midi_read (framepos_t& start, framecnt_t dur, bool reversed)
|
|||
int
|
||||
DiskReader::refill_midi ()
|
||||
{
|
||||
int ret = 0;
|
||||
if (!_playlists[DataType::MIDI]) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t write_space = _midi_buf->write_space();
|
||||
bool reversed = (_visible_speed * _session.transport_speed()) < 0.0f;
|
||||
|
||||
DEBUG_TRACE (DEBUG::MidiDiskstreamIO, string_compose ("MDS refill, write space = %1 file frame = %2\n",
|
||||
write_space, file_frame));
|
||||
DEBUG_TRACE (DEBUG::DiskIO, string_compose ("MIDI refill, write space = %1 file frame = %2\n", write_space, file_frame));
|
||||
//PBD::stacktrace (cerr, 20);
|
||||
|
||||
/* no space to write */
|
||||
if (write_space == 0) {
|
||||
|
|
@ -1395,27 +1415,26 @@ DiskReader::refill_midi ()
|
|||
}
|
||||
|
||||
/* at end: nothing to do */
|
||||
|
||||
if (file_frame == max_framepos) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (_playlists[DataType::MIDI]) {
|
||||
int ret = 0;
|
||||
const uint32_t frames_read = g_atomic_int_get (&_frames_read_from_ringbuffer);
|
||||
const uint32_t frames_written = g_atomic_int_get (&_frames_written_to_ringbuffer);
|
||||
|
||||
const uint32_t frames_read = g_atomic_int_get (&_frames_read_from_ringbuffer);
|
||||
const uint32_t frames_written = g_atomic_int_get (&_frames_written_to_ringbuffer);
|
||||
if ((frames_read < frames_written) && (frames_written - frames_read) >= midi_readahead) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((frames_read < frames_written) && (frames_written - frames_read) >= midi_readahead) {
|
||||
return 0;
|
||||
}
|
||||
framecnt_t to_read = midi_readahead - ((framecnt_t)frames_written - (framecnt_t)frames_read);
|
||||
|
||||
framecnt_t to_read = midi_readahead - ((framecnt_t)frames_written - (framecnt_t)frames_read);
|
||||
to_read = min (to_read, (framecnt_t) (max_framepos - file_frame));
|
||||
to_read = min (to_read, (framecnt_t) write_space);
|
||||
|
||||
to_read = min (to_read, (framecnt_t) (max_framepos - file_frame));
|
||||
to_read = min (to_read, (framecnt_t) write_space);
|
||||
|
||||
if (midi_read (file_frame, to_read, reversed)) {
|
||||
ret = -1;
|
||||
}
|
||||
if (midi_read (file_frame, to_read, reversed)) {
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -477,9 +477,6 @@ DiskWriter::prepare_record_status(framepos_t capture_start_frame)
|
|||
void
|
||||
DiskWriter::run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame,
|
||||
double speed, pframes_t nframes, bool result_required)
|
||||
|
||||
/* (BufferSet& bufs, framepos_t transport_frame, pframes_t nframes, framecnt_t& playback_distance, bool need_disk_signal)
|
||||
*/
|
||||
{
|
||||
uint32_t n;
|
||||
boost::shared_ptr<ChannelList> c = channels.reader();
|
||||
|
|
@ -490,6 +487,8 @@ DiskWriter::run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame,
|
|||
bool re = record_enabled ();
|
||||
bool can_record = _session.actively_recording ();
|
||||
|
||||
_need_butler = false;
|
||||
|
||||
check_record_status (start_frame, can_record);
|
||||
|
||||
if (nframes == 0) {
|
||||
|
|
@ -687,7 +686,7 @@ DiskWriter::run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame,
|
|||
|
||||
/* AUDIO BUTLER REQUIRED CODE */
|
||||
|
||||
if (!c->empty()) {
|
||||
if (_playlists[DataType::AUDIO] && !c->empty()) {
|
||||
if (((framecnt_t) c->front()->buf->read_space() >= _chunk_frames)) {
|
||||
_need_butler = true;
|
||||
}
|
||||
|
|
@ -695,9 +694,11 @@ DiskWriter::run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame,
|
|||
|
||||
/* MIDI BUTLER REQUIRED CODE */
|
||||
|
||||
if (_midi_buf->read_space() < _midi_buf->bufsize() / 2) {
|
||||
if (_playlists[DataType::MIDI] && (_midi_buf->read_space() < _midi_buf->bufsize() / 2)) {
|
||||
_need_butler = true;
|
||||
}
|
||||
|
||||
DEBUG_TRACE (DEBUG::Butler, string_compose ("%1 writer run, needs butler = %2\n", name(), _need_butler));
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -76,10 +76,15 @@ Session::schedule_curve_reallocation ()
|
|||
}
|
||||
|
||||
void
|
||||
Session::request_overwrite_buffer (Track* t)
|
||||
Session::request_overwrite_buffer (boost::shared_ptr<Route> r)
|
||||
{
|
||||
boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track> (r);
|
||||
if (!t) {
|
||||
return;
|
||||
}
|
||||
|
||||
SessionEvent *ev = new SessionEvent (SessionEvent::Overwrite, SessionEvent::Add, SessionEvent::Immediate, 0, 0, 0.0);
|
||||
ev->set_ptr (t);
|
||||
ev->set_ptr (t.get());
|
||||
queue_event (ev);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -218,6 +218,7 @@ Session::process_routes (pframes_t nframes, bool& need_butler)
|
|||
}
|
||||
|
||||
if (b) {
|
||||
DEBUG_TRACE (DEBUG::Butler, string_compose ("%1 rolled and needs butler\n", (*i)->name()));
|
||||
need_butler = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -548,6 +549,7 @@ Session::process_with_events (pframes_t nframes)
|
|||
} /* implicit release of route lock */
|
||||
|
||||
if (session_needs_butler) {
|
||||
DEBUG_TRACE (DEBUG::Butler, "p-with-events: session needs butler, call it\n");
|
||||
_butler->summon ();
|
||||
}
|
||||
}
|
||||
|
|
@ -859,6 +861,7 @@ Session::follow_slave_silently (pframes_t nframes, float slave_speed)
|
|||
get_track_statistics ();
|
||||
|
||||
if (need_butler) {
|
||||
DEBUG_TRACE (DEBUG::Butler, "f-slave-silently: session needs butler, call it\n");
|
||||
_butler->summon ();
|
||||
}
|
||||
|
||||
|
|
@ -942,6 +945,7 @@ Session::process_without_events (pframes_t nframes)
|
|||
check_declick_out ();
|
||||
|
||||
if (session_needs_butler) {
|
||||
DEBUG_TRACE (DEBUG::Butler, "p-without-events: session needs butler, call it\n");
|
||||
_butler->summon ();
|
||||
}
|
||||
}
|
||||
|
|
@ -964,6 +968,7 @@ Session::process_audition (pframes_t nframes)
|
|||
/* run the auditioner, and if it says we need butler service, ask for it */
|
||||
|
||||
if (auditioner->play_audition (nframes) > 0) {
|
||||
DEBUG_TRACE (DEBUG::Butler, "auditioner needs butler, call it\n");
|
||||
_butler->summon ();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -80,7 +80,6 @@ Track::init ()
|
|||
|
||||
_disk_reader->set_block_size (_session.get_block_size ());
|
||||
_disk_reader->set_route (shared_from_this());
|
||||
_disk_reader->do_refill_with_alloc ();
|
||||
|
||||
_disk_writer.reset (new DiskWriter (_session, name(), dflags));
|
||||
_disk_writer->set_block_size (_session.get_block_size ());
|
||||
|
|
@ -546,7 +545,6 @@ Track::silent_roll (pframes_t nframes, framepos_t /*start_frame*/, framepos_t /*
|
|||
boost::shared_ptr<Playlist>
|
||||
Track::playlist ()
|
||||
{
|
||||
cerr << name() << " lookup " << data_type().to_string() << " pl's\n";
|
||||
return _playlists[data_type()];
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue