Consolidate send/delivery gain control
This moves the _amp from send to delivery (which already applies gain for the master-bus normalization). This generalizes the use of a gain stage for use in port-inserts.
This commit is contained in:
parent
e665d456c3
commit
f3423b8a77
@ -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<PannerShell> panner_shell() const { return _panshell; }
|
||||
boost::shared_ptr<Panner> panner() const;
|
||||
|
||||
void add_gain (boost::shared_ptr<GainControl> gc) {
|
||||
_gain_control = gc;
|
||||
void set_gain_control (boost::shared_ptr<GainControl> gc);
|
||||
|
||||
void set_polarity_control (boost::shared_ptr<AutomationControl> 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<GainControl> gain_control () const {
|
||||
return _gain_control;
|
||||
}
|
||||
|
||||
boost::shared_ptr<AutomationControl> polarity_control () const {
|
||||
return _polarity_control;
|
||||
}
|
||||
|
||||
boost::shared_ptr<Amp> amp() const {
|
||||
return _amp;
|
||||
}
|
||||
|
||||
protected:
|
||||
XMLNode& state () const;
|
||||
|
||||
@ -124,15 +138,16 @@ protected:
|
||||
BufferSet* _output_buffers;
|
||||
gain_t _current_gain;
|
||||
boost::shared_ptr<PannerShell> _panshell;
|
||||
boost::shared_ptr<AutomationControl> _polarity_control;
|
||||
boost::shared_ptr<Amp> _amp;
|
||||
|
||||
gain_t target_gain ();
|
||||
|
||||
private:
|
||||
bool _no_outs_cuz_we_no_monitor;
|
||||
|
||||
boost::shared_ptr<MuteMaster> _mute_master;
|
||||
boost::shared_ptr<GainControl> _gain_control;
|
||||
boost::shared_ptr<MuteMaster> _mute_master;
|
||||
boost::shared_ptr<GainControl> _gain_control;
|
||||
boost::shared_ptr<AutomationControl> _polarity_control;
|
||||
|
||||
static bool panners_legal;
|
||||
static PBD::Signal0<void> PannersLegal;
|
||||
|
@ -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> amp() const { return _amp; }
|
||||
boost::shared_ptr<PeakMeter> meter() const { return _meter; }
|
||||
boost::shared_ptr<GainControl> 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<GainControl> _gain_control;
|
||||
boost::shared_ptr<Amp> _amp;
|
||||
boost::shared_ptr<PeakMeter> _meter;
|
||||
boost::shared_ptr<DelayLine> _send_delay;
|
||||
boost::shared_ptr<DelayLine> _thru_delay;
|
||||
|
@ -187,6 +187,18 @@ Delivery::can_support_io_configuration (const ChanCount& in, ChanCount& out)
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
Delivery::set_gain_control (boost::shared_ptr<GainControl> 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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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<GainControl> ());
|
||||
main_outs()->set_gain_control (boost::shared_ptr<GainControl> ());
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<GainControl> ());
|
||||
main_outs()->set_gain_control (boost::shared_ptr<GainControl> ());
|
||||
}
|
||||
_volume_applies_to_output = en;
|
||||
_session.set_dirty ();
|
||||
|
@ -98,11 +98,11 @@ Send::Send (Session& s, boost::shared_ptr<Pannable> p, boost::shared_ptr<MuteMas
|
||||
//boost_debug_shared_ptr_mark_interesting (this, "send");
|
||||
|
||||
boost::shared_ptr<AutomationList> gl (new AutomationList (Evoral::Parameter (BusSendLevel), time_domain()));
|
||||
_gain_control = boost::shared_ptr<GainControl> (new GainControl (_session, Evoral::Parameter(BusSendLevel), gl));
|
||||
_gain_control->set_flag (Controllable::InlineControl);
|
||||
add_control (_gain_control);
|
||||
set_gain_control (boost::shared_ptr<GainControl> (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<Pannable> p, boost::shared_ptr<MuteMas
|
||||
|
||||
|
||||
if (_role == Delivery::Aux || _role == Delivery::Send) {
|
||||
_polarity_control = boost::shared_ptr<AutomationControl> (new AutomationControl (_session, PhaseAutomation, ParameterDescriptor (PhaseAutomation),
|
||||
boost::shared_ptr<AutomationList>(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<AutomationControl> (new AutomationControl (_session, PhaseAutomation, ParameterDescriptor (PhaseAutomation), boost::shared_ptr<AutomationList>(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;
|
||||
}
|
||||
|
||||
|
@ -3390,7 +3390,7 @@ Session::globally_set_send_gains_to_zero (boost::shared_ptr<Route> 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<Route> 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<Route> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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<Amp> 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<InternalSend> isend = boost::dynamic_pointer_cast<InternalSend> (p);
|
||||
if (isend) {
|
||||
if( isend->target_route()->id() == r->id()){
|
||||
boost::shared_ptr<Amp> 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);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user