diff options
Diffstat (limited to 'libs')
-rw-r--r-- | libs/ardour/ardour/audio_diskstream.h | 8 | ||||
-rw-r--r-- | libs/ardour/ardour/diskstream.h | 16 | ||||
-rw-r--r-- | libs/ardour/ardour/midi_diskstream.h | 6 | ||||
-rw-r--r-- | libs/ardour/audio_diskstream.cc | 84 | ||||
-rw-r--r-- | libs/ardour/midi_diskstream.cc | 2 | ||||
-rw-r--r-- | libs/ardour/session_transport.cc | 4 |
6 files changed, 85 insertions, 35 deletions
diff --git a/libs/ardour/ardour/audio_diskstream.h b/libs/ardour/ardour/audio_diskstream.h index f48204d7ab..9eb94b9573 100644 --- a/libs/ardour/ardour/audio_diskstream.h +++ b/libs/ardour/ardour/audio_diskstream.h @@ -209,9 +209,8 @@ class LIBARDOUR_API AudioDiskstream : public Diskstream /* The two central butler operations */ int do_flush (RunContext context, bool force = false); - int do_refill () { return _do_refill(_mixdown_buffer, _gain_buffer); } + int do_refill () { return _do_refill(_mixdown_buffer, _gain_buffer, 0); } - int do_refill_with_alloc (); int read (Sample* buf, Sample* mixdown_buffer, float* gain_buffer, framepos_t& start, framecnt_t cnt, @@ -258,9 +257,12 @@ class LIBARDOUR_API AudioDiskstream : public Diskstream SerializedRCUManager<ChannelList> channels; + protected: + int _do_refill_with_alloc (bool one_chunk_only); + /* really */ private: - int _do_refill (Sample *mixdown_buffer, float *gain_buffer); + int _do_refill (Sample *mixdown_buffer, float *gain_buffer, framecnt_t fill_level); int add_channel_to (boost::shared_ptr<ChannelList>, uint32_t how_many); int remove_channel_from (boost::shared_ptr<ChannelList>, uint32_t how_many); diff --git a/libs/ardour/ardour/diskstream.h b/libs/ardour/ardour/diskstream.h index 0e82459981..a298e3f2c8 100644 --- a/libs/ardour/ardour/diskstream.h +++ b/libs/ardour/ardour/diskstream.h @@ -171,8 +171,15 @@ class LIBARDOUR_API Diskstream : public SessionObject, public PublicDiskstream void move_processor_automation (boost::weak_ptr<Processor>, std::list<Evoral::RangeMove<framepos_t> > const &); - /** For non-butler contexts (allocates temporary working buffers) */ - virtual int do_refill_with_alloc() = 0; + /** For non-butler contexts (allocates temporary working buffers) + * + * This accessible method has a default argument; derived classes + * must inherit the virtual method that we call which does NOT + * have a default argument, to avoid complications with inheritance + */ + int do_refill_with_alloc(bool partial_fill = true) { + return _do_refill_with_alloc (partial_fill); + } virtual void set_block_size (pframes_t) = 0; bool pending_overwrite () const { @@ -205,6 +212,11 @@ class LIBARDOUR_API Diskstream : public SessionObject, public PublicDiskstream virtual int can_internal_playback_seek (framecnt_t distance) = 0; virtual void reset_write_sources (bool, bool force = false) = 0; virtual void non_realtime_input_change () = 0; + /* accessible method has default argument, so use standard C++ "trick" + to avoid complications with inheritance, by adding this virtual + method which does NOT have a default argument. + */ + virtual int _do_refill_with_alloc (bool partial_fill) = 0; protected: friend class Auditioner; diff --git a/libs/ardour/ardour/midi_diskstream.h b/libs/ardour/ardour/midi_diskstream.h index 6610708581..dac262e269 100644 --- a/libs/ardour/ardour/midi_diskstream.h +++ b/libs/ardour/ardour/midi_diskstream.h @@ -128,10 +128,10 @@ class LIBARDOUR_API MidiDiskstream : public Diskstream protected: friend class MidiTrack; friend class Auditioner; - int seek (framepos_t which_sample, bool complete_refill = false); + int seek (framepos_t which_sample, bool complete_refill = false); + int _do_refill_with_alloc (bool one_chunk_only); int process (BufferSet&, framepos_t transport_frame, pframes_t nframes, framecnt_t &, bool need_diskstream); - frameoffset_t calculate_playback_distance (pframes_t nframes); bool commit (framecnt_t nframes); @@ -143,8 +143,6 @@ class LIBARDOUR_API MidiDiskstream : public Diskstream int do_flush (RunContext context, bool force = false); int do_refill (); - int do_refill_with_alloc(); - int read (framepos_t& start, framecnt_t cnt, bool reversed); void finish_capture (); diff --git a/libs/ardour/audio_diskstream.cc b/libs/ardour/audio_diskstream.cc index 7a30e191d5..d36d533e31 100644 --- a/libs/ardour/audio_diskstream.cc +++ b/libs/ardour/audio_diskstream.cc @@ -924,9 +924,15 @@ AudioDiskstream::seek (framepos_t frame, bool complete_refill) file_frame = frame; if (complete_refill) { - while ((ret = do_refill_with_alloc ()) > 0) ; + /* call _do_refill() to refill the entire buffer, using + the largest reads possible. + */ + while ((ret = do_refill_with_alloc (false)) > 0) ; } else { - ret = do_refill_with_alloc (); + /* call _do_refill() to refill just one chunk, and then + return. + */ + ret = do_refill_with_alloc (true); } return ret; @@ -1068,12 +1074,13 @@ AudioDiskstream::read (Sample* buf, Sample* mixdown_buffer, float* gain_buffer, } int -AudioDiskstream::do_refill_with_alloc () +AudioDiskstream::_do_refill_with_alloc (bool partial_fill) { - Sample* mix_buf = new Sample[disk_read_chunk_frames]; - float* gain_buf = new float[disk_read_chunk_frames]; + Sample* mix_buf = new Sample[1048576]; + float* gain_buf = new float[1048576]; - int ret = _do_refill(mix_buf, gain_buf); + int ret = _do_refill (mix_buf, gain_buf, (partial_fill ? + (_session.butler()->audio_diskstream_playback_buffer_size() / 4.0) : 0)); delete [] mix_buf; delete [] gain_buf; @@ -1083,9 +1090,15 @@ AudioDiskstream::do_refill_with_alloc () /** Get some more data from disk and put it in our channels' playback_bufs, * if there is suitable space in them. + * + * If fill_level is non-zero, then we will refill the buffer so that there is + * still at least fill_level samples of space left to be filled. This is used + * after locates so that we do not need to wait to fill the entire buffer. + * */ + int -AudioDiskstream::_do_refill (Sample* mixdown_buffer, float* gain_buffer) +AudioDiskstream::_do_refill (Sample* mixdown_buffer, float* gain_buffer, framecnt_t fill_level) { int32_t ret = 0; framecnt_t to_read; @@ -1117,13 +1130,12 @@ AudioDiskstream::_do_refill (Sample* mixdown_buffer, float* gain_buffer) return 0; } - /* if there are 2+ chunks of disk i/o possible for - this track, let the caller know so that it can arrange - for us to be called again, ASAP. - */ - - if (total_space >= (_slaved ? 3 : 2) * disk_read_chunk_frames) { - ret = 1; + if (fill_level && (fill_level < total_space)) { + cerr << name() << " adjust total space of " << total_space << " to leave " << fill_level << " to still refill\n"; + if (fill_level < 0) { + PBD::stacktrace (cerr, 20); + } + total_space -= fill_level; } /* if we're running close to normal speed and there isn't enough @@ -1150,10 +1162,6 @@ AudioDiskstream::_do_refill (Sample* mixdown_buffer, float* gain_buffer) return 0; } - /* never do more than disk_read_chunk_frames worth of disk input per call (limit doesn't apply for memset) */ - - total_space = min (disk_read_chunk_frames, total_space); - if (reversed) { if (file_frame == 0) { @@ -1220,6 +1228,34 @@ AudioDiskstream::_do_refill (Sample* mixdown_buffer, float* gain_buffer) framepos_t file_frame_tmp = 0; + /* this needs to be 32 bit for the power-of-two hack below to work. + Clever, but poses ugly casting problems since the value is + semantically a framecnt_t. + */ + + uint32_t chunk_size_for_read = (uint32_t) max ((framecnt_t) 65536, min ((framecnt_t) 1048576, total_space)); + + /* if not already a power of 2, go to next lower power of 2 */ + + if ((chunk_size_for_read & (chunk_size_for_read - 1)) != 0) { + + /* move to the next largest power of two. Hack from stanford bithacks page. */ + + chunk_size_for_read--; + chunk_size_for_read |= chunk_size_for_read >> 1; + chunk_size_for_read |= chunk_size_for_read >> 2; + chunk_size_for_read |= chunk_size_for_read >> 4; + chunk_size_for_read |= chunk_size_for_read >> 8; + chunk_size_for_read |= chunk_size_for_read >> 16; + chunk_size_for_read++; + + /* go back to previous power */ + + chunk_size_for_read >>= 1; + } + + cerr << name() << " will read " << chunk_size_for_read << " out of total space " << total_space << " in buffer of " << c->front()->playback_buf->bufsize() << endl; + for (chan_n = 0, i = c->begin(); i != c->end(); ++i, ++chan_n) { ChannelInfo* chan (*i); @@ -1229,7 +1265,7 @@ AudioDiskstream::_do_refill (Sample* mixdown_buffer, float* gain_buffer) chan->playback_buf->get_write_vector (&vector); - if ((framecnt_t) vector.len[0] > disk_read_chunk_frames) { + if ((framecnt_t) vector.len[0] > chunk_size_for_read) { /* we're not going to fill the first chunk, so certainly do not bother with the other part. it won't be connected with the part we do fill, as in: @@ -1261,7 +1297,7 @@ AudioDiskstream::_do_refill (Sample* mixdown_buffer, float* gain_buffer) len2 = vector.len[1]; to_read = min (ts, len1); - to_read = min (to_read, disk_read_chunk_frames); + to_read = min (to_read, (framecnt_t) chunk_size_for_read); assert (to_read >= 0); @@ -1280,8 +1316,9 @@ AudioDiskstream::_do_refill (Sample* mixdown_buffer, float* gain_buffer) if (to_read) { - /* we read all of vector.len[0], but it wasn't an entire disk_read_chunk_frames of data, - so read some or all of vector.len[1] as well. + /* we read all of vector.len[0], but it wasn't the + entire chunk_size_for_read of data, so read some or + all of vector.len[1] as well. */ if (read (buf2, mixdown_buffer, gain_buffer, file_frame_tmp, to_read, chan_n, reversed)) { @@ -1301,8 +1338,9 @@ AudioDiskstream::_do_refill (Sample* mixdown_buffer, float* gain_buffer) file_frame = file_frame_tmp; assert (file_frame >= 0); + ret = ((total_space - chunk_size_for_read) > disk_read_chunk_frames); + out: - return ret; } diff --git a/libs/ardour/midi_diskstream.cc b/libs/ardour/midi_diskstream.cc index a2a80f780b..229c0ad768 100644 --- a/libs/ardour/midi_diskstream.cc +++ b/libs/ardour/midi_diskstream.cc @@ -784,7 +784,7 @@ MidiDiskstream::read (framepos_t& start, framecnt_t dur, bool reversed) } int -MidiDiskstream::do_refill_with_alloc () +MidiDiskstream::_do_refill_with_alloc (bool /* partial_fill */) { return do_refill(); } diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc index 97e6eb7d5b..711c3e51e7 100644 --- a/libs/ardour/session_transport.cc +++ b/libs/ardour/session_transport.cc @@ -319,7 +319,7 @@ Session::butler_transport_work () finished = true; ptw = post_transport_work(); - DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler transport work, todo = %1\n", enum_2_string (ptw))); + DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler transport work, todo = %1 at %2\n", enum_2_string (ptw), g_get_monotonic_time())); if (ptw & PostTransportAdjustPlaybackBuffering) { for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { @@ -410,7 +410,7 @@ Session::butler_transport_work () g_atomic_int_dec_and_test (&_butler->should_do_transport_work); - DEBUG_TRACE (DEBUG::Transport, X_("Butler transport work all done\n")); + DEBUG_TRACE (DEBUG::Transport, string_compose (X_("Butler transport work all done at %1\n"), g_get_monotonic_time())); DEBUG_TRACE (DEBUG::Transport, X_(string_compose ("Frame %1\n", _transport_frame))); } |