diff --git a/libs/ardour/ardour/surround_return.h b/libs/ardour/ardour/surround_return.h index 2f6eb70275..247d2b7cd7 100644 --- a/libs/ardour/ardour/surround_return.h +++ b/libs/ardour/ardour/surround_return.h @@ -35,6 +35,7 @@ #endif #include "ardour/chan_mapping.h" +#include "ardour/fixed_delay.h" #include "ardour/lufs_meter.h" #include "ardour/monitor_processor.h" #include "ardour/processor.h" @@ -109,6 +110,7 @@ public: /* XXX this is only for testing */ void set_bed_mix (bool on, std::string const& ref, int* cmap = NULL); + void set_sync_and_return (bool on); int set_state (XMLNode const&, int version); @@ -124,6 +126,7 @@ private: void evaluate (size_t id, std::shared_ptr const&, timepos_t const& , pframes_t, bool force = false); void reset_object_map (); + void latency_changed (); std::shared_ptr _surround_processor; @@ -188,6 +191,8 @@ private: bool _rolling; bool _with_bed; std::string _export_reference; + bool _sync_and_align; + FixedDelay _delaybuffers; std::atomic _flush; }; diff --git a/libs/ardour/luabindings.cc b/libs/ardour/luabindings.cc index fe6eda6ba3..44e8fbc2fd 100644 --- a/libs/ardour/luabindings.cc +++ b/libs/ardour/luabindings.cc @@ -1922,6 +1922,7 @@ LuaBindings::common (lua_State* L) .deriveWSPtrClass ("SurroundReturn") .addFunction ("set_bed_mix", &SurroundReturn::set_bed_mix) + .addFunction ("set_sync_and_return", &SurroundReturn::set_sync_and_return) .addFunction ("have_au_renderer", &SurroundReturn::have_au_renderer) .addFunction ("load_au_preset", &SurroundReturn::load_au_preset) .addFunction ("set_au_param", &SurroundReturn::set_au_param) diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index b6d97cfb7b..e9aeab28ad 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -299,6 +299,7 @@ Route::init () if (is_surround_master ()) { _meter_point = _pending_meter_point = MeterPreFader; _surround_return.reset (new SurroundReturn (_session, this)); + _surround_return->set_owner (this); _surround_return->activate (); panner_shell()->set_bypassed (true); diff --git a/libs/ardour/surround_return.cc b/libs/ardour/surround_return.cc index 248f8b8ce4..e3ecdc73d7 100644 --- a/libs/ardour/surround_return.cc +++ b/libs/ardour/surround_return.cc @@ -91,6 +91,7 @@ SurroundReturn::SurroundReturn (Session& s, Route* r) , _export_end (0) , _rolling (false) , _with_bed (false) + , _sync_and_align (false) { #if !(defined(LV2_EXTENDED) && defined(HAVE_LV2_1_10_0)) throw failed_constructor (); @@ -115,6 +116,9 @@ SurroundReturn::SurroundReturn (Session& s, Route* r) _trim->configure_io (cca128, cca128); _trim->activate (); + ChanCount cca20 (ChanCount (DataType::AUDIO, 20)); // 7.1.4 + binaural + 5.1 + _delaybuffers.configure (cca20, 512); + for (size_t i = 0; i < max_object_id; ++i) { _current_render_mode[i] = -1; _channel_id_map[i] = i; @@ -324,7 +328,7 @@ SurroundReturn::set_block_size (pframes_t nframes) samplecnt_t SurroundReturn::signal_latency () const { - return _surround_processor->signal_latency (); + return _surround_processor->signal_latency () + _delaybuffers.delay (); } void @@ -333,6 +337,14 @@ SurroundReturn::flush () _flush.store (1); } +void +SurroundReturn::latency_changed () +{ + LatencyChanged (); + assert (owner()); + static_cast(owner ())->processor_latency_changed (); /* EMIT SIGNAL */ +} + void SurroundReturn::reset_object_map () { @@ -364,6 +376,15 @@ SurroundReturn::set_bed_mix (bool on, std::string const& ref, int* cmap) } } +void +SurroundReturn::set_sync_and_return (bool on) +{ + if (_sync_and_align == on) { + return; + } + _sync_and_align = on; +} + void SurroundReturn::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sample, double speed, pframes_t nframes, bool) { @@ -376,6 +397,27 @@ SurroundReturn::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_ _surround_processor->flush (); } + if (_sync_and_align) { + if (!_rolling && start_sample != end_sample) { + _delaybuffers.flush (); + _surround_processor->deactivate(); + _surround_processor->activate(); + } + if (0 != (playback_offset() % 512)) { + ChanCount cca20 (ChanCount (DataType::AUDIO, 20)); // 7.1.4 + binaural + 5.1 + if (_delaybuffers.delay () == 0) { + _delaybuffers.set (cca20, 512 - playback_offset() % 512); + } else { + _delaybuffers.set (cca20, 0); + } + latency_changed (); + } + } else if (_delaybuffers.delay () != 0) { + ChanCount cca20 (ChanCount (DataType::AUDIO, 20)); // 7.1.4 + binaural + 5.1 + _delaybuffers.set (cca20, 0); + latency_changed (); + } + bool with_bed = _with_bed; bufs.set_count (_configured_output); @@ -438,7 +480,7 @@ SurroundReturn::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_ * IOW: end_sample == next cycle's start_sample; */ if (nframes < 2) { - evaluate (id, p, timepos_t (start_sample), 0); + evaluate (id, p, timepos_t (start_sample + latency), 0); } else { bool found_event = false; timepos_t start (start_sample + latency); @@ -456,7 +498,7 @@ SurroundReturn::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_ } /* inform live renderer */ if (!found_event && !_exporting) { - evaluate (id, p, end, nframes - 1); + evaluate (id, p, start, 0); } } } @@ -583,8 +625,9 @@ SurroundReturn::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_ _surround_processor->connect_and_run (_surround_bufs, start_sample, end_sample, speed, _in_map, _out_map, nframes, 0); BufferSet::iterator i = _surround_bufs.begin (DataType::AUDIO); - for (BufferSet::iterator o = bufs.begin (DataType::AUDIO); o != bufs.end (DataType::AUDIO); ++i, ++o) { - o->read_from (*i, nframes); + uint32_t idx = 0; + for (BufferSet::iterator o = bufs.begin (DataType::AUDIO); o != bufs.end (DataType::AUDIO); ++i, ++o, ++idx) { + _delaybuffers.delay (DataType::AUDIO, idx, *o, *i, nframes); } if (_exporting) {