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 , channels (new ChannelList)
60 DiskIOProcessor::set_buffering_parameters (BufferingPreset bp)
62 framecnt_t read_chunk_size;
63 framecnt_t read_buffer_size;
64 framecnt_t write_chunk_size;
65 framecnt_t write_buffer_size;
67 if (!get_buffering_presets (bp, read_chunk_size, read_buffer_size, write_chunk_size, write_buffer_size)) {
71 DiskReader::set_chunk_frames (read_chunk_size);
72 DiskWriter::set_chunk_frames (write_chunk_size);
74 Config->set_audio_capture_buffer_seconds (write_buffer_size);
75 Config->set_audio_playback_buffer_seconds (read_buffer_size);
79 DiskIOProcessor::get_buffering_presets (BufferingPreset bp,
80 framecnt_t& read_chunk_size,
81 framecnt_t& read_buffer_size,
82 framecnt_t& write_chunk_size,
83 framecnt_t& write_buffer_size)
87 read_chunk_size = 65536; /* samples */
88 write_chunk_size = 65536; /* samples */
89 read_buffer_size = 5; /* seconds */
90 write_buffer_size = 5; /* seconds */
94 read_chunk_size = 262144; /* samples */
95 write_chunk_size = 131072; /* samples */
96 read_buffer_size = 10; /* seconds */
97 write_buffer_size = 10; /* seconds */
101 read_chunk_size = 524288; /* samples */
102 write_chunk_size = 131072; /* samples */
103 read_buffer_size = 20; /* seconds */
104 write_buffer_size = 20; /* seconds */
116 DiskIOProcessor::set_loop (Location *location)
119 if (location->start() >= location->end()) {
120 error << string_compose(_("Location \"%1\" not valid for track loop (start >= end)"), location->name()) << endl;
125 loop_location = location;
127 LoopSet (location); /* EMIT SIGNAL */
132 DiskIOProcessor::non_realtime_set_speed ()
134 if (_buffer_reallocation_required)
136 Glib::Threads::Mutex::Lock lm (state_lock);
137 allocate_temporary_buffers ();
139 _buffer_reallocation_required = false;
142 if (_seek_required) {
143 if (speed() != 1.0f || speed() != -1.0f) {
144 seek ((framepos_t) (_session.transport_frame() * (double) speed()), true);
147 seek (_session.transport_frame(), true);
150 _seek_required = false;
155 DiskIOProcessor::realtime_set_speed (double sp, bool global)
157 bool changed = false;
158 double new_speed = sp * _session.transport_speed();
160 if (_visible_speed != sp) {
165 if (new_speed != _actual_speed) {
167 framecnt_t required_wrap_size = (framecnt_t) ceil (_session.get_block_size() *
168 fabs (new_speed)) + 2;
170 if (required_wrap_size > wrap_buffer_size) {
171 _buffer_reallocation_required = true;
174 _actual_speed = new_speed;
175 _target_speed = fabs(_actual_speed);
180 _seek_required = true;
182 SpeedChanged (); /* EMIT SIGNAL */
185 return _buffer_reallocation_required || _seek_required;
189 DiskIOProcessor::set_state (const XMLNode& node, int version)
191 XMLProperty const * prop;
193 Processor::set_state (node, version);
195 if ((prop = node.property ("flags")) != 0) {
196 _flags = Flag (string_2_enum (prop->value(), _flags));
199 if ((prop = node.property ("speed")) != 0) {
200 double sp = atof (prop->value().c_str());
202 if (realtime_set_speed (sp, false)) {
203 non_realtime_set_speed ();
210 DiskIOProcessor::add_channel_to (boost::shared_ptr<ChannelList> c, uint32_t how_many)
213 c->push_back (new ChannelInfo(
214 _session.butler()->audio_diskstream_playback_buffer_size(),
215 speed_buffer_size, wrap_buffer_size));
216 interpolation.add_channel_to (
217 _session.butler()->audio_diskstream_playback_buffer_size(),
221 _n_channels.set (DataType::AUDIO, c->size());
227 DiskIOProcessor::add_channel (uint32_t how_many)
229 RCUWriter<ChannelList> writer (channels);
230 boost::shared_ptr<ChannelList> c = writer.get_copy();
232 return add_channel_to (c, how_many);
236 DiskIOProcessor::remove_channel_from (boost::shared_ptr<ChannelList> c, uint32_t how_many)
238 while (how_many-- && !c->empty()) {
241 interpolation.remove_channel_from ();
244 _n_channels.set(DataType::AUDIO, c->size());
250 DiskIOProcessor::remove_channel (uint32_t how_many)
252 RCUWriter<ChannelList> writer (channels);
253 boost::shared_ptr<ChannelList> c = writer.get_copy();
255 return remove_channel_from (c, how_many);