From 53e6f13852f1cc831002cce9dc84d07e7e526515 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Tue, 11 Apr 2017 17:38:34 +0100 Subject: addd more DEBUG_TRACE for DiskIO; set DiskIOProcess::_need_butler more appropriately; other minor adjustments --- libs/ardour/ardour/session.h | 2 +- libs/ardour/audio_track.cc | 4 + libs/ardour/disk_io.cc | 4 + libs/ardour/disk_reader.cc | 171 +++++++++++++++++++++++------------------ libs/ardour/disk_writer.cc | 11 +-- libs/ardour/session_butler.cc | 9 ++- libs/ardour/session_process.cc | 5 ++ libs/ardour/track.cc | 2 - 8 files changed, 122 insertions(+), 86 deletions(-) diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 4c848ec366..7d408234b2 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -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); void adjust_playback_buffering(); void adjust_capture_buffering(); void request_track_speed (Track *, double speed); diff --git a/libs/ardour/audio_track.cc b/libs/ardour/audio_track.cc index e17babaff2..22e2cb7356 100644 --- a/libs/ardour/audio_track.cc +++ b/libs/ardour/audio_track.cc @@ -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; diff --git a/libs/ardour/disk_io.cc b/libs/ardour/disk_io.cc index e15620b1d2..4acbc49057 100644 --- a/libs/ardour/disk_io.cc +++ b/libs/ardour/disk_io.cc @@ -293,6 +293,10 @@ DiskIOProcessor::add_channel_to (boost::shared_ptr 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; diff --git a/libs/ardour/disk_reader.cc b/libs/ardour/disk_reader.cc index cf3b29c306..2c2bcb4375 100644 --- a/libs/ardour/disk_reader.cc +++ b/libs/ardour/disk_reader.cc @@ -224,8 +224,8 @@ DiskReader::use_playlist (DataType dt, boost::shared_ptr 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) { - _need_butler = true; - } - } else { - if ((framecnt_t) c->front()->buf->write_space() >= _chunk_frames) { - _need_butler = true; + 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; + } } } } - /* MIDI butler needed part */ - - uint32_t frames_read = g_atomic_int_get(const_cast(&_frames_read_from_ringbuffer)); - uint32_t frames_written = g_atomic_int_get(const_cast(&_frames_written_to_ringbuffer)); + if (_playlists[DataType::MIDI]) { + /* MIDI butler needed part */ - /* - cerr << name() << " MDS written: " << frames_written << " - read: " << frames_read << - " = " << frames_written - frames_read - << " + " << playback_distance << " < " << midi_readahead << " = " << need_butler << ")" << endl; - */ + uint32_t frames_read = g_atomic_int_get(const_cast(&_frames_read_from_ringbuffer)); + uint32_t frames_written = g_atomic_int_get(const_cast(&_frames_written_to_ringbuffer)); - /* 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. - */ + /* + cerr << name() << " MDS written: " << frames_written << " - read: " << frames_read << + " = " << frames_written - frames_read + << " + " << playback_distance << " < " << midi_readahead << " = " << need_butler << ")" << endl; + */ - /* 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) { + /* 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; } - } 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 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]) { - - 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); + 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); - 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; diff --git a/libs/ardour/disk_writer.cc b/libs/ardour/disk_writer.cc index be6763e088..f02217e046 100644 --- a/libs/ardour/disk_writer.cc +++ b/libs/ardour/disk_writer.cc @@ -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 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 diff --git a/libs/ardour/session_butler.cc b/libs/ardour/session_butler.cc index 259a3a1d3d..262444c435 100644 --- a/libs/ardour/session_butler.cc +++ b/libs/ardour/session_butler.cc @@ -76,10 +76,15 @@ Session::schedule_curve_reallocation () } void -Session::request_overwrite_buffer (Track* t) +Session::request_overwrite_buffer (boost::shared_ptr r) { + boost::shared_ptr t = boost::dynamic_pointer_cast (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); } diff --git a/libs/ardour/session_process.cc b/libs/ardour/session_process.cc index f74bfd2d73..a24123d959 100644 --- a/libs/ardour/session_process.cc +++ b/libs/ardour/session_process.cc @@ -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 (); } diff --git a/libs/ardour/track.cc b/libs/ardour/track.cc index fa1cba6000..41769ae471 100644 --- a/libs/ardour/track.cc +++ b/libs/ardour/track.cc @@ -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 Track::playlist () { - cerr << name() << " lookup " << data_type().to_string() << " pl's\n"; return _playlists[data_type()]; } -- cgit v1.2.3