summaryrefslogtreecommitdiff
path: root/libs/ardour/audio_diskstream.cc
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2015-01-28 13:43:17 -0500
committerPaul Davis <paul@linuxaudiosystems.com>2015-06-29 14:18:12 -0400
commit1caf54ee7f6754181037a6a05a5667acd0b3e9b1 (patch)
tree2c9f75d1acb8d0f718d3265ed005f890fcc1c450 /libs/ardour/audio_diskstream.cc
parent4644e113a86974ba29c5979b7285260bd3afdfcb (diff)
add initial support for vari-fill
When refilling playback buffer, try to fill it completely, or at least using the next-lowest power-of-2 as the amount to read. When locating, where we use do_refill_with_alloc(), only partially fill the buffer. Work not yet finished, but possibly promising.
Diffstat (limited to 'libs/ardour/audio_diskstream.cc')
-rw-r--r--libs/ardour/audio_diskstream.cc84
1 files changed, 61 insertions, 23 deletions
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;
}