2 Copyright (C) 2008 Paul Davis
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include "ardour/audio_buffer.h"
22 #include "ardour/audio_port.h"
23 #include "ardour/audio_track.h"
24 #include "ardour/audioengine.h"
25 #include "ardour/audioregion.h"
26 #include "ardour/capturing_processor.h"
27 #include "ardour/export_channel.h"
28 #include "ardour/export_failed.h"
29 #include "ardour/session.h"
31 #include "pbd/error.h"
35 using namespace ARDOUR;
37 PortExportChannel::PortExportChannel ()
42 PortExportChannel::~PortExportChannel ()
47 void PortExportChannel::set_max_buffer_size(samplecnt_t samples)
49 _buffer_size = samples;
50 _buffer.reset (new Sample[samples]);
54 for (PortSet::const_iterator it = ports.begin(); it != ports.end(); ++it) {
55 boost::shared_ptr<AudioPort> p = it->lock ();
57 samplecnt_t latency = p->private_latency_range (true).max;
58 PBD::RingBuffer<Sample>* rb = new PBD::RingBuffer<Sample> (latency + 1 + _buffer_size);
59 for (samplepos_t i = 0; i < latency; ++i) {
63 _delaylines.push_back (boost::shared_ptr<PBD::RingBuffer<Sample> >(rb));
68 PortExportChannel::operator< (ExportChannel const & other) const
70 PortExportChannel const * pec;
71 if (!(pec = dynamic_cast<PortExportChannel const *> (&other))) {
74 return ports < pec->ports;
78 PortExportChannel::read (Sample const *& data, samplecnt_t samples) const
81 assert(samples <= _buffer_size);
83 if (ports.size() == 1 && _delaylines.size() ==1 && _delaylines.front()->bufsize () == _buffer_size + 1) {
84 boost::shared_ptr<AudioPort> p = ports.begin()->lock ();
85 AudioBuffer& ab (p->get_audio_buffer(samples)); // unsets AudioBuffer::_written
87 ab.set_written (true);
91 memset (_buffer.get(), 0, samples * sizeof (Sample));
93 std::list <boost::shared_ptr<PBD::RingBuffer<Sample> > >::const_iterator di = _delaylines.begin ();
94 for (PortSet::const_iterator it = ports.begin(); it != ports.end(); ++it) {
95 boost::shared_ptr<AudioPort> p = it->lock ();
99 AudioBuffer& ab (p->get_audio_buffer(samples)); // unsets AudioBuffer::_written
100 Sample* port_buffer = ab.data();
101 ab.set_written (true);
102 (*di)->write (port_buffer, samples);
103 // TODO optimze, get_read_vector()
104 for (uint32_t i = 0; i < samples; ++i) {
106 (*di)->read (&spl, 1);
112 data = _buffer.get();
116 PortExportChannel::get_state (XMLNode * node) const
119 for (PortSet::const_iterator it = ports.begin(); it != ports.end(); ++it) {
120 boost::shared_ptr<Port> p = it->lock ();
121 if (p && (port_node = node->add_child ("Port"))) {
122 port_node->set_property ("name", p->name());
128 PortExportChannel::set_state (XMLNode * node, Session & session)
130 XMLNodeList xml_ports = node->children ("Port");
131 for (XMLNodeList::iterator it = xml_ports.begin(); it != xml_ports.end(); ++it) {
133 if ((*it)->get_property ("name", name)) {
134 boost::shared_ptr<AudioPort> port = boost::dynamic_pointer_cast<AudioPort> (session.engine().get_port_by_name (name));
138 PBD::warning << string_compose (_("Could not get port for export channel \"%1\", dropping the channel"), name) << endmsg;
144 RegionExportChannelFactory::RegionExportChannelFactory (Session * session, AudioRegion const & region, AudioTrack & track, Type type)
148 , samples_per_cycle (session->engine().samples_per_cycle ())
149 , buffers_up_to_date (false)
150 , region_start (region.position())
151 , position (region_start)
155 n_channels = region.n_channels();
158 n_channels = region.n_channels();
160 mixdown_buffer.reset (new Sample [samples_per_cycle]);
161 gain_buffer.reset (new Sample [samples_per_cycle]);
162 std::fill_n (gain_buffer.get(), samples_per_cycle, Sample (1.0));
166 n_channels = track.n_outputs().n_audio();
169 throw ExportFailed ("Unhandled type in ExportChannelFactory constructor");
172 session->ProcessExport.connect_same_thread (export_connection, boost::bind (&RegionExportChannelFactory::new_cycle_started, this, _1));
174 buffers.ensure_buffers (DataType::AUDIO, n_channels, samples_per_cycle);
175 buffers.set_count (ChanCount (DataType::AUDIO, n_channels));
178 RegionExportChannelFactory::~RegionExportChannelFactory ()
183 RegionExportChannelFactory::create (uint32_t channel)
185 assert (channel < n_channels);
186 return ExportChannelPtr (new RegionExportChannel (*this, channel));
190 RegionExportChannelFactory::read (uint32_t channel, Sample const *& data, samplecnt_t samples_to_read)
192 assert (channel < n_channels);
193 assert (samples_to_read <= samples_per_cycle);
195 if (!buffers_up_to_date) {
196 update_buffers(samples_to_read);
197 buffers_up_to_date = true;
200 data = buffers.get_audio (channel).data();
204 RegionExportChannelFactory::update_buffers (samplecnt_t samples)
206 assert (samples <= samples_per_cycle);
210 for (size_t channel = 0; channel < n_channels; ++channel) {
211 region.read (buffers.get_audio (channel).data(), position - region_start, samples, channel);
215 assert (mixdown_buffer && gain_buffer);
216 for (size_t channel = 0; channel < n_channels; ++channel) {
217 memset (mixdown_buffer.get(), 0, sizeof (Sample) * samples);
218 buffers.get_audio (channel).silence(samples);
219 region.read_at (buffers.get_audio (channel).data(), mixdown_buffer.get(), gain_buffer.get(), position, samples, channel);
223 track.export_stuff (buffers, position, samples, track.main_outs(), true, true, false);
226 throw ExportFailed ("Unhandled type in ExportChannelFactory::update_buffers");
233 RouteExportChannel::RouteExportChannel(boost::shared_ptr<CapturingProcessor> processor, size_t channel,
234 boost::shared_ptr<ProcessorRemover> remover)
235 : processor (processor)
241 RouteExportChannel::~RouteExportChannel()
246 RouteExportChannel::create_from_route(std::list<ExportChannelPtr> & result, boost::shared_ptr<Route> route)
248 boost::shared_ptr<CapturingProcessor> processor = route->add_export_point();
249 uint32_t channels = processor->input_streams().n_audio();
251 boost::shared_ptr<ProcessorRemover> remover (new ProcessorRemover (route, processor));
253 for (uint32_t i = 0; i < channels; ++i) {
254 result.push_back (ExportChannelPtr (new RouteExportChannel (processor, i, remover)));
259 RouteExportChannel::set_max_buffer_size(samplecnt_t samples)
262 processor->set_block_size (samples);
267 RouteExportChannel::read (Sample const *& data, samplecnt_t samples) const
270 AudioBuffer const & buffer = processor->get_capture_buffers().get_audio (channel);
274 assert (samples <= (samplecnt_t) buffer.capacity());
276 data = buffer.data();
280 RouteExportChannel::get_state (XMLNode *) const
286 RouteExportChannel::set_state (XMLNode *, Session &)
292 RouteExportChannel::operator< (ExportChannel const & other) const
294 RouteExportChannel const * rec;
295 if ((rec = dynamic_cast<RouteExportChannel const *>(&other)) == 0) {
296 return this < &other;
299 if (processor.get() == rec->processor.get()) {
300 return channel < rec->channel;
302 return processor.get() < rec->processor.get();
305 RouteExportChannel::ProcessorRemover::~ProcessorRemover()
307 route->remove_processor (processor);