2 Copyright (C) 2009-2016 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include "pbd/memento_command.h"
23 #include "ardour/audioplaylist.h"
24 #include "ardour/audio_buffer.h"
25 #include "ardour/butler.h"
26 #include "ardour/debug.h"
27 #include "ardour/disk_reader.h"
28 #include "ardour/playlist.h"
29 #include "ardour/playlist_factory.h"
30 #include "ardour/session.h"
31 #include "ardour/session_playlists.h"
33 using namespace ARDOUR;
37 ARDOUR::framecnt_t DiskReader::_chunk_frames = default_chunk_frames ();
39 DiskReader::DiskReader (Session& s, string const & str, DiskIOProcessor::Flag f)
40 : DiskIOProcessor (s, str, f)
43 , overwrite_offset (0)
44 , _pending_overwrite (false)
45 , overwrite_queued (false)
48 , _monitoring_choice (MonitorDisk)
49 , channels (new ChannelList)
53 DiskReader::~DiskReader ()
55 DEBUG_TRACE (DEBUG::Destruction, string_compose ("DiskReader %1 deleted\n", _name));
58 _playlist->release ();
62 RCUWriter<ChannelList> writer (channels);
63 boost::shared_ptr<ChannelList> c = writer.get_copy();
65 for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) {
76 DiskReader::allocate_working_buffers()
78 /* with varifill buffer refilling, we compute the read size in bytes (to optimize
79 for disk i/o bandwidth) and then convert back into samples. These buffers
80 need to reflect the maximum size we could use, which is 4MB reads, or 2M samples
83 _mixdown_buffer = new Sample[2*1048576];
84 _gain_buffer = new gain_t[2*1048576];
88 DiskReader::free_working_buffers()
90 delete [] _mixdown_buffer;
91 delete [] _gain_buffer;
97 DiskReader::default_chunk_frames()
103 DiskReader::set_name (string const & str)
107 _playlist->set_name (str);
108 SessionObject::set_name(str);
115 DiskReader::set_roll_delay (ARDOUR::framecnt_t nframes)
117 _roll_delay = nframes;
121 DiskReader::set_state (const XMLNode& node, int version)
123 XMLProperty const * prop;
125 if (DiskIOProcessor::set_state (node, version)) {
129 if ((prop = node.property ("playlist")) == 0) {
133 if (find_and_use_playlist (prop->value())) {
140 /* Processor interface */
143 DiskReader::configure_io (ChanCount in, ChanCount out)
149 DiskReader::can_support_io_configuration (const ChanCount& in, ChanCount& out)
155 DiskReader::realtime_handle_transport_stopped ()
160 DiskReader::realtime_locate ()
165 DiskReader::add_channel_to (boost::shared_ptr<ChannelList> c, uint32_t how_many)
168 c->push_back (new ChannelInfo(
169 _session.butler()->audio_diskstream_playback_buffer_size(),
170 speed_buffer_size, wrap_buffer_size));
171 interpolation.add_channel_to (
172 _session.butler()->audio_diskstream_playback_buffer_size(),
176 _n_channels.set (DataType::AUDIO, c->size());
182 DiskReader::add_channel (uint32_t how_many)
184 RCUWriter<ChannelList> writer (channels);
185 boost::shared_ptr<ChannelList> c = writer.get_copy();
187 return add_channel_to (c, how_many);
191 DiskReader::remove_channel_from (boost::shared_ptr<ChannelList> c, uint32_t how_many)
193 while (how_many-- && !c->empty()) {
196 interpolation.remove_channel_from ();
199 _n_channels.set(DataType::AUDIO, c->size());
205 DiskReader::remove_channel (uint32_t how_many)
207 RCUWriter<ChannelList> writer (channels);
208 boost::shared_ptr<ChannelList> c = writer.get_copy();
210 return remove_channel_from (c, how_many);
214 DiskReader::buffer_load () const
216 boost::shared_ptr<ChannelList> c = channels.reader();
222 return (float) ((double) c->front()->buf->read_space()/
223 (double) c->front()->buf->bufsize());
227 DiskReader::adjust_buffering ()
229 boost::shared_ptr<ChannelList> c = channels.reader();
231 for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) {
232 (*chan)->resize (_session.butler()->audio_diskstream_playback_buffer_size());
236 DiskReader::ChannelInfo::ChannelInfo (framecnt_t bufsize, framecnt_t speed_size, framecnt_t wrap_size)
240 speed_buffer = new Sample[speed_size];
241 wrap_buffer = new Sample[wrap_size];
243 buf = new RingBufferNPT<Sample> (bufsize);
245 /* touch the ringbuffer buffer, which will cause
246 them to be mapped into locked physical RAM if
247 we're running with mlockall(). this doesn't do
251 memset (buf->buffer(), 0, sizeof (Sample) * buf->bufsize());
255 DiskReader::ChannelInfo::resize (framecnt_t bufsize)
258 buf = new RingBufferNPT<Sample> (bufsize);
259 memset (buf->buffer(), 0, sizeof (Sample) * buf->bufsize());
262 DiskReader::ChannelInfo::~ChannelInfo ()
264 delete [] speed_buffer;
267 delete [] wrap_buffer;
275 DiskReader::set_block_size (pframes_t /*nframes*/)
277 if (_session.get_block_size() > speed_buffer_size) {
278 speed_buffer_size = _session.get_block_size();
279 boost::shared_ptr<ChannelList> c = channels.reader();
281 for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) {
282 delete [] (*chan)->speed_buffer;
283 (*chan)->speed_buffer = new Sample[speed_buffer_size];
286 allocate_temporary_buffers ();
291 DiskReader::allocate_temporary_buffers ()
293 /* make sure the wrap buffer is at least large enough to deal
294 with the speeds up to 1.2, to allow for micro-variation
295 when slaving to MTC, Timecode etc.
298 double const sp = max (fabs (_actual_speed), 1.2);
299 framecnt_t required_wrap_size = (framecnt_t) ceil (_session.get_block_size() * sp) + 2;
301 if (required_wrap_size > wrap_buffer_size) {
303 boost::shared_ptr<ChannelList> c = channels.reader();
305 for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) {
306 if ((*chan)->wrap_buffer) {
307 delete [] (*chan)->wrap_buffer;
309 (*chan)->wrap_buffer = new Sample[required_wrap_size];
312 wrap_buffer_size = required_wrap_size;
318 DiskReader::playlist_changed (const PropertyChange&)
320 playlist_modified ();
324 DiskReader::playlist_modified ()
326 if (!i_am_the_modifier && !overwrite_queued) {
327 // !!!! _session.request_overwrite_buffer (this);
328 overwrite_queued = true;
333 DiskReader::playlist_deleted (boost::weak_ptr<Playlist> wpl)
335 boost::shared_ptr<Playlist> pl (wpl.lock());
337 if (pl == _playlist) {
339 /* this catches an ordering issue with session destruction. playlists
340 are destroyed before disk readers. we have to invalidate any handles
341 we have to the playlist.
351 DiskReader::use_playlist (boost::shared_ptr<Playlist> playlist)
357 bool prior_playlist = false;
360 Glib::Threads::Mutex::Lock lm (state_lock);
362 if (playlist == _playlist) {
366 playlist_connections.drop_connections ();
369 _playlist->release();
370 prior_playlist = true;
373 _playlist = playlist;
376 _playlist->ContentsChanged.connect_same_thread (playlist_connections, boost::bind (&DiskReader::playlist_modified, this));
377 _playlist->LayeringChanged.connect_same_thread (playlist_connections, boost::bind (&DiskReader::playlist_modified, this));
378 _playlist->DropReferences.connect_same_thread (playlist_connections, boost::bind (&DiskReader::playlist_deleted, this, boost::weak_ptr<Playlist>(_playlist)));
379 _playlist->RangesMoved.connect_same_thread (playlist_connections, boost::bind (&DiskReader::playlist_ranges_moved, this, _1, _2));
382 /* don't do this if we've already asked for it *or* if we are setting up
383 the diskstream for the very first time - the input changed handling will
384 take care of the buffer refill.
387 if (!overwrite_queued && prior_playlist) {
388 // !!! _session.request_overwrite_buffer (this);
389 overwrite_queued = true;
392 PlaylistChanged (); /* EMIT SIGNAL */
393 _session.set_dirty ();
399 DiskReader::find_and_use_playlist (const string& name)
401 boost::shared_ptr<AudioPlaylist> playlist;
403 if ((playlist = boost::dynamic_pointer_cast<AudioPlaylist> (_session.playlists->by_name (name))) == 0) {
404 playlist = boost::dynamic_pointer_cast<AudioPlaylist> (PlaylistFactory::create (DataType::AUDIO, _session, name));
408 error << string_compose(_("DiskReader: Playlist \"%1\" isn't an audio playlist"), name) << endmsg;
412 return use_playlist (playlist);
416 DiskReader::use_new_playlist ()
419 boost::shared_ptr<AudioPlaylist> playlist;
422 newname = Playlist::bump_name (_playlist->name(), _session);
424 newname = Playlist::bump_name (_name, _session);
427 if ((playlist = boost::dynamic_pointer_cast<AudioPlaylist> (PlaylistFactory::create (DataType::AUDIO, _session, newname, hidden()))) != 0) {
429 return use_playlist (playlist);
437 DiskReader::use_copy_playlist ()
439 assert(audio_playlist());
441 if (_playlist == 0) {
442 error << string_compose(_("DiskReader %1: there is no existing playlist to make a copy of!"), _name) << endmsg;
447 boost::shared_ptr<AudioPlaylist> playlist;
449 newname = Playlist::bump_name (_playlist->name(), _session);
451 if ((playlist = boost::dynamic_pointer_cast<AudioPlaylist>(PlaylistFactory::create (audio_playlist(), newname))) != 0) {
452 playlist->reset_shares();
453 return use_playlist (playlist);
460 /** Do some record stuff [not described in this comment!]
463 * - Setup playback_distance with the nframes, or nframes adjusted
464 * for current varispeed, if appropriate.
465 * - Setup current_buffer in each ChannelInfo to point to data
466 * that someone can read playback_distance worth of data from.
469 DiskReader::run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame,
470 double speed, pframes_t nframes, bool result_required)
473 DiskReader::process (BufferSet& bufs, framepos_t transport_frame, pframes_t nframes,
474 framecnt_t& playback_distance, bool need_disk_signal)
478 boost::shared_ptr<ChannelList> c = channels.reader();
479 ChannelList::iterator chan;
480 framecnt_t playback_distance = 0;
482 Glib::Threads::Mutex::Lock sm (state_lock, Glib::Threads::TRY_LOCK);
488 for (chan = c->begin(); chan != c->end(); ++chan) {
489 (*chan)->current_buffer = 0;
492 if (result_required || _monitoring_choice == MonitorDisk || _monitoring_choice == MonitorCue) {
494 /* we're doing playback */
496 framecnt_t necessary_samples;
498 if (_actual_speed != 1.0) {
499 necessary_samples = (framecnt_t) ceil ((nframes * fabs (_actual_speed))) + 2;
501 necessary_samples = nframes;
504 for (chan = c->begin(); chan != c->end(); ++chan) {
505 (*chan)->buf->get_read_vector (&(*chan)->read_vector);
510 /* Setup current_buffer in each ChannelInfo to point to data that someone
511 can read necessary_samples (== nframes at a transport speed of 1) worth of data
515 for (chan = c->begin(); chan != c->end(); ++chan, ++n) {
517 ChannelInfo* chaninfo (*chan);
519 if (necessary_samples <= (framecnt_t) chaninfo->read_vector.len[0]) {
520 /* There are enough samples in the first part of the ringbuffer */
521 chaninfo->current_buffer = chaninfo->read_vector.buf[0];
524 framecnt_t total = chaninfo->read_vector.len[0] + chaninfo->read_vector.len[1];
526 if (necessary_samples > total) {
527 cerr << _name << " Need " << necessary_samples << " total = " << total << endl;
528 cerr << "underrun for " << _name << endl;
529 DEBUG_TRACE (DEBUG::Butler, string_compose ("%1 underrun in %2, total space = %3\n",
530 DEBUG_THREAD_SELF, name(), total));
536 /* We have enough samples, but not in one lump. Coalesce the two parts
537 into one in wrap_buffer in our ChannelInfo, and specify that
538 as our current_buffer.
541 assert(wrap_buffer_size >= necessary_samples);
543 /* Copy buf[0] from buf */
544 memcpy ((char *) chaninfo->wrap_buffer,
545 chaninfo->read_vector.buf[0],
546 chaninfo->read_vector.len[0] * sizeof (Sample));
548 /* Copy buf[1] from buf */
549 memcpy (chaninfo->wrap_buffer + chaninfo->read_vector.len[0],
550 chaninfo->read_vector.buf[1],
551 (necessary_samples - chaninfo->read_vector.len[0])
554 chaninfo->current_buffer = chaninfo->wrap_buffer;
559 if (_actual_speed != 1.0f && _actual_speed != -1.0f) {
561 interpolation.set_speed (_target_speed);
564 for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan, ++channel) {
565 ChannelInfo* chaninfo (*chan);
567 playback_distance = interpolation.interpolate (
568 channel, nframes, chaninfo->current_buffer, chaninfo->speed_buffer);
570 chaninfo->current_buffer = chaninfo->speed_buffer;
574 playback_distance = nframes;
577 _speed = _target_speed;
580 if (result_required || _monitoring_choice == MonitorDisk || _monitoring_choice == MonitorCue) {
582 /* copy data over to buffer set */
584 size_t n_buffers = bufs.count().n_audio();
585 size_t n_chans = c->size();
586 gain_t scaling = 1.0f;
588 if (n_chans > n_buffers) {
589 scaling = ((float) n_buffers)/n_chans;
592 for (n = 0, chan = c->begin(); chan != c->end(); ++chan, ++n) {
594 AudioBuffer& buf (bufs.get_audio (n%n_buffers));
595 ChannelInfo* chaninfo (*chan);
598 if (scaling != 1.0f) {
599 buf.read_from_with_gain (chaninfo->current_buffer, nframes, scaling);
601 buf.read_from (chaninfo->current_buffer, nframes);
604 if (scaling != 1.0f) {
605 buf.accumulate_with_gain_from (chaninfo->current_buffer, nframes, scaling);
607 buf.accumulate_from (chaninfo->current_buffer, nframes);
612 /* leave the MIDI count alone */
613 ChanCount cnt (DataType::AUDIO, n_chans);
614 cnt.set (DataType::MIDI, bufs.count().n_midi());
615 bufs.set_count (cnt);
617 /* extra buffers will already be silent, so leave them alone */
620 bool need_butler = false;
622 if (_actual_speed < 0.0) {
623 playback_sample -= playback_distance;
625 playback_sample += playback_distance;
628 for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) {
629 (*chan)->buf->increment_read_ptr (playback_distance);
634 need_butler = c->front()->buf->write_space() >= c->front()->buf->bufsize() / 2;
636 need_butler = (framecnt_t) c->front()->buf->write_space() >= _chunk_frames;
640 //return need_butler;
644 DiskReader::calculate_playback_distance (pframes_t nframes)
646 frameoffset_t playback_distance = nframes;
648 if (_actual_speed != 1.0f && _actual_speed != -1.0f) {
649 interpolation.set_speed (_target_speed);
650 boost::shared_ptr<ChannelList> c = channels.reader();
652 for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan, ++channel) {
653 playback_distance = interpolation.interpolate (channel, nframes, NULL, NULL);
656 playback_distance = nframes;
659 if (_actual_speed < 0.0) {
660 return -playback_distance;
662 return playback_distance;
667 DiskReader::set_pending_overwrite (bool yn)
669 /* called from audio thread, so we can use the read ptr and playback sample as we wish */
671 _pending_overwrite = yn;
673 overwrite_frame = playback_sample;
675 boost::shared_ptr<ChannelList> c = channels.reader ();
677 overwrite_offset = c->front()->buf->get_read_ptr();
682 DiskReader::overwrite_existing_buffers ()
684 boost::shared_ptr<ChannelList> c = channels.reader();
686 _pending_overwrite = false;
690 Sample* mixdown_buffer;
693 bool reversed = (_visible_speed * _session.transport_speed()) < 0.0f;
695 overwrite_queued = false;
697 /* assume all are the same size */
698 framecnt_t size = c->front()->buf->bufsize();
700 mixdown_buffer = new Sample[size];
701 gain_buffer = new float[size];
703 /* reduce size so that we can fill the buffer correctly (ringbuffers
704 can only handle size-1, otherwise they appear to be empty)
711 for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan, ++n) {
713 start = overwrite_frame;
714 framecnt_t cnt = size;
716 /* to fill the buffer without resetting the playback sample, we need to
717 do it one or two chunks (normally two).
719 |----------------------------------------------------------------------|
723 |<- second chunk->||<----------------- first chunk ------------------>|
727 framecnt_t to_read = size - overwrite_offset;
729 if (read ((*chan)->buf->buffer() + overwrite_offset, mixdown_buffer, gain_buffer, start, to_read, n, reversed)) {
730 error << string_compose(_("DiskReader %1: when refilling, cannot read %2 from playlist at frame %3"),
731 id(), size, playback_sample) << endmsg;
739 if (read ((*chan)->buf->buffer(), mixdown_buffer, gain_buffer, start, cnt, n, reversed)) {
740 error << string_compose(_("DiskReader %1: when refilling, cannot read %2 from playlist at frame %3"),
741 id(), size, playback_sample) << endmsg;
750 _pending_overwrite = false;
751 delete [] gain_buffer;
752 delete [] mixdown_buffer;
757 DiskReader::non_realtime_locate (framepos_t location)
759 /* now refill channel buffers */
761 if (speed() != 1.0f || speed() != -1.0f) {
762 seek ((framepos_t) (location * (double) speed()), true);
764 seek (location, true);
769 DiskReader::seek (framepos_t frame, bool complete_refill)
773 ChannelList::iterator chan;
774 boost::shared_ptr<ChannelList> c = channels.reader();
776 Glib::Threads::Mutex::Lock lm (state_lock);
778 for (n = 0, chan = c->begin(); chan != c->end(); ++chan, ++n) {
779 (*chan)->buf->reset ();
782 playback_sample = frame;
785 if (complete_refill) {
786 /* call _do_refill() to refill the entire buffer, using
787 the largest reads possible.
789 while ((ret = do_refill_with_alloc (false)) > 0) ;
791 /* call _do_refill() to refill just one chunk, and then
794 ret = do_refill_with_alloc (true);
801 DiskReader::can_internal_playback_seek (framecnt_t distance)
803 ChannelList::iterator chan;
804 boost::shared_ptr<ChannelList> c = channels.reader();
806 for (chan = c->begin(); chan != c->end(); ++chan) {
807 if ((*chan)->buf->read_space() < (size_t) distance) {
815 DiskReader::internal_playback_seek (framecnt_t distance)
817 ChannelList::iterator chan;
818 boost::shared_ptr<ChannelList> c = channels.reader();
820 for (chan = c->begin(); chan != c->end(); ++chan) {
821 (*chan)->buf->increment_read_ptr (::llabs(distance));
824 playback_sample += distance;
830 void swap_by_ptr (Sample *first, Sample *last)
832 while (first < last) {
839 /** Read some data for 1 channel from our playlist into a buffer.
840 * @param buf Buffer to write to.
841 * @param start Session frame to start reading from; updated to where we end up
843 * @param cnt Count of samples to read.
844 * @param reversed true if we are running backwards, otherwise false.
847 DiskReader::read (Sample* buf, Sample* mixdown_buffer, float* gain_buffer,
848 framepos_t& start, framecnt_t cnt,
849 int channel, bool reversed)
851 framecnt_t this_read = 0;
853 framepos_t loop_end = 0;
854 framepos_t loop_start = 0;
855 framecnt_t offset = 0;
858 /* XXX we don't currently play loops in reverse. not sure why */
862 framecnt_t loop_length = 0;
864 /* Make the use of a Location atomic for this read operation.
866 Note: Locations don't get deleted, so all we care about
867 when I say "atomic" is that we are always pointing to
868 the same one and using a start/length values obtained
872 if ((loc = loop_location) != 0) {
873 loop_start = loc->start();
874 loop_end = loc->end();
875 loop_length = loop_end - loop_start;
878 /* if we are looping, ensure that the first frame we read is at the correct
879 position within the loop.
882 if (loc && start >= loop_end) {
883 start = loop_start + ((start - loop_start) % loop_length);
892 /* We need this while loop in case we hit a loop boundary, in which case our read from
893 the playlist must be split into more than one section.
898 /* take any loop into account. we can't read past the end of the loop. */
900 if (loc && (loop_end - start < cnt)) {
901 this_read = loop_end - start;
908 if (this_read == 0) {
912 this_read = min(cnt,this_read);
914 if (audio_playlist()->read (buf+offset, mixdown_buffer, gain_buffer, start, this_read, channel) != this_read) {
915 error << string_compose(_("DiskReader %1: cannot read %2 from playlist at frame %3"), id(), this_read,
922 swap_by_ptr (buf, buf + this_read - 1);
926 /* if we read to the end of the loop, go back to the beginning */
943 DiskReader::_do_refill_with_alloc (bool partial_fill)
945 /* We limit disk reads to at most 4MB chunks, which with floating point
946 samples would be 1M samples. But we might use 16 or 14 bit samples,
947 in which case 4MB is more samples than that. Therefore size this for
948 the smallest sample value .. 4MB = 2M samples (16 bit).
951 Sample* mix_buf = new Sample[2*1048576];
952 float* gain_buf = new float[2*1048576];
954 int ret = _do_refill (mix_buf, gain_buf, (partial_fill ? _chunk_frames : 0));
962 /** Get some more data from disk and put it in our channels' bufs,
963 * if there is suitable space in them.
965 * If fill_level is non-zero, then we will refill the buffer so that there is
966 * still at least fill_level samples of space left to be filled. This is used
967 * after locates so that we do not need to wait to fill the entire buffer.
972 DiskReader::_do_refill (Sample* mixdown_buffer, float* gain_buffer, framecnt_t fill_level)
974 if (_session.state_of_the_state() & Session::Loading) {
980 RingBufferNPT<Sample>::rw_vector vector;
981 bool const reversed = (_visible_speed * _session.transport_speed()) < 0.0f;
982 framecnt_t total_space;
983 framecnt_t zero_fill;
985 ChannelList::iterator i;
986 boost::shared_ptr<ChannelList> c = channels.reader();
989 /* do not read from disk while session is marked as Loading, to avoid
990 useless redundant I/O.
997 assert(mixdown_buffer);
1005 c->front()->buf->get_write_vector (&vector);
1007 if ((total_space = vector.len[0] + vector.len[1]) == 0) {
1008 /* nowhere to write to */
1013 if (fill_level < total_space) {
1014 total_space -= fill_level;
1016 /* we can't do anything with it */
1021 /* if we're running close to normal speed and there isn't enough
1022 space to do disk_read_chunk_frames of I/O, then don't bother.
1024 at higher speeds, just do it because the sync between butler
1025 and audio thread may not be good enough.
1027 Note: it is a design assumption that disk_read_chunk_frames is smaller
1028 than the playback buffer size, so this check should never trip when
1029 the playback buffer is empty.
1032 if ((total_space < _chunk_frames) && fabs (_actual_speed) < 2.0f) {
1036 /* when slaved, don't try to get too close to the read pointer. this
1037 leaves space for the buffer reversal to have something useful to
1041 if (_slaved && total_space < (framecnt_t) (c->front()->buf->bufsize() / 2)) {
1047 if (file_frame == 0) {
1049 /* at start: nothing to do but fill with silence */
1051 for (chan_n = 0, i = c->begin(); i != c->end(); ++i, ++chan_n) {
1053 ChannelInfo* chan (*i);
1054 chan->buf->get_write_vector (&vector);
1055 memset (vector.buf[0], 0, sizeof(Sample) * vector.len[0]);
1056 if (vector.len[1]) {
1057 memset (vector.buf[1], 0, sizeof(Sample) * vector.len[1]);
1059 chan->buf->increment_write_ptr (vector.len[0] + vector.len[1]);
1064 if (file_frame < total_space) {
1066 /* too close to the start: read what we can,
1067 and then zero fill the rest
1070 zero_fill = total_space - file_frame;
1071 total_space = file_frame;
1080 if (file_frame == max_framepos) {
1082 /* at end: nothing to do but fill with silence */
1084 for (chan_n = 0, i = c->begin(); i != c->end(); ++i, ++chan_n) {
1086 ChannelInfo* chan (*i);
1087 chan->buf->get_write_vector (&vector);
1088 memset (vector.buf[0], 0, sizeof(Sample) * vector.len[0]);
1089 if (vector.len[1]) {
1090 memset (vector.buf[1], 0, sizeof(Sample) * vector.len[1]);
1092 chan->buf->increment_write_ptr (vector.len[0] + vector.len[1]);
1097 if (file_frame > max_framepos - total_space) {
1099 /* to close to the end: read what we can, and zero fill the rest */
1101 zero_fill = total_space - (max_framepos - file_frame);
1102 total_space = max_framepos - file_frame;
1109 framepos_t file_frame_tmp = 0;
1111 /* total_space is in samples. We want to optimize read sizes in various sizes using bytes */
1113 const size_t bits_per_sample = format_data_width (_session.config.get_native_file_data_format());
1114 size_t total_bytes = total_space * bits_per_sample / 8;
1116 /* chunk size range is 256kB to 4MB. Bigger is faster in terms of MB/sec, but bigger chunk size always takes longer
1118 size_t byte_size_for_read = max ((size_t) (256 * 1024), min ((size_t) (4 * 1048576), total_bytes));
1120 /* find nearest (lower) multiple of 16384 */
1122 byte_size_for_read = (byte_size_for_read / 16384) * 16384;
1124 /* now back to samples */
1126 framecnt_t samples_to_read = byte_size_for_read / (bits_per_sample / 8);
1128 //cerr << name() << " will read " << byte_size_for_read << " out of total bytes " << total_bytes << " in buffer of "
1129 // << c->front()->buf->bufsize() * bits_per_sample / 8 << " bps = " << bits_per_sample << endl;
1130 // cerr << name () << " read samples = " << samples_to_read << " out of total space " << total_space << " in buffer of " << c->front()->buf->bufsize() << " samples\n";
1132 // uint64_t before = g_get_monotonic_time ();
1133 // uint64_t elapsed;
1135 for (chan_n = 0, i = c->begin(); i != c->end(); ++i, ++chan_n) {
1137 ChannelInfo* chan (*i);
1140 framecnt_t len1, len2;
1142 chan->buf->get_write_vector (&vector);
1144 if ((framecnt_t) vector.len[0] > samples_to_read) {
1146 /* we're not going to fill the first chunk, so certainly do not bother with the
1147 other part. it won't be connected with the part we do fill, as in:
1149 .... => writable space
1150 ++++ => readable space
1151 ^^^^ => 1 x disk_read_chunk_frames that would be filled
1153 |......|+++++++++++++|...............................|
1158 So, just pretend that the buf1 part isn't there.
1168 file_frame_tmp = file_frame;
1170 buf1 = vector.buf[0];
1171 len1 = vector.len[0];
1172 buf2 = vector.buf[1];
1173 len2 = vector.len[1];
1175 to_read = min (ts, len1);
1176 to_read = min (to_read, (framecnt_t) samples_to_read);
1178 assert (to_read >= 0);
1182 if (read (buf1, mixdown_buffer, gain_buffer, file_frame_tmp, to_read, chan_n, reversed)) {
1187 chan->buf->increment_write_ptr (to_read);
1191 to_read = min (ts, len2);
1195 /* we read all of vector.len[0], but it wasn't the
1196 entire samples_to_read of data, so read some or
1197 all of vector.len[1] as well.
1200 if (read (buf2, mixdown_buffer, gain_buffer, file_frame_tmp, to_read, chan_n, reversed)) {
1205 chan->buf->increment_write_ptr (to_read);
1209 /* XXX: do something */
1214 // elapsed = g_get_monotonic_time () - before;
1215 // cerr << "\tbandwidth = " << (byte_size_for_read / 1048576.0) / (elapsed/1000000.0) << "MB/sec\n";
1217 file_frame = file_frame_tmp;
1218 assert (file_frame >= 0);
1220 ret = ((total_space - samples_to_read) > _chunk_frames);
1222 c->front()->buf->get_write_vector (&vector);
1229 DiskReader::playlist_ranges_moved (list< Evoral::RangeMove<framepos_t> > const & movements_frames, bool from_undo)
1231 /* If we're coming from an undo, it will have handled
1232 automation undo (it must, since automation-follows-regions
1233 can lose automation data). Hence we can do nothing here.
1241 if (!_track || Config->get_automation_follows_regions () == false) {
1245 list< Evoral::RangeMove<double> > movements;
1247 for (list< Evoral::RangeMove<framepos_t> >::const_iterator i = movements_frames.begin();
1248 i != movements_frames.end();
1251 movements.push_back(Evoral::RangeMove<double>(i->from, i->length, i->to));
1254 /* move panner automation */
1255 boost::shared_ptr<Pannable> pannable = _track->pannable();
1256 Evoral::ControlSet::Controls& c (pannable->controls());
1258 for (Evoral::ControlSet::Controls::iterator ci = c.begin(); ci != c.end(); ++ci) {
1259 boost::shared_ptr<AutomationControl> ac = boost::dynamic_pointer_cast<AutomationControl>(ci->second);
1263 boost::shared_ptr<AutomationList> alist = ac->alist();
1264 if (!alist->size()) {
1267 XMLNode & before = alist->get_state ();
1268 bool const things_moved = alist->move_ranges (movements);
1270 _session.add_command (new MementoCommand<AutomationList> (
1271 *alist.get(), &before, &alist->get_state ()));
1274 /* move processor automation */
1275 _track->foreach_processor (boost::bind (&Diskstream::move_processor_automation, this, _1, movements_frames));
1280 DiskReader::move_processor_automation (boost::weak_ptr<Processor> p, list< Evoral::RangeMove<framepos_t> > const & movements_frames)
1282 boost::shared_ptr<Processor> processor (p.lock ());
1287 list< Evoral::RangeMove<double> > movements;
1288 for (list< Evoral::RangeMove<framepos_t> >::const_iterator i = movements_frames.begin(); i != movements_frames.end(); ++i) {
1289 movements.push_back(Evoral::RangeMove<double>(i->from, i->length, i->to));
1292 set<Evoral::Parameter> const a = processor->what_can_be_automated ();
1294 for (set<Evoral::Parameter>::const_iterator i = a.begin (); i != a.end (); ++i) {
1295 boost::shared_ptr<AutomationList> al = processor->automation_control(*i)->alist();
1299 XMLNode & before = al->get_state ();
1300 bool const things_moved = al->move_ranges (movements);
1302 _session.add_command (
1303 new MementoCommand<AutomationList> (
1304 *al.get(), &before, &al->get_state ()