summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
Diffstat (limited to 'libs')
-rw-r--r--libs/ardour/ardour/audio_diskstream.h8
-rw-r--r--libs/ardour/ardour/diskstream.h16
-rw-r--r--libs/ardour/ardour/midi_diskstream.h6
-rw-r--r--libs/ardour/audio_diskstream.cc84
-rw-r--r--libs/ardour/midi_diskstream.cc2
-rw-r--r--libs/ardour/session_transport.cc4
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)));
}