change VCA model to facilitate Harrison *and* SSL designs

This commit is contained in:
Paul Davis 2016-02-28 11:57:18 -05:00
parent 3daad04936
commit 405f9fc712
3 changed files with 78 additions and 26 deletions

View file

@ -20,7 +20,10 @@
#define __ardour_gain_control_h__
#include <string>
#include <list>
#include <boost/shared_ptr.hpp>
#include <glibmm/threads.h>
#include "pbd/controllable.h"
@ -51,12 +54,18 @@ class LIBARDOUR_API GainControl : public AutomationControl {
double lower_db;
double range_db;
boost::shared_ptr<GainControl> master() const { return _master; }
void set_master (boost::shared_ptr<GainControl>);
void add_master (boost::shared_ptr<GainControl>);
void remove_master (boost::shared_ptr<GainControl>);
void clear_masters ();
private:
void _set_value (double val, PBD::Controllable::GroupControlDisposition group_override);
boost::shared_ptr<GainControl> _master;
gain_t get_master_gain () const;
mutable Glib::Threads::Mutex master_lock;
typedef std::list<boost::shared_ptr<GainControl> > Masters;
Masters _masters;
};
} /* namespace */

View file

@ -39,10 +39,17 @@ GainControl::GainControl (Session& session, const Evoral::Parameter &param, boos
double
GainControl::get_value() const
{
if (!_master) {
Glib::Threads::Mutex::Lock sm (master_lock, Glib::Threads::TRY_LOCK);
if (sm.locked()) {
if (_masters.empty()) {
return AutomationControl::get_value();
}
return AutomationControl::get_value() * _master->get_value();
return AutomationControl::get_value() * get_master_gain ();
} else {
/* could not take lock */
return AutomationControl::get_value ();
}
}
void
@ -106,25 +113,31 @@ GainControl::get_user_string () const
return std::string(theBuf);
}
void
GainControl::set_master (boost::shared_ptr<GainControl> m)
gain_t
GainControl::get_master_gain () const
{
double old_master_val;
/* Master lock MUST be held */
if (_master) {
old_master_val = _master->get_value();
} else {
old_master_val = 1.0;
gain_t g = 1.0;
for (Masters::const_iterator m = _masters.begin(); m != _masters.end(); ++m) {
g *= (*m)->get_value ();
}
_master = m;
return g;
}
double new_master_val;
void
GainControl::add_master (boost::shared_ptr<GainControl> m)
{
gain_t old_master_val;
gain_t new_master_val;
if (_master) {
new_master_val = _master->get_value();
} else {
new_master_val = 1.0;
{
Glib::Threads::Mutex::Lock lm (master_lock);
old_master_val = get_master_gain ();
_masters.push_back (m);
new_master_val = get_master_gain ();
}
if (old_master_val != new_master_val) {
@ -132,3 +145,38 @@ GainControl::set_master (boost::shared_ptr<GainControl> m)
}
}
void
GainControl::remove_master (boost::shared_ptr<GainControl> m)
{
gain_t old_master_val;
gain_t new_master_val;
{
Glib::Threads::Mutex::Lock lm (master_lock);
old_master_val = get_master_gain ();
_masters.remove (m);
new_master_val = get_master_gain ();
}
if (old_master_val != new_master_val) {
Changed(); /* EMIT SIGNAL */
}
}
void
GainControl::clear_masters ()
{
gain_t old_master_val;
gain_t new_master_val;
{
Glib::Threads::Mutex::Lock lm (master_lock);
old_master_val = get_master_gain ();
_masters.clear ();
new_master_val = get_master_gain ();
}
if (old_master_val != new_master_val) {
Changed(); /* EMIT SIGNAL */
}
}

View file

@ -47,16 +47,11 @@ VCA::get_value() const
void
VCA::add (boost::shared_ptr<Route> r)
{
boost::dynamic_pointer_cast<GainControl>(r->gain_control())->set_master (_control);
boost::dynamic_pointer_cast<GainControl>(r->gain_control())->add_master (_control);
}
void
VCA::remove (boost::shared_ptr<Route> r)
{
boost::shared_ptr<GainControl> route_gain = boost::dynamic_pointer_cast<GainControl>(r->gain_control());
boost::shared_ptr<GainControl> current_master = route_gain->master();
if (current_master == _control) {
route_gain->set_master (boost::shared_ptr<GainControl>());
}
r->gain_control()->remove_master (_control);
}