split apart read and write chunk size and offer platform-dependent sizes for reading...
authorPaul Davis <paul@linuxaudiosystems.com>
Thu, 22 Jan 2015 17:52:06 +0000 (12:52 -0500)
committerPaul Davis <paul@linuxaudiosystems.com>
Fri, 23 Jan 2015 17:25:49 +0000 (12:25 -0500)
libs/ardour/ardour/diskstream.h
libs/ardour/ardour/rc_configuration_vars.h
libs/ardour/audio_diskstream.cc
libs/ardour/diskstream.cc
libs/ardour/midi_diskstream.cc
libs/ardour/rc_configuration.cc
libs/ardour/srcfilesource.cc
system_config

index c960e925c81046ce651a6288f34b90a027bde117..cde21b209f66702d4a61a1eda868b33aa472cbea 100644 (file)
@@ -138,8 +138,12 @@ class LIBARDOUR_API Diskstream : public SessionObject, public PublicDiskstream
 
        ChanCount n_channels() { return _n_channels; }
 
-       static framecnt_t disk_io_frames() { return disk_io_chunk_frames; }
-       static void set_disk_io_chunk_frames (framecnt_t n) { disk_io_chunk_frames = n; }
+       static framecnt_t disk_read_frames() { return disk_read_chunk_frames; }
+       static framecnt_t disk_write_frames() { return disk_write_chunk_frames; }
+       static void set_disk_read_chunk_frames (framecnt_t n) { disk_read_chunk_frames = n; }
+       static void set_disk_write_chunk_frames (framecnt_t n) { disk_write_chunk_frames = n; }
+       static framecnt_t default_disk_read_chunk_frames ();
+       static framecnt_t default_disk_write_chunk_frames ();
 
        /* Stateful */
        virtual XMLNode& get_state(void);
@@ -268,7 +272,9 @@ class LIBARDOUR_API Diskstream : public SessionObject, public PublicDiskstream
                framecnt_t& rec_nframes, framecnt_t& rec_offset
                );
 
-       static framecnt_t disk_io_chunk_frames;
+       static framecnt_t disk_read_chunk_frames;
+       static framecnt_t disk_write_chunk_frames;
+
        std::vector<CaptureInfo*> capture_info;
        mutable Glib::Threads::Mutex capture_info_lock;
 
index 826175a60b0c3cfb1c8d2f90274a9084d5a23d83..1c5f9a82b83c7e37108cd495fe8d7f36e1f6d52c 100644 (file)
@@ -67,7 +67,8 @@ CONFIG_VARIABLE (RemoteModel, remote_model, "remote-model", MixerOrdered)
 
 /* disk operations */
 
-CONFIG_VARIABLE (uint32_t, minimum_disk_io_bytes,  "minimum-disk-io-bytes", 1024 * 256)
+CONFIG_VARIABLE (uint32_t, minimum_disk_read_bytes,  "minimum-disk-read-bytes", ARDOUR::Diskstream::default_disk_read_chunk_frames() * sizeof (ARDOUR::Sample))
+CONFIG_VARIABLE (uint32_t, minimum_disk_write_bytes,  "minimum-disk-write-bytes", ARDOUR::Diskstream::default_disk_write_chunk_frames() * sizeof (ARDOUR::Sample))
 CONFIG_VARIABLE (float, midi_readahead,  "midi-readahead", 1.0)
 CONFIG_VARIABLE (float, audio_capture_buffer_seconds, "capture-buffer-seconds", 5.0)
 CONFIG_VARIABLE (float, audio_playback_buffer_seconds, "playback-buffer-seconds", 5.0)
index b31e6abe9155ac71b71d30a549270102db5dd6d2..d835c4a20fa89d166758fe28ee5855022cf6444d 100644 (file)
@@ -128,9 +128,7 @@ AudioDiskstream::~AudioDiskstream ()
 void
 AudioDiskstream::allocate_working_buffers()
 {
-       assert(disk_io_frames() > 0);
-
-       _working_buffers_size = disk_io_frames();
+       _working_buffers_size = max (disk_write_chunk_frames, disk_read_chunk_frames);
        _mixdown_buffer       = new Sample[_working_buffers_size];
        _gain_buffer          = new gain_t[_working_buffers_size];
 }
@@ -786,10 +784,10 @@ AudioDiskstream::commit (framecnt_t playback_distance)
                }
        } else {
                if (_io && _io->active()) {
-                       need_butler = ((framecnt_t) c->front()->playback_buf->write_space() >= disk_io_chunk_frames)
-                               || ((framecnt_t) c->front()->capture_buf->read_space() >= disk_io_chunk_frames);
+                       need_butler = ((framecnt_t) c->front()->playback_buf->write_space() >= disk_read_chunk_frames)
+                               || ((framecnt_t) c->front()->capture_buf->read_space() >= disk_write_chunk_frames);
                } else {
-                       need_butler = ((framecnt_t) c->front()->capture_buf->read_space() >= disk_io_chunk_frames);
+                       need_butler = ((framecnt_t) c->front()->capture_buf->read_space() >= disk_write_chunk_frames);
                }
        }
 
@@ -1056,8 +1054,8 @@ AudioDiskstream::read (Sample* buf, Sample* mixdown_buffer, float* gain_buffer,
 int
 AudioDiskstream::do_refill_with_alloc ()
 {
-       Sample* mix_buf  = new Sample[disk_io_chunk_frames];
-       float*  gain_buf = new float[disk_io_chunk_frames];
+       Sample* mix_buf  = new Sample[disk_read_chunk_frames];
+       float*  gain_buf = new float[disk_read_chunk_frames];
 
        int ret = _do_refill(mix_buf, gain_buf);
 
@@ -1108,22 +1106,22 @@ AudioDiskstream::_do_refill (Sample* mixdown_buffer, float* gain_buffer)
           for us to be called again, ASAP.
        */
 
-       if (total_space >= (_slaved ? 3 : 2) * disk_io_chunk_frames) {
+       if (total_space >= (_slaved ? 3 : 2) * disk_read_chunk_frames) {
                ret = 1;
        }
 
        /* if we're running close to normal speed and there isn't enough
-          space to do disk_io_chunk_frames of I/O, then don't bother.
+          space to do disk_read_chunk_frames of I/O, then don't bother.
 
           at higher speeds, just do it because the sync between butler
           and audio thread may not be good enough.
 
-          Note: it is a design assumption that disk_io_chunk_frames is smaller
+          Note: it is a design assumption that disk_read_chunk_frames is smaller
           than the playback buffer size, so this check should never trip when
           the playback buffer is empty.
        */
 
-       if ((total_space < disk_io_chunk_frames) && fabs (_actual_speed) < 2.0f) {
+       if ((total_space < disk_read_chunk_frames) && fabs (_actual_speed) < 2.0f) {
                return 0;
        }
 
@@ -1136,9 +1134,9 @@ AudioDiskstream::_do_refill (Sample* mixdown_buffer, float* gain_buffer)
                return 0;
        }
 
-       /* never do more than disk_io_chunk_frames worth of disk input per call (limit doesn't apply for memset) */
+       /* never do more than disk_read_chunk_frames worth of disk input per call (limit doesn't apply for memset) */
 
-       total_space = min (disk_io_chunk_frames, total_space);
+       total_space = min (disk_read_chunk_frames, total_space);
 
        if (reversed) {
 
@@ -1215,14 +1213,14 @@ AudioDiskstream::_do_refill (Sample* mixdown_buffer, float* gain_buffer)
 
                chan->playback_buf->get_write_vector (&vector);
 
-               if ((framecnt_t) vector.len[0] > disk_io_chunk_frames) {
+               if ((framecnt_t) vector.len[0] > disk_read_chunk_frames) {
 
                        /* 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:
 
                           .... => writable space
                           ++++ => readable space
-                          ^^^^ => 1 x disk_io_chunk_frames that would be filled
+                          ^^^^ => 1 x disk_read_chunk_frames that would be filled
 
                           |......|+++++++++++++|...............................|
                           buf1                buf0
@@ -1247,7 +1245,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_io_chunk_frames);
+               to_read = min (to_read, disk_read_chunk_frames);
 
                assert (to_read >= 0);
 
@@ -1266,7 +1264,7 @@ 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_io_chunk_frames of data,
+                       /* 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.
                        */
 
@@ -1294,12 +1292,12 @@ AudioDiskstream::_do_refill (Sample* mixdown_buffer, float* gain_buffer)
 
 /** Flush pending data to disk.
  *
- * Important note: this function will write *AT MOST* disk_io_chunk_frames
+ * Important note: this function will write *AT MOST* disk_write_chunk_frames
  * of data to disk. it will never write more than that.  If it writes that
  * much and there is more than that waiting to be written, it will return 1,
  * otherwise 0 on success or -1 on failure.
  *
- * If there is less than disk_io_chunk_frames to be written, no data will be
+ * If there is less than disk_write_chunk_frames to be written, no data will be
  * written at all unless @a force_flush is true.
  */
 int
@@ -1323,7 +1321,7 @@ AudioDiskstream::do_flush (RunContext /*context*/, bool force_flush)
 
                total = vector.len[0] + vector.len[1];
 
-               if (total == 0 || (total < disk_io_chunk_frames && !force_flush && was_recording)) {
+               if (total == 0 || (total < disk_write_chunk_frames && !force_flush && was_recording)) {
                        goto out;
                }
 
@@ -1338,11 +1336,11 @@ AudioDiskstream::do_flush (RunContext /*context*/, bool force_flush)
                   let the caller know too.
                */
 
-               if (total >= 2 * disk_io_chunk_frames || ((force_flush || !was_recording) && total > disk_io_chunk_frames)) {
+               if (total >= 2 * disk_write_chunk_frames || ((force_flush || !was_recording) && total > disk_write_chunk_frames)) {
                        ret = 1;
                }
 
-               to_write = min (disk_io_chunk_frames, (framecnt_t) vector.len[0]);
+               to_write = min (disk_write_chunk_frames, (framecnt_t) vector.len[0]);
 
                // check the transition buffer when recording destructive
                // important that we get this after the capture buf
@@ -1402,14 +1400,14 @@ AudioDiskstream::do_flush (RunContext /*context*/, bool force_flush)
                (*chan)->capture_buf->increment_read_ptr (to_write);
                (*chan)->curr_capture_cnt += to_write;
 
-               if ((to_write == vector.len[0]) && (total > to_write) && (to_write < disk_io_chunk_frames) && !destructive()) {
+               if ((to_write == vector.len[0]) && (total > to_write) && (to_write < disk_write_chunk_frames) && !destructive()) {
 
                        /* we wrote all of vector.len[0] but it wasn't an entire
-                          disk_io_chunk_frames of data, so arrange for some part
+                          disk_write_chunk_frames of data, so arrange for some part
                           of vector.len[1] to be flushed to disk as well.
                        */
 
-                       to_write = min ((framecnt_t)(disk_io_chunk_frames - to_write), (framecnt_t) vector.len[1]);
+                       to_write = min ((framecnt_t)(disk_write_chunk_frames - to_write), (framecnt_t) vector.len[1]);
 
                         DEBUG_TRACE (DEBUG::Butler, string_compose ("%1 additional write of %2\n", name(), to_write));
 
index 427063c3a2ee2f9d83bc6058baeb5c774ac8a5b0..0e4b5fcc496ad27f1e8fad9e7bb12e6fb0104ac2 100644 (file)
@@ -53,12 +53,8 @@ using namespace std;
 using namespace ARDOUR;
 using namespace PBD;
 
-/* XXX This goes uninitialized when there is no ~/.config/ardour3 directory.
- * I can't figure out why, so this will do for now (just stole the
- * default from configuration_vars.h).  0 is not a good value for
- * allocating buffer sizes..
- */
-ARDOUR::framecnt_t Diskstream::disk_io_chunk_frames = 1024 * 256 / sizeof (Sample);
+ARDOUR::framecnt_t Diskstream::disk_read_chunk_frames = default_disk_read_chunk_frames ();
+ARDOUR::framecnt_t Diskstream::disk_write_chunk_frames = default_disk_write_chunk_frames ();
 
 PBD::Signal0<void>                Diskstream::DiskOverrun;
 PBD::Signal0<void>                Diskstream::DiskUnderrun;
@@ -772,3 +768,21 @@ Diskstream::disengage_record_enable ()
 {
        g_atomic_int_set (&_record_enabled, 0);
 }
+
+framecnt_t
+Diskstream::default_disk_read_chunk_frames()
+{
+#ifdef PLATFORM_WINDOWS
+       return (2 * 1048576) / sizeof (Sample);
+#elif defined __APPLE__
+       return (4 * 1048576) / sizeof (Sample);
+#else
+       return 65536;
+#endif
+}      
+
+framecnt_t
+Diskstream::default_disk_write_chunk_frames ()
+{
+       return 65536;
+}
index e1c29fa7086af43d66c53e3f21094f434dea84db..3e04876eb4de41007c92e52ab31360a1b0bdfc46 100644 (file)
@@ -620,7 +620,7 @@ MidiDiskstream::overwrite_existing_buffers ()
           having the old data or knowing what change caused the overwrite. */
        midi_playlist()->resolve_note_trackers (*_playback_buf, overwrite_frame);
 
-       read (overwrite_frame, disk_io_chunk_frames, false);
+       read (overwrite_frame, disk_read_chunk_frames, false);
        file_frame = overwrite_frame; // it was adjusted by ::read()
        overwrite_queued = false;
        _pending_overwrite = false;
@@ -810,12 +810,12 @@ MidiDiskstream::do_refill ()
 
 /** Flush pending data to disk.
  *
- * Important note: this function will write *AT MOST* disk_io_chunk_frames
+ * Important note: this function will write *AT MOST* disk_write_chunk_frames
  * of data to disk. it will never write more than that.  If it writes that
  * much and there is more than that waiting to be written, it will return 1,
  * otherwise 0 on success or -1 on failure.
  *
- * If there is less than disk_io_chunk_frames to be written, no data will be
+ * If there is less than disk_write_chunk_frames to be written, no data will be
  * written at all unless @a force_flush is true.
  */
 int
@@ -832,7 +832,7 @@ MidiDiskstream::do_flush (RunContext /*context*/, bool force_flush)
 
        if (total == 0 || 
            _capture_buf->read_space() == 0 || 
-           (!force_flush && (total < disk_io_chunk_frames) && was_recording)) {
+           (!force_flush && (total < disk_write_chunk_frames) && was_recording)) {
                goto out;
        }
 
@@ -847,7 +847,7 @@ MidiDiskstream::do_flush (RunContext /*context*/, bool force_flush)
           let the caller know too.
           */
 
-       if (total >= 2 * disk_io_chunk_frames || ((force_flush || !was_recording) && total > disk_io_chunk_frames)) {
+       if (total >= 2 * disk_write_chunk_frames || ((force_flush || !was_recording) && total > disk_write_chunk_frames)) {
                ret = 1;
        }
 
@@ -855,10 +855,10 @@ MidiDiskstream::do_flush (RunContext /*context*/, bool force_flush)
                /* push out everything we have, right now */
                to_write = max_framecnt;
        } else {
-               to_write = disk_io_chunk_frames;
+               to_write = disk_write_chunk_frames;
        }
 
-       if (record_enabled() && ((total > disk_io_chunk_frames) || force_flush)) {
+       if (record_enabled() && ((total > disk_write_chunk_frames) || force_flush)) {
                Source::Lock lm(_write_source->mutex());
                if (_write_source->midi_write (lm, *_capture_buf, get_capture_start_frame (0), to_write) != to_write) {
                        error << string_compose(_("MidiDiskstream %1: cannot write to disk"), id()) << endmsg;
index 840b8f6883cf6a594e81caae9eb3c6f15bff1b17..9fdd6aa1ad606639f900c0b20920d9c8f0719a6b 100644 (file)
@@ -235,7 +235,8 @@ RCConfiguration::set_state (const XMLNode& root, int version)
                }
        }
 
-       Diskstream::set_disk_io_chunk_frames (minimum_disk_io_bytes.get() / sizeof (Sample));
+       Diskstream::set_disk_read_chunk_frames (minimum_disk_read_bytes.get() / sizeof (Sample));
+       Diskstream::set_disk_write_chunk_frames (minimum_disk_write_bytes.get() / sizeof (Sample));
 
        return 0;
 }
@@ -270,3 +271,4 @@ RCConfiguration::map_parameters (boost::function<void (std::string)>& functor)
 #undef  CONFIG_VARIABLE
 #undef  CONFIG_VARIABLE_SPECIAL
 }
+
index 6af4aaa9d815fb1567f731402472810948229b1c..e54afbfaba738e64c50381109d7a9998bf639a67 100644 (file)
@@ -30,8 +30,7 @@
 using namespace ARDOUR;
 using namespace PBD;
 
-/* see disk_io_chunk_frames */
-const uint32_t SrcFileSource::blocksize = 65536U;
+const uint32_t SrcFileSource::blocksize = 65536U; /* somewhat arbitrary */
 
 SrcFileSource::SrcFileSource (Session& s, boost::shared_ptr<AudioFileSource> src, SrcQuality srcq)
        : Source(s, DataType::AUDIO, src->name(), Flag (src->flags() & ~(Writable|Removable|RemovableIfEmpty|RemoveAtDestroy)))
index 4a968428f36101372beea7b97bbf2c44c7646328..1260a700931849a061432219ad8c88feedb866b5 100644 (file)
@@ -2,7 +2,6 @@
 <Ardour>
   <MIDI-port tag="@MIDITAG@" device="ardour" type="@MIDITYPE@" mode="duplex"/>
   <Config>
-    <Option name="minimum-disk-io-bytes" value="262144"/>
     <Option name="track-buffer-seconds" value="5.000000"/>
     <Option name="mute-affects-pre-fader" value="1"/>
     <Option name="mute-affects-post-fader" value="1"/>