Implement master/loudness volume processor
This provides for a better user-experience than using a-amp. Particularly since a-amp only has a 20dB range and can be automated.
This commit is contained in:
parent
5b734e819c
commit
e9ff843bb1
|
@ -334,7 +334,20 @@ XMLNode&
|
|||
Amp::state ()
|
||||
{
|
||||
XMLNode& node (Processor::state ());
|
||||
node.set_property("type", _gain_control->parameter().type() == GainAutomation ? "amp" : "trim");
|
||||
switch (_gain_control->parameter().type()) {
|
||||
case GainAutomation:
|
||||
node.set_property("type", "amp");
|
||||
break;
|
||||
case TrimAutomation:
|
||||
node.set_property("type", "trim");
|
||||
break;
|
||||
case MainOutVolume:
|
||||
node.set_property("type", "main-volume");
|
||||
break;
|
||||
default:
|
||||
assert (0);
|
||||
break;
|
||||
}
|
||||
node.add_child_nocopy (_gain_control->get_state());
|
||||
|
||||
return node;
|
||||
|
|
|
@ -503,6 +503,12 @@ public:
|
|||
boost::shared_ptr<GainControl> volume_control() const;
|
||||
boost::shared_ptr<PhaseControl> phase_control() const;
|
||||
|
||||
void set_volume_applies_to_output (bool);
|
||||
|
||||
bool volume_applies_to_output () const {
|
||||
return _volume_applies_to_output;
|
||||
}
|
||||
|
||||
/**
|
||||
Return the first processor that accepts has at least one MIDI input
|
||||
and at least one audio output. In the vast majority of cases, this
|
||||
|
@ -687,9 +693,12 @@ protected:
|
|||
boost::shared_ptr<PhaseControl> _phase_control;
|
||||
boost::shared_ptr<Amp> _amp;
|
||||
boost::shared_ptr<Amp> _trim;
|
||||
boost::shared_ptr<Amp> _volume;
|
||||
boost::shared_ptr<PeakMeter> _meter;
|
||||
boost::shared_ptr<PolarityProcessor> _polarity;
|
||||
|
||||
bool _volume_applies_to_output;
|
||||
|
||||
boost::shared_ptr<DelayLine> _delayline;
|
||||
|
||||
bool is_internal_processor (boost::shared_ptr<Processor>) const;
|
||||
|
|
|
@ -125,6 +125,7 @@ Route::Route (Session& sess, string name, PresentationInfo::Flag flag, DataType
|
|||
, _default_type (default_type)
|
||||
, _instrument_fanned_out (false)
|
||||
, _loop_location (NULL)
|
||||
, _volume_applies_to_output (true)
|
||||
, _track_number (0)
|
||||
, _strict_io (false)
|
||||
, _in_configure_processors (false)
|
||||
|
@ -256,9 +257,10 @@ Route::init ()
|
|||
if (is_master()) {
|
||||
_volume_control.reset (new GainControl (_session, MainOutVolume));
|
||||
_volume_control->set_flag (Controllable::NotAutomatable);
|
||||
if (Config->get_use_master_volume ()) {
|
||||
_main_outs->add_gain (_volume_control);
|
||||
}
|
||||
_main_outs->add_gain (_volume_control);
|
||||
_volume.reset (new Amp (_session, X_("Volume Ctrl"), _volume_control, false));
|
||||
_volume->set_display_to_user (false);
|
||||
_volume->deactivate ();
|
||||
}
|
||||
_main_outs->activate ();
|
||||
|
||||
|
@ -1394,7 +1396,7 @@ Route::clear_processors (Placement p)
|
|||
bool
|
||||
Route::is_internal_processor (boost::shared_ptr<Processor> p) const
|
||||
{
|
||||
if (p == _amp || p == _meter || p == _main_outs || p == _delayline || p == _trim || p == _polarity) {
|
||||
if (p == _amp || p == _meter || p == _main_outs || p == _delayline || p == _trim || p == _polarity || (_volume && p == _volume)) {
|
||||
return true;
|
||||
}
|
||||
#ifdef MIXBUS
|
||||
|
@ -2508,6 +2510,10 @@ Route::state (bool save_template)
|
|||
node->set_property (X_("default-type"), _default_type);
|
||||
node->set_property (X_("strict-io"), _strict_io);
|
||||
|
||||
if (is_master ()) {
|
||||
node->set_property (X_("volume-applies-to-output"), _volume_applies_to_output);
|
||||
}
|
||||
|
||||
node->add_child_nocopy (_presentation_info.get_state());
|
||||
|
||||
node->set_property (X_("active"), _active);
|
||||
|
@ -2705,6 +2711,19 @@ Route::set_state (const XMLNode& node, int version)
|
|||
|
||||
_initial_io_setup = false;
|
||||
|
||||
if (is_master ()) {
|
||||
node.get_property (X_("volume-applies-to-output"), _volume_applies_to_output);
|
||||
if (_volume_applies_to_output) {
|
||||
_volume->deactivate ();
|
||||
_volume->set_display_to_user (false);
|
||||
main_outs()->add_gain (_volume_control);
|
||||
} else {
|
||||
_volume->set_display_to_user (true);
|
||||
_volume->activate ();
|
||||
main_outs()->add_gain (boost::shared_ptr<GainControl> ());
|
||||
}
|
||||
}
|
||||
|
||||
set_processor_state (processor_state, version);
|
||||
|
||||
// this looks up the internal instrument in processors
|
||||
|
@ -3043,6 +3062,10 @@ Route::set_processor_state (const XMLNode& node, int version)
|
|||
} else if (prop->value() == "trim") {
|
||||
_trim->set_state (**niter, version);
|
||||
new_order.push_back (_trim);
|
||||
} else if (prop->value() == "main-volume") {
|
||||
assert (is_master ());
|
||||
_volume->set_state (**niter, version);
|
||||
new_order.push_back (_volume);
|
||||
} else if (prop->value() == "meter") {
|
||||
_meter->set_state (**niter, version);
|
||||
new_order.push_back (_meter);
|
||||
|
@ -4638,6 +4661,32 @@ Route::phase_control() const
|
|||
return _phase_control;
|
||||
}
|
||||
|
||||
void
|
||||
Route::set_volume_applies_to_output (bool en)
|
||||
{
|
||||
if (!is_master () || _volume_applies_to_output == en) {
|
||||
return;
|
||||
}
|
||||
if (en) {
|
||||
_volume->deactivate ();
|
||||
_volume->set_display_to_user (false);
|
||||
main_outs()->add_gain (_volume_control);
|
||||
{
|
||||
/* remove hidden processor */
|
||||
Glib::Threads::Mutex::Lock lx (AudioEngine::instance()->process_lock ());
|
||||
configure_processors (NULL);
|
||||
}
|
||||
processors_changed (RouteProcessorChange ()); /* EMIT SIGNAL */
|
||||
} else {
|
||||
_volume->set_display_to_user (true);
|
||||
add_processor (_volume, PostFader, NULL, true);
|
||||
_volume->activate ();
|
||||
main_outs()->add_gain (boost::shared_ptr<GainControl> ());
|
||||
}
|
||||
_volume_applies_to_output = en;
|
||||
_session.set_dirty ();
|
||||
}
|
||||
|
||||
boost::shared_ptr<AutomationControl>
|
||||
Route::get_control (const Evoral::Parameter& param)
|
||||
{
|
||||
|
|
|
@ -4237,12 +4237,9 @@ Session::config_changed (std::string p, bool ours)
|
|||
last_loopend = 0; /* force locate to refill buffers with new loop boundary data */
|
||||
auto_loop_changed (_locations->auto_loop_location());
|
||||
} else if (p == "use-master-volume") {
|
||||
if (master_volume ()) {
|
||||
bool en = Config->get_use_master_volume ();
|
||||
_master_out->main_outs()->add_gain (en ? master_volume () : boost::shared_ptr<GainControl> ());
|
||||
if (!en) {
|
||||
master_volume ()->set_value (GAIN_COEFF_UNITY, Controllable::NoGroup);
|
||||
}
|
||||
if (master_volume () && !Config->get_use_master_volume ()) {
|
||||
_master_out->set_volume_applies_to_output (true);
|
||||
master_volume ()->set_value (GAIN_COEFF_UNITY, Controllable::NoGroup);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user