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.
20 #include "pbd/error.h"
23 #include "ardour/butler.h"
24 #include "ardour/disk_io.h"
25 #include "ardour/disk_reader.h"
26 #include "ardour/disk_writer.h"
27 #include "ardour/location.h"
28 #include "ardour/rc_configuration.h"
29 #include "ardour/session.h"
31 using namespace ARDOUR;
35 const string DiskIOProcessor::state_node_name = X_("DiskIOProcessor");
37 // PBD::Signal0<void> DiskIOProcessor::DiskOverrun;
38 // PBD::Signal0<void> DiskIOProcessor::DiskUnderrun;
40 DiskIOProcessor::DiskIOProcessor (Session& s, string const & str, Flag f)
43 , i_am_the_modifier (false)
44 , _visible_speed (0.0)
48 , _buffer_reallocation_required (false)
49 , _seek_required (false)
52 , in_set_state (false)
53 , wrap_buffer_size (0)
54 , speed_buffer_size (0)
55 , _need_butler (false)
56 , channels (new ChannelList)
61 DiskIOProcessor::set_buffering_parameters (BufferingPreset bp)
63 framecnt_t read_chunk_size;
64 framecnt_t read_buffer_size;
65 framecnt_t write_chunk_size;
66 framecnt_t write_buffer_size;
68 if (!get_buffering_presets (bp, read_chunk_size, read_buffer_size, write_chunk_size, write_buffer_size)) {
72 DiskReader::set_chunk_frames (read_chunk_size);
73 DiskWriter::set_chunk_frames (write_chunk_size);
75 Config->set_audio_capture_buffer_seconds (write_buffer_size);
76 Config->set_audio_playback_buffer_seconds (read_buffer_size);
80 DiskIOProcessor::get_buffering_presets (BufferingPreset bp,
81 framecnt_t& read_chunk_size,
82 framecnt_t& read_buffer_size,
83 framecnt_t& write_chunk_size,
84 framecnt_t& write_buffer_size)
88 read_chunk_size = 65536; /* samples */
89 write_chunk_size = 65536; /* samples */
90 read_buffer_size = 5; /* seconds */
91 write_buffer_size = 5; /* seconds */
95 read_chunk_size = 262144; /* samples */
96 write_chunk_size = 131072; /* samples */
97 read_buffer_size = 10; /* seconds */
98 write_buffer_size = 10; /* seconds */
102 read_chunk_size = 524288; /* samples */
103 write_chunk_size = 131072; /* samples */
104 read_buffer_size = 20; /* seconds */
105 write_buffer_size = 20; /* seconds */
117 DiskIOProcessor::set_loop (Location *location)
120 if (location->start() >= location->end()) {
121 error << string_compose(_("Location \"%1\" not valid for track loop (start >= end)"), location->name()) << endl;
126 loop_location = location;
128 LoopSet (location); /* EMIT SIGNAL */
133 DiskIOProcessor::non_realtime_set_speed ()
135 if (_buffer_reallocation_required)
137 Glib::Threads::Mutex::Lock lm (state_lock);
138 allocate_temporary_buffers ();
140 _buffer_reallocation_required = false;
143 if (_seek_required) {
144 if (speed() != 1.0f || speed() != -1.0f) {
145 seek ((framepos_t) (_session.transport_frame() * (double) speed()), true);
148 seek (_session.transport_frame(), true);
151 _seek_required = false;
156 DiskIOProcessor::realtime_set_speed (double sp, bool global)
158 bool changed = false;
159 double new_speed = sp * _session.transport_speed();
161 if (_visible_speed != sp) {
166 if (new_speed != _actual_speed) {
168 framecnt_t required_wrap_size = (framecnt_t) ceil (_session.get_block_size() *
169 fabs (new_speed)) + 2;
171 if (required_wrap_size > wrap_buffer_size) {
172 _buffer_reallocation_required = true;
175 _actual_speed = new_speed;
176 _target_speed = fabs(_actual_speed);
181 _seek_required = true;
183 SpeedChanged (); /* EMIT SIGNAL */
186 return _buffer_reallocation_required || _seek_required;
190 DiskIOProcessor::set_state (const XMLNode& node, int version)
192 XMLProperty const * prop;
194 Processor::set_state (node, version);
196 if ((prop = node.property ("flags")) != 0) {
197 _flags = Flag (string_2_enum (prop->value(), _flags));
200 if ((prop = node.property ("speed")) != 0) {
201 double sp = atof (prop->value().c_str());
203 if (realtime_set_speed (sp, false)) {
204 non_realtime_set_speed ();
211 DiskIOProcessor::add_channel_to (boost::shared_ptr<ChannelList> c, uint32_t how_many)
214 c->push_back (new ChannelInfo(
215 _session.butler()->audio_diskstream_playback_buffer_size(),
216 speed_buffer_size, wrap_buffer_size));
217 interpolation.add_channel_to (
218 _session.butler()->audio_diskstream_playback_buffer_size(),
222 _n_channels.set (DataType::AUDIO, c->size());
228 DiskIOProcessor::add_channel (uint32_t how_many)
230 RCUWriter<ChannelList> writer (channels);
231 boost::shared_ptr<ChannelList> c = writer.get_copy();
233 return add_channel_to (c, how_many);
237 DiskIOProcessor::remove_channel_from (boost::shared_ptr<ChannelList> c, uint32_t how_many)
239 while (how_many-- && !c->empty()) {
242 interpolation.remove_channel_from ();
245 _n_channels.set(DataType::AUDIO, c->size());
251 DiskIOProcessor::remove_channel (uint32_t how_many)
253 RCUWriter<ChannelList> writer (channels);
254 boost::shared_ptr<ChannelList> c = writer.get_copy();
256 return remove_channel_from (c, how_many);