diff --git a/libs/ardour/ardour/delivery.h b/libs/ardour/ardour/delivery.h index c7e147832c..3e955e2fe3 100644 --- a/libs/ardour/ardour/delivery.h +++ b/libs/ardour/ardour/delivery.h @@ -33,6 +33,7 @@ namespace ARDOUR { +class Amp; class BufferSet; class IO; class MuteMaster; @@ -78,6 +79,9 @@ public: bool can_support_io_configuration (const ChanCount& in, ChanCount& out); bool configure_io (ChanCount in, ChanCount out); + void activate (); + void deactivate (); + void run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sample, double speed, pframes_t nframes, bool); /* supplemental method used with MIDI */ @@ -101,8 +105,10 @@ public: boost::shared_ptr panner_shell() const { return _panshell; } boost::shared_ptr panner() const; - void add_gain (boost::shared_ptr gc) { - _gain_control = gc; + void set_gain_control (boost::shared_ptr gc); + + void set_polarity_control (boost::shared_ptr ac) { + _polarity_control = ac; } void unpan (); @@ -113,10 +119,18 @@ public: uint32_t pans_required() const { return _configured_input.n_audio(); } virtual uint32_t pan_outs() const; + boost::shared_ptr gain_control () const { + return _gain_control; + } + boost::shared_ptr polarity_control () const { return _polarity_control; } + boost::shared_ptr amp() const { + return _amp; + } + protected: XMLNode& state () const; @@ -124,15 +138,16 @@ protected: BufferSet* _output_buffers; gain_t _current_gain; boost::shared_ptr _panshell; - boost::shared_ptr _polarity_control; + boost::shared_ptr _amp; gain_t target_gain (); private: bool _no_outs_cuz_we_no_monitor; - boost::shared_ptr _mute_master; - boost::shared_ptr _gain_control; + boost::shared_ptr _mute_master; + boost::shared_ptr _gain_control; + boost::shared_ptr _polarity_control; static bool panners_legal; static PBD::Signal0 PannersLegal; diff --git a/libs/ardour/ardour/send.h b/libs/ardour/ardour/send.h index e52638e2ce..eeaabf9cfd 100644 --- a/libs/ardour/ardour/send.h +++ b/libs/ardour/ardour/send.h @@ -33,7 +33,6 @@ namespace ARDOUR { class PeakMeter; -class Amp; class GainControl; class DelayLine; @@ -73,9 +72,7 @@ public: bool display_to_user() const; bool is_foldback () const { return _role == Foldback; } - boost::shared_ptr amp() const { return _amp; } boost::shared_ptr meter() const { return _meter; } - boost::shared_ptr gain_control() const { return _gain_control; } bool metering() const { return _metering; } void set_metering (bool yn) { _metering = yn; } @@ -117,8 +114,6 @@ protected: XMLNode& state () const; bool _metering; - boost::shared_ptr _gain_control; - boost::shared_ptr _amp; boost::shared_ptr _meter; boost::shared_ptr _send_delay; boost::shared_ptr _thru_delay; diff --git a/libs/ardour/delivery.cc b/libs/ardour/delivery.cc index 09a19e49f4..19e4730062 100644 --- a/libs/ardour/delivery.cc +++ b/libs/ardour/delivery.cc @@ -187,6 +187,18 @@ Delivery::can_support_io_configuration (const ChanCount& in, ChanCount& out) return false; } +void +Delivery::set_gain_control (boost::shared_ptr gc) { + if (gc) { + _gain_control = gc; + _amp.reset (new Amp (_session, _("Fader"), _gain_control, true)); + _amp->configure_io (_configured_input, _configured_output); + } else { + _amp.reset (); + _gain_control = gc; + } +} + /** Caller must hold process lock */ bool Delivery::configure_io (ChanCount in, ChanCount out) @@ -233,11 +245,15 @@ Delivery::configure_io (ChanCount in, ChanCount out) reset_panner (); + if (_amp) { + return _amp->configure_io (in, out); + } + return true; } void -Delivery::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sample, double /*speed*/, pframes_t nframes, bool result_required) +Delivery::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sample, double speed, pframes_t nframes, bool result_required) { assert (_output); @@ -272,11 +288,11 @@ Delivery::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sample _current_gain = Amp::apply_gain (bufs, _session.nominal_sample_rate(), nframes, _current_gain, tgain); - } else if (tgain < GAIN_COEFF_SMALL) { + } else if (fabsf (tgain) < GAIN_COEFF_SMALL) { /* we were quiet last time, and we're still supposed to be quiet. - Silence the outputs, and make sure the buffers are quiet too, - */ + * Silence the outputs, and make sure the buffers are quiet too, + */ _output->silence (nframes); if (result_required) { @@ -297,6 +313,13 @@ Delivery::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sample Amp::apply_simple_gain (bufs, nframes, speed_quietning, false); } + /* gain control/automation */ + if (_amp) { + _amp->set_gain_automation_buffer (_session.send_gain_automation_buffer ()); + _amp->setup_gain_automation (start_sample, end_sample, nframes); + _amp->run (bufs, start_sample, end_sample, speed, nframes, true); + } + // Panning if (_panshell && !_panshell->bypassed() && _panshell->panner()) { @@ -376,6 +399,11 @@ Delivery::state () const node.add_child_nocopy (_panshell->unlinked_pannable()->get_state ()); } } + /* Note: _gain_control state is saved by the owner, + * mainly for backwards compatibility reasons, but also because + * the gain-control may be owned by Route e.g. LAN _volume_control + */ + if (_polarity_control) { node.add_child_nocopy (_polarity_control->get_state()); } @@ -588,10 +616,6 @@ Delivery::target_gain () gain_t desired_gain = _mute_master->mute_gain_at (mp); - if (_gain_control) { - desired_gain *= _gain_control->get_value(); - } - if (_role == Listen && _session.monitor_out() && !_session.listening()) { /* nobody is soloed, and this delivery is a listen-send to the @@ -609,6 +633,24 @@ Delivery::target_gain () return desired_gain; } +void +Delivery::activate () +{ + if (_amp) { + _amp->activate (); + } + Processor::activate (); +} + +void +Delivery::deactivate () +{ + if (_amp) { + _amp->deactivate (); + } + Processor::deactivate (); +} + void Delivery::no_outs_cuz_we_no_monitor (bool yn) { diff --git a/libs/ardour/internal_send.cc b/libs/ardour/internal_send.cc index 923462c35c..ec009139e3 100644 --- a/libs/ardour/internal_send.cc +++ b/libs/ardour/internal_send.cc @@ -140,10 +140,10 @@ InternalSend::init_gain () { if (_role == Listen) { /* send to monitor bus is always at unity */ - _gain_control->set_value (GAIN_COEFF_UNITY, PBD::Controllable::NoGroup); + gain_control ()->set_value (GAIN_COEFF_UNITY, PBD::Controllable::NoGroup); } else { /* aux sends start at -inf dB */ - _gain_control->set_value (GAIN_COEFF_ZERO, PBD::Controllable::NoGroup); + gain_control ()->set_value (GAIN_COEFF_ZERO, PBD::Controllable::NoGroup); } } @@ -331,7 +331,7 @@ InternalSend::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sa /* consider metering */ if (_metering) { - if (_amp->gain_control ()->get_value () == GAIN_COEFF_ZERO) { + if (gain_control ()->get_value () == GAIN_COEFF_ZERO) { _meter->reset (); } else { _meter->run (mixbufs, start_sample, end_sample, speed, nframes, true); diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index 682c23f5f8..8e9b9bad1f 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -266,7 +266,7 @@ Route::init () if (is_master()) { _volume_control.reset (new GainControl (_session, MainOutVolume)); _volume_control->set_flag (Controllable::NotAutomatable); - _main_outs->add_gain (_volume_control); + _main_outs->set_gain_control (_volume_control); _volume.reset (new Amp (_session, X_("LAN Amp"), _volume_control, false)); _volume->set_display_to_user (false); _volume->deactivate (); @@ -2770,11 +2770,11 @@ Route::set_state (const XMLNode& node, int version) if (_volume_applies_to_output) { _volume->deactivate (); _volume->set_display_to_user (false); - main_outs()->add_gain (_volume_control); + main_outs()->set_gain_control (_volume_control); } else { _volume->set_display_to_user (true); _volume->activate (); - main_outs()->add_gain (boost::shared_ptr ()); + main_outs()->set_gain_control (boost::shared_ptr ()); } } @@ -4792,7 +4792,7 @@ Route::set_volume_applies_to_output (bool en) if (en) { _volume->deactivate (); _volume->set_display_to_user (false); - main_outs()->add_gain (_volume_control); + main_outs()->set_gain_control (_volume_control); { /* remove hidden processor */ Glib::Threads::Mutex::Lock lx (AudioEngine::instance()->process_lock ()); @@ -4803,7 +4803,7 @@ Route::set_volume_applies_to_output (bool en) _volume->set_display_to_user (true); add_processor (_volume, PostFader, NULL, true); _volume->activate (); - main_outs()->add_gain (boost::shared_ptr ()); + main_outs()->set_gain_control (boost::shared_ptr ()); } _volume_applies_to_output = en; _session.set_dirty (); diff --git a/libs/ardour/send.cc b/libs/ardour/send.cc index f183cd98a3..cdb6471608 100644 --- a/libs/ardour/send.cc +++ b/libs/ardour/send.cc @@ -98,11 +98,11 @@ Send::Send (Session& s, boost::shared_ptr p, boost::shared_ptr gl (new AutomationList (Evoral::Parameter (BusSendLevel), time_domain())); - _gain_control = boost::shared_ptr (new GainControl (_session, Evoral::Parameter(BusSendLevel), gl)); - _gain_control->set_flag (Controllable::InlineControl); - add_control (_gain_control); + set_gain_control (boost::shared_ptr (new GainControl (_session, Evoral::Parameter(BusSendLevel), gl))); + + gain_control ()->set_flag (Controllable::InlineControl); + add_control (gain_control ()); - _amp.reset (new Amp (_session, _("Fader"), _gain_control, true)); _meter.reset (new PeakMeter (_session, name())); _send_delay.reset (new DelayLine (_session, "Send-" + name())); @@ -110,11 +110,8 @@ Send::Send (Session& s, boost::shared_ptr p, boost::shared_ptr (new AutomationControl (_session, PhaseAutomation, ParameterDescriptor (PhaseAutomation), - boost::shared_ptr(new AutomationList(Evoral::Parameter(PhaseAutomation), time_domain())), - "polarity-invert")); - //_polarity_control->set_flag (Controllable::InlineControl); - add_control (_polarity_control); + set_polarity_control (boost::shared_ptr (new AutomationControl (_session, PhaseAutomation, ParameterDescriptor (PhaseAutomation), boost::shared_ptr(new AutomationList(Evoral::Parameter(PhaseAutomation), time_domain())), "polarity-invert"))); + add_control (polarity_control ()); } if (panner_shell()) { @@ -134,20 +131,18 @@ Send::~Send () void Send::activate () { - _amp->activate (); _meter->activate (); - Processor::activate (); + Delivery::activate (); } void Send::deactivate () { - _amp->deactivate (); _meter->deactivate (); _meter->reset (); - Processor::deactivate (); + Delivery::deactivate (); } samplecnt_t @@ -257,22 +252,16 @@ Send::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sample, do sendbufs.read_from (bufs, nframes); assert(sendbufs.count() == bufs.count()); - /* gain control */ - - _amp->set_gain_automation_buffer (_session.send_gain_automation_buffer ()); - _amp->setup_gain_automation (start_sample, end_sample, nframes); - _amp->run (sendbufs, start_sample, end_sample, speed, nframes, true); - _send_delay->run (sendbufs, start_sample, end_sample, speed, nframes, true); - /* deliver to outputs */ + /* deliver to outputs (and apply gain) */ Delivery::run (sendbufs, start_sample, end_sample, speed, nframes, true); /* consider metering */ if (_metering) { - if (_amp->gain_control()->get_value() == 0) { + if (gain_control()->get_value() == 0) { _meter->reset(); } else { _meter->run (*_output_buffers, start_sample, end_sample, speed, nframes, true); @@ -297,7 +286,7 @@ Send::state () const node.set_property ("selfdestruct", _remove_on_disconnect); - node.add_child_nocopy (_gain_control->get_state()); + node.add_child_nocopy (gain_control ()->get_state()); return node; } @@ -317,7 +306,7 @@ Send::set_state (const XMLNode& node, int version) /* old versions had a single Controllable only, and it was * not always a "gaincontrol" */ - _gain_control->set_state (*i, version); + gain_control()->set_state (*i, version); break; } @@ -326,7 +315,7 @@ Send::set_state (const XMLNode& node, int version) continue; } if (control_name == "gaincontrol" /* gain_control_name (BusSendLevel) */) { - _gain_control->set_state (*i, version); + gain_control ()->set_state (*i, version); break; } } @@ -347,8 +336,8 @@ Send::set_state (const XMLNode& node, int version) XMLNode* gain_node; nn = processor; if ((gain_node = nn->child (Controllable::xml_node_name.c_str ())) != 0) { - _gain_control->set_state (*gain_node, version); - _gain_control->set_flags (Controllable::InlineControl); + gain_control ()->set_state (*gain_node, version); + gain_control ()->set_flags (Controllable::InlineControl); } } } @@ -385,7 +374,7 @@ Send::set_state (const XMLNode& node, int version) } XMLNode xn (**i); xn.set_property ("automation-id", EventTypeMap::instance().to_symbol(Evoral::Parameter (BusSendLevel))); - _gain_control->alist()->set_state (xn, version); + gain_control()->alist()->set_state (xn, version); break; } } @@ -508,11 +497,7 @@ Send::configure_io (ChanCount in, ChanCount out) ChanCount send_count = in; send_count.set(DataType::AUDIO, pan_outs()); - if (!_amp->configure_io (in, out)) { - return false; - } - - if (!Processor::configure_io (in, out)) { + if (!Delivery::configure_io (in, out)) { return false; } diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index 52b2ad3fe9..7f2de21938 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -3390,7 +3390,7 @@ Session::globally_set_send_gains_to_zero (boost::shared_ptr dest) for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { if ((s = (*i)->internal_send_for (dest)) != 0) { - s->amp()->gain_control()->set_value (GAIN_COEFF_ZERO, Controllable::NoGroup); + s->gain_control()->set_value (GAIN_COEFF_ZERO, Controllable::NoGroup); } } } @@ -3403,7 +3403,7 @@ Session::globally_set_send_gains_to_unity (boost::shared_ptr dest) for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { if ((s = (*i)->internal_send_for (dest)) != 0) { - s->amp()->gain_control()->set_value (GAIN_COEFF_UNITY, Controllable::NoGroup); + s->gain_control()->set_value (GAIN_COEFF_UNITY, Controllable::NoGroup); } } } @@ -3416,7 +3416,7 @@ Session::globally_set_send_gains_from_track(boost::shared_ptr dest) for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { if ((s = (*i)->internal_send_for (dest)) != 0) { - s->amp()->gain_control()->set_value ((*i)->gain_control()->get_value(), Controllable::NoGroup); + s->gain_control()->set_value ((*i)->gain_control()->get_value(), Controllable::NoGroup); } } } diff --git a/libs/surfaces/osc/osc.cc b/libs/surfaces/osc/osc.cc index 0b97266e6d..44487107cd 100644 --- a/libs/surfaces/osc/osc.cc +++ b/libs/surfaces/osc/osc.cc @@ -3255,8 +3255,7 @@ OSC::route_get_sends(lo_message msg) { lo_message_add_int32(reply, get_sid(isend->target_route(), get_address(msg))); lo_message_add_string(reply, isend->name().c_str()); lo_message_add_int32(reply, i); - boost::shared_ptr a = isend->amp(); - lo_message_add_float(reply, a->gain_control()->internal_to_interface (a->gain_control()->get_value())); + lo_message_add_float(reply, isend->gain_control()->internal_to_interface (isend->gain_control()->get_value())); lo_message_add_int32(reply, p->active() ? 1 : 0); } } @@ -3312,12 +3311,10 @@ OSC::route_get_receives(lo_message msg) { boost::shared_ptr isend = boost::dynamic_pointer_cast (p); if (isend) { if( isend->target_route()->id() == r->id()){ - boost::shared_ptr a = isend->amp(); - lo_message_add_int32(reply, get_sid(tr, get_address(msg))); lo_message_add_string(reply, tr->name().c_str()); lo_message_add_int32(reply, j); - lo_message_add_float(reply, a->gain_control()->internal_to_interface (a->gain_control()->get_value())); + lo_message_add_float(reply, isend->gain_control()->internal_to_interface (isend->gain_control()->get_value())); lo_message_add_int32(reply, p->active() ? 1 : 0); } }