summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libs/ardour/ardour/route.h7
-rw-r--r--libs/ardour/audio_track.cc33
-rw-r--r--libs/ardour/route.cc62
-rw-r--r--libs/ardour/session.cc43
4 files changed, 107 insertions, 38 deletions
diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h
index fb2b18f177..1132967ecf 100644
--- a/libs/ardour/ardour/route.h
+++ b/libs/ardour/ardour/route.h
@@ -470,6 +470,13 @@ class LIBARDOUR_API Route : public SessionObject, public Automatable, public Rou
pframes_t nframes, int declick,
bool gain_automation_ok);
+ virtual void bounce_process (BufferSet& bufs,
+ framepos_t start_frame, framecnt_t nframes,
+ boost::shared_ptr<Processor> endpoint, bool include_endpoint,
+ bool for_export);
+
+ framecnt_t bounce_get_latency (boost::shared_ptr<Processor> endpoint, bool include_endpoint, bool for_export) const;
+
boost::shared_ptr<IO> _input;
boost::shared_ptr<IO> _output;
diff --git a/libs/ardour/audio_track.cc b/libs/ardour/audio_track.cc
index 94201882e7..61b6e56bb6 100644
--- a/libs/ardour/audio_track.cc
+++ b/libs/ardour/audio_track.cc
@@ -417,38 +417,7 @@ AudioTrack::export_stuff (BufferSet& buffers, framepos_t start, framecnt_t nfram
}
}
- // If no processing is required, there's no need to go any further.
-
- if (!endpoint && !include_endpoint) {
- return 0;
- }
-
- for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
-
- if (!include_endpoint && (*i) == endpoint) {
- break;
- }
-
- /* if we're not exporting, stop processing if we come across a routing processor.
- */
-
- if (!for_export && (*i)->does_routing()) {
- break;
- }
-
- /* even for export, don't run any processor that does routing.
-
- oh, and don't bother with the peak meter either.
- */
-
- if (!(*i)->does_routing() && !boost::dynamic_pointer_cast<PeakMeter>(*i)) {
- (*i)->run (buffers, start, start+nframes, nframes, true);
- }
-
- if ((*i) == endpoint) {
- break;
- }
- }
+ bounce_process (buffers, start, nframes, endpoint, include_endpoint, for_export);
return 0;
}
diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc
index 4d7bb5802d..2727f511cb 100644
--- a/libs/ardour/route.cc
+++ b/libs/ardour/route.cc
@@ -536,6 +536,68 @@ Route::process_output_buffers (BufferSet& bufs,
}
}
+void
+Route::bounce_process (BufferSet& buffers, framepos_t start, framecnt_t nframes,
+ boost::shared_ptr<Processor> endpoint, bool include_endpoint, bool for_export)
+{
+ /* If no processing is required, there's no need to go any further. */
+ if (!endpoint && !include_endpoint) {
+ return;
+ }
+
+ for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
+
+ if (!include_endpoint && (*i) == endpoint) {
+ break;
+ }
+
+ /* if we're not exporting, stop processing if we come across a routing processor. */
+
+ if (!for_export && (*i)->does_routing()) {
+ break;
+ }
+
+ /* don't run any processors that does routing.
+ * oh, and don't bother with the peak meter either.
+ */
+ if (!(*i)->does_routing() && !boost::dynamic_pointer_cast<PeakMeter>(*i)) {
+ (*i)->run (buffers, start, start+nframes, nframes, true);
+ }
+
+ //buffers.set_count ((*i)->output_streams());
+
+ if ((*i) == endpoint) {
+ break;
+ }
+ }
+}
+
+framecnt_t
+Route::bounce_get_latency (boost::shared_ptr<Processor> endpoint, bool include_endpoint, bool for_export) const
+{
+ framecnt_t latency = 0;
+ if (!endpoint && !include_endpoint) {
+ return latency;
+ }
+
+ for (ProcessorList::const_iterator i = _processors.begin(); i != _processors.end(); ++i) {
+
+ if (!include_endpoint && (*i) == endpoint) {
+ break;
+ }
+ if (!for_export && (*i)->does_routing()) {
+ break;
+ }
+ if (!(*i)->does_routing() && !boost::dynamic_pointer_cast<PeakMeter>(*i)) {
+ latency += (*i)->signal_latency ();
+ }
+ if ((*i) == endpoint) {
+ break;
+ }
+ }
+ return latency;
+}
+
ChanCount
Route::n_process_buffers ()
{
diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc
index 85059ccaea..bd33201199 100644
--- a/libs/ardour/session.cc
+++ b/libs/ardour/session.cc
@@ -4133,6 +4133,7 @@ Session::write_one_track (AudioTrack& track, framepos_t start, framepos_t end,
framepos_t position;
framecnt_t this_chunk;
framepos_t to_do;
+ framepos_t latency_skip;
BufferSet buffers;
SessionDirectory sdir(get_best_session_directory_for_new_source ());
const string sound_dir = sdir.sound_path();
@@ -4208,10 +4209,12 @@ Session::write_one_track (AudioTrack& track, framepos_t start, framepos_t end,
position = start;
to_do = len;
+ latency_skip = track.bounce_get_latency (endpoint, include_endpoint, for_export);
/* create a set of reasonably-sized buffers */
- buffers.ensure_buffers (DataType::AUDIO, max_proc.n_audio(), chunk_size);
- buffers.ensure_buffers (DataType::MIDI, max_proc.n_midi(), chunk_size);
+ for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
+ buffers.ensure_buffers(*t, max_proc.get(*t), chunk_size);
+ }
buffers.set_count (max_proc);
for (vector<boost::shared_ptr<Source> >::iterator src = srcs.begin(); src != srcs.end(); ++src) {
@@ -4228,22 +4231,50 @@ Session::write_one_track (AudioTrack& track, framepos_t start, framepos_t end,
goto out;
}
+ start += this_chunk;
+ to_do -= this_chunk;
+ itt.progress = (float) (1.0 - ((double) to_do / len));
+
+ if (latency_skip >= chunk_size) {
+ latency_skip -= chunk_size;
+ continue;
+ }
+
+ const framecnt_t current_chunk = this_chunk - latency_skip;
+
uint32_t n = 0;
for (vector<boost::shared_ptr<Source> >::iterator src=srcs.begin(); src != srcs.end(); ++src, ++n) {
boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*src);
if (afs) {
- if (afs->write (buffers.get_audio(n).data(), this_chunk) != this_chunk) {
+ if (afs->write (buffers.get_audio(n).data(latency_skip), current_chunk) != current_chunk) {
goto out;
}
}
}
+ latency_skip = 0;
+ }
- start += this_chunk;
- to_do -= this_chunk;
+ /* post-roll, pick up delayed processor output */
+ latency_skip = track.bounce_get_latency (endpoint, include_endpoint, for_export);
- itt.progress = (float) (1.0 - ((double) to_do / len));
+ while (latency_skip && !itt.cancel) {
+ this_chunk = min (latency_skip, chunk_size);
+ latency_skip -= this_chunk;
+
+ buffers.silence (this_chunk, 0);
+ track.bounce_process (buffers, start, this_chunk, endpoint, include_endpoint, for_export);
+
+ uint32_t n = 0;
+ for (vector<boost::shared_ptr<Source> >::iterator src=srcs.begin(); src != srcs.end(); ++src, ++n) {
+ boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*src);
+ if (afs) {
+ if (afs->write (buffers.get_audio(n).data(), this_chunk) != this_chunk) {
+ goto out;
+ }
+ }
+ }
}
if (!itt.cancel) {