X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Froute.cc;h=ee31b2a4e769975af1fd702f1bd71ab48fc4a717;hb=b69d818ce9fb86728b0033c6396e17dea56508a8;hp=b67b687ff6af6c39c036465c35beb0317a6442c4;hpb=28d8f2f6b9b512fb7d866a829d6b426bfebd74ad;p=ardour.git diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index b67b687ff6..ee31b2a4e7 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -65,6 +65,7 @@ #include "ardour/parameter_descriptor.h" #include "ardour/phase_control.h" #include "ardour/plugin_insert.h" +#include "ardour/polarity_processor.h" #include "ardour/port.h" #include "ardour/port_insert.h" #include "ardour/processor.h" @@ -107,6 +108,7 @@ Route::Route (Session& sess, string name, PresentationInfo::Flag flag, DataType , _declickable (false) , _have_internal_generator (false) , _default_type (default_type) + , _loop_location (NULL) , _track_number (0) , _strict_io (false) , _in_configure_processors (false) @@ -187,6 +189,10 @@ Route::init () _amp.reset (new Amp (_session, X_("Fader"), _gain_control, true)); add_processor (_amp, PostFader); + _polarity.reset (new PolarityProcessor (_session, _phase_control)); + _polarity->activate(); + _polarity->set_owner (this); + if (is_monitor ()) { _amp->set_display_name (_("Monitor")); } @@ -329,6 +335,10 @@ Route::process_output_buffers (BufferSet& bufs, */ automation_run (start_sample, nframes); + if (_pannable) { + _pannable->automation_run (start_sample + _signal_latency, nframes); + } + /* figure out if we're going to use gain automation */ if (gain_automation_ok) { _amp->set_gain_automation_buffer (_session.gain_automation_buffer ()); @@ -355,21 +365,25 @@ Route::process_output_buffers (BufferSet& bufs, * By the Time T=0 is reached (dt=15 later) that sample is audible. */ - start_sample += _signal_latency; - end_sample += _signal_latency; - - start_sample += _output->latency (); - end_sample += _output->latency (); - const double speed = (is_auditioner() ? 1.0 : _session.transport_speed ()); + const sampleoffset_t latency_offset = _signal_latency + _output->latency (); + if (speed < 0) { + /* when rolling backwards this can become negative */ + start_sample -= latency_offset; + end_sample -= latency_offset; + } else { + start_sample += latency_offset; + end_sample += latency_offset; + } + /* Note: during intial pre-roll 'start_sample' as passed as argument can be negative. * Functions calling process_output_buffers() will set "run_disk_reader" * to false if the pre-roll count-down is larger than playback_latency (). * * playback_latency() is guarnteed to be <= _signal_latency + _output->latency () */ - assert (!_disk_reader || !run_disk_reader || start_sample >= 0); + assert (!_disk_reader || !run_disk_reader || start_sample >= 0 || speed < 0); /* however the disk-writer may need to pick up output from other tracks * during pre-roll (in particular if this route has latent effects after the disk). @@ -381,7 +395,7 @@ Route::process_output_buffers (BufferSet& bufs, * given that */ bool run_disk_writer = false; - if (_disk_writer && speed != 0) { + if (_disk_writer && speed > 0) { samplecnt_t latency_preroll = _session.remaining_latency_preroll (); run_disk_writer = latency_preroll < nframes + (_signal_latency + _output->latency ()); if (end_sample - _disk_writer->input_latency () < _session.transport_sample ()) { @@ -417,65 +431,25 @@ Route::process_output_buffers (BufferSet& bufs, _pending_declick = 0; /* ------------------------------------------------------------------------------------------- - DENORMAL CONTROL/PHASE INVERT + DENORMAL CONTROL ----------------------------------------------------------------------------------------- */ - - /* TODO phase-control should become a processor, or rather a Stub-processor: - * a point in the chain which calls a special-cased private Route method. - * _phase_control is route-owned and dynamic.) - * and we should rename it to polarity. + /* XXX We'll need to protect silent inputs as well as silent disk + * (when not monitoring input or monitoring disk and there's no region + * for a longer time). * - * denormals: we'll need to protect silent inputs as well as silent disk - * (when not monitoring input). Or simply drop that feature. + * ...or simply drop that feature. */ - if (!_phase_control->none()) { - - int chn = 0; + if (_denormal_protection || Config->get_denormal_protection()) { - if (_denormal_protection || Config->get_denormal_protection()) { - - for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i, ++chn) { - Sample* const sp = i->data(); - - if (_phase_control->inverted (chn)) { - for (pframes_t nx = 0; nx < nframes; ++nx) { - sp[nx] = -sp[nx]; - sp[nx] += 1.0e-27f; - } - } else { - for (pframes_t nx = 0; nx < nframes; ++nx) { - sp[nx] += 1.0e-27f; - } - } - } - - } else { - - for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i, ++chn) { - Sample* const sp = i->data(); - - if (_phase_control->inverted (chn)) { - for (pframes_t nx = 0; nx < nframes; ++nx) { - sp[nx] = -sp[nx]; - } - } + for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i) { + Sample* const sp = i->data(); + for (pframes_t nx = 0; nx < nframes; ++nx) { + sp[nx] += 1.0e-27f; } } - - } else { - - if (_denormal_protection || Config->get_denormal_protection()) { - - for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i) { - Sample* const sp = i->data(); - for (pframes_t nx = 0; nx < nframes; ++nx) { - sp[nx] += 1.0e-27f; - } - } - } - } + /* ------------------------------------------------------------------------------------------- and go .... ----------------------------------------------------------------------------------------- */ @@ -504,27 +478,6 @@ Route::process_output_buffers (BufferSet& bufs, } #endif - if (boost::dynamic_pointer_cast(*i) != 0) { - /* set potential sidechain ports, capture and playback latency. - * This effectively sets jack port latency which should include - * up/downstream latencies. - * - * However, the value is not used by Ardour (2017-09-20) and calling - * IO::latency() is expensive, so we punt. - * - * capture should be - * input()->latenct + latency, - * playback should be - * output->latency() + _signal_latency - latency - * - * Also see note below, _signal_latency may be smaller than latency - * if a plugin's latency increases while it's running. - */ - const samplecnt_t playback_latency = std::max ((samplecnt_t)0, _signal_latency - latency); - boost::dynamic_pointer_cast(*i)->set_sidechain_latency ( - /* input->latency() + */ latency, /* output->latency() + */ playback_latency); - } - bool re_inject_oob_data = false; if ((*i) == _disk_reader) { /* Well now, we've made it past the disk-writer and to the disk-reader. @@ -549,7 +502,11 @@ Route::process_output_buffers (BufferSet& bufs, pspeed = 0; } - (*i)->run (bufs, start_sample - latency, end_sample - latency, pspeed, nframes, *i != _processors.back()); + if (speed < 0) { + (*i)->run (bufs, start_sample + latency, end_sample + latency, pspeed, nframes, *i != _processors.back()); + } else { + (*i)->run (bufs, start_sample - latency, end_sample - latency, pspeed, nframes, *i != _processors.back()); + } bufs.set_count ((*i)->output_streams()); @@ -569,7 +526,7 @@ Route::process_output_buffers (BufferSet& bufs, #if 0 if ((*i) == _delayline) { - latency += _delayline->get_delay (); + latency += _delayline->delay (); } #endif } @@ -703,6 +660,7 @@ void Route::monitor_run (samplepos_t start_sample, samplepos_t end_sample, pframes_t nframes, int declick) { assert (is_monitor()); + Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK); run_route (start_sample, end_sample, nframes, declick, true, false); } @@ -1413,7 +1371,7 @@ Route::clear_processors (Placement p) bool Route::is_internal_processor (boost::shared_ptr p) const { - if (p == _amp || p == _meter || p == _main_outs || p == _delayline || p == _trim) { + if (p == _amp || p == _meter || p == _main_outs || p == _delayline || p == _trim || p == _polarity) { return true; } return false; @@ -2949,6 +2907,9 @@ Route::set_processor_state (const XMLNode& node) } else if (prop->value() == "meter") { _meter->set_state (**niter, Stateful::current_state_version); new_order.push_back (_meter); + } else if (prop->value() == "polarity") { + _polarity->set_state (**niter, Stateful::current_state_version); + new_order.push_back (_polarity); } else if (prop->value() == "delay") { // skip -- internal } else if (prop->value() == "main-outs") { @@ -3133,6 +3094,9 @@ Route::silence_unlocked (samplecnt_t nframes) // update owned automated controllables automation_run (now, nframes); + if (_pannable) { + _pannable->automation_run (now, nframes); + } for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) { boost::shared_ptr pi; @@ -3474,7 +3438,6 @@ Route::input_change_handler (IOChange change, void * /*src*/) contains ConfigurationChanged */ configure_processors (0); - _phase_control->resize (_input->n_ports().n_audio ()); io_changed (); /* EMIT SIGNAL */ } @@ -4012,6 +3975,9 @@ Route::update_signal_latency (bool apply_to_delayline) // here or in Session::* ? -> also zero send latencies, // and make sure that re-enabling a route updates things again... + samplecnt_t capt_lat_in = _input->connected_latency (false); + samplecnt_t play_lat_out = _output->connected_latency (true); + Glib::Threads::RWLock::ReaderLock lm (_processor_lock); samplecnt_t l_in = 0; @@ -4020,6 +3986,14 @@ Route::update_signal_latency (bool apply_to_delayline) if (boost::shared_ptr snd = boost::dynamic_pointer_cast (*i)) { snd->set_delay_in (l_out + _output->latency()); } + + if (boost::shared_ptr pi = boost::dynamic_pointer_cast (*i)) { + if (boost::shared_ptr pio = pi->sidechain_input ()) { + samplecnt_t lat = l_out + _output->latency(); + pio->set_private_port_latencies (lat, true); + pio->set_public_port_latencies (lat, true); + } + } (*i)->set_output_latency (l_out); if ((*i)->active ()) { l_out += (*i)->signal_latency (); @@ -4031,6 +4005,27 @@ Route::update_signal_latency (bool apply_to_delayline) _signal_latency = l_out; for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) { + + /* set sidechain, send and insert port latencies */ + if (boost::shared_ptr pi = boost::dynamic_pointer_cast (*i)) { + if (pi->input ()) { + /* propagate playback latency from output to input */ + pi->input ()->set_private_port_latencies (play_lat_out + l_in, true); + } + if (pi->output ()) { + /* propagate capture latency from input to output */ + pi->output ()->set_private_port_latencies (capt_lat_in + l_in, false); + } + + } else if (boost::shared_ptr snd = boost::dynamic_pointer_cast (*i)) { + if (snd->output ()) { + /* set capture latency */ + snd->output ()->set_private_port_latencies (capt_lat_in + l_in, false); + /* take send-target's playback latency into account */ + snd->set_delay_out (snd->output ()->connected_latency (true)); + } + } + (*i)->set_input_latency (l_in); (*i)->set_playback_offset (_signal_latency + _output->latency ()); (*i)->set_capture_offset (_input->latency ()); @@ -4064,7 +4059,7 @@ void Route::apply_latency_compensation () { if (_delayline) { - samplecnt_t old = _delayline->get_delay (); + samplecnt_t old = _delayline->delay (); samplecnt_t play_lat_in = _input->connected_latency (true); samplecnt_t play_lat_out = _output->connected_latency (true); @@ -4080,7 +4075,7 @@ Route::apply_latency_compensation () _delayline->set_delay (latcomp > 0 ? latcomp : 0); - if (old != _delayline->get_delay ()) { + if (old != _delayline->delay ()) { signal_latency_updated (); /* EMIT SIGNAL */ } } @@ -4613,6 +4608,7 @@ Route::set_private_port_latencies (bool playback) const */ for (ProcessorList::const_iterator i = _processors.begin(); i != _processors.end(); ++i) { + if ((*i)->active ()) { own_latency += (*i)->signal_latency (); } @@ -4630,28 +4626,26 @@ Route::set_private_port_latencies (bool playback) const void Route::set_public_port_latencies (samplecnt_t value, bool playback) const { - /* this is called to set the JACK-visible port latencies, which take - latency compensation into account. - */ - - LatencyRange range; - - range.min = value; - range.max = value; - - { - const PortSet& ports (_input->ports()); - for (PortSet::const_iterator p = ports.begin(); p != ports.end(); ++p) { - p->set_public_latency_range (range, playback); + /* publish private latencies */ + Glib::Threads::RWLock::ReaderLock lm (_processor_lock); + for (ProcessorList::const_iterator i = _processors.begin(); i != _processors.end(); ++i) { + boost::shared_ptr iop = boost::dynamic_pointer_cast(*i); + if (!iop) { + continue; } - } - - { - const PortSet& ports (_output->ports()); - for (PortSet::const_iterator p = ports.begin(); p != ports.end(); ++p) { - p->set_public_latency_range (range, playback); + if (iop->input ()) { + iop->input ()->set_public_port_latencies (iop->input()->latency(), true); + } + if (iop->output ()) { + iop->output ()->set_public_port_latencies (iop->output()->latency(), false); } } + + /* this is called to set the JACK-visible port latencies, which take + * latency compensation into account. + */ + _input->set_public_port_latencies (value, playback); + _output->set_public_port_latencies (value, playback); } /** Put the invisible processors in the right place in _processors. @@ -4849,7 +4843,6 @@ Route::setup_invisible_processors () } } - /* EXPORT PROCESSOR */ if (_capturing_processor) { assert (!_capturing_processor->display_to_user ()); @@ -4858,7 +4851,30 @@ Route::setup_invisible_processors () /* insert after disk-reader */ new_processors.insert (++reader_pos, _capturing_processor); } else { - new_processors.push_front (_capturing_processor); + ProcessorList::iterator return_pos = find (new_processors.begin(), new_processors.end(), _intreturn); + /* insert after return */ + if (return_pos != new_processors.end()) { + new_processors.insert (++return_pos, _capturing_processor); + } else { + new_processors.push_front (_capturing_processor); + } + } + } + + /* Polarity Invert */ + if (_polarity) { + ProcessorList::iterator reader_pos = find (new_processors.begin(), new_processors.end(), _disk_reader); + if (reader_pos != new_processors.end()) { + /* insert after disk-reader */ + new_processors.insert (++reader_pos, _polarity); + } else { + ProcessorList::iterator return_pos = find (new_processors.begin(), new_processors.end(), _intreturn); + /* insert after return */ + if (return_pos != new_processors.end()) { + new_processors.insert (++return_pos, _polarity); + } else { + new_processors.push_front (_polarity); + } } } @@ -4871,9 +4887,16 @@ Route::setup_invisible_processors () assert (!_meter->display_to_user ()); ProcessorList::iterator writer_pos = find (new_processors.begin(), new_processors.end(), _disk_writer); if (writer_pos != new_processors.end()) { + /* insert before disk-writer */ new_processors.insert (writer_pos, _meter); } else { - new_processors.push_front (_meter); + ProcessorList::iterator return_pos = find (new_processors.begin(), new_processors.end(), _intreturn); + /* insert after return */ + if (return_pos != new_processors.end()) { + new_processors.insert (++return_pos, _meter); + } else { + new_processors.push_front (_meter); + } } } @@ -5419,6 +5442,19 @@ Route::filter_enable_controllable (bool) const #endif } +boost::shared_ptr +Route::tape_drive_controllable () const +{ +#ifdef MIXBUS + + if ( _ch_pre && (is_master() || mixbus()) ) { + return boost::dynamic_pointer_cast (_ch_pre->control (Evoral::Parameter (ARDOUR::PluginAutomation, 0, 4))); + } +#endif + + return boost::shared_ptr(); +} + string Route::eq_band_name (uint32_t band) const { @@ -5618,7 +5654,7 @@ Route::send_pan_azi_controllable (uint32_t n) const } #endif - boost::shared_ptr(); + return boost::shared_ptr(); } boost::shared_ptr @@ -5862,6 +5898,16 @@ Route::set_disk_io_point (DiskIOPoint diop) processors_changed (RouteProcessorChange ()); /* EMIT SIGNAL */ } +void +Route::set_loop (Location* l) +{ + _loop_location = l; + Glib::Threads::RWLock::ReaderLock lm (_processor_lock); + for (ProcessorList::const_iterator i = _processors.begin(); i != _processors.end(); ++i) { + (*i)->set_loop (l); + } +} + #ifdef USE_TRACKS_CODE_FEATURES /* This is the Tracks version of Track::monitoring_state(). @@ -6020,5 +6066,4 @@ Route::monitoring_state () const abort(); /* NOTREACHED */ return MonitoringSilence; } - #endif