2 Copyright (C) 2006-2016 Paul Davis
4 This program is free software; you can redistribute it and/or modify it
5 under the terms of the GNU General Public License as published by the Free
6 Software Foundation; either version 2 of the License, or (at your option)
9 This program is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation, Inc.,
16 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include "pbd/convert.h"
22 #include "pbd/strsplit.h"
24 #include "ardour/dB.h"
25 #include "ardour/gain_control.h"
26 #include "ardour/session.h"
27 #include "ardour/vca.h"
28 #include "ardour/vca_manager.h"
32 using namespace ARDOUR;
35 GainControl::GainControl (Session& session, const Evoral::Parameter ¶m, boost::shared_ptr<AutomationList> al)
36 : SlavableAutomationControl (session, param, ParameterDescriptor(param),
37 al ? al : boost::shared_ptr<AutomationList> (new AutomationList (param)),
38 param.type() == GainAutomation ? X_("gaincontrol") : X_("trimcontrol")) {
40 alist()->reset_default (1.0);
42 lower_db = accurate_coefficient_to_dB (_desc.lower);
43 range_db = accurate_coefficient_to_dB (_desc.upper) - lower_db;
47 GainControl::internal_to_interface (double v) const
49 if (_desc.type == GainAutomation) {
50 return gain_to_slider_position (v);
52 return (accurate_coefficient_to_dB (v) - lower_db) / range_db;
57 GainControl::interface_to_internal (double v) const
59 if (_desc.type == GainAutomation) {
60 return slider_position_to_gain (v);
62 return dB_to_coefficient (lower_db + v * range_db);
67 GainControl::internal_to_user (double v) const
69 return accurate_coefficient_to_dB (v);
73 GainControl::user_to_internal (double u) const
75 return dB_to_coefficient (u);
79 GainControl::get_user_string () const
81 char theBuf[32]; sprintf( theBuf, _("%3.1f dB"), accurate_coefficient_to_dB (get_value()));
82 return std::string(theBuf);
86 GainControl::inc_gain (gain_t factor)
88 /* To be used ONLY when doing group-relative gain adjustment, from
89 * ControlGroup::set_group_values().
92 const float desired_gain = user_double();
94 if (fabsf (desired_gain) < GAIN_COEFF_SMALL) {
95 // really?! what's the idea here?
96 actually_set_value (0.000001f + (0.000001f * factor), Controllable::ForGroup);
98 actually_set_value (desired_gain + (desired_gain * factor), Controllable::ForGroup);
103 GainControl::recompute_masters_ratios (double val)
105 /* Master WRITE lock must be held */
107 /* V' is the new gain value for this
109 Mv(n) is the return value of ::get_value() for the n-th master
110 Mr(n) is the return value of ::ratio() for the n-th master record
112 the slave should return V' on the next call to ::get_value().
114 but the value is determined by the masters, so we know:
116 V' = (Mv(1) * Mr(1)) * (Mv(2) * Mr(2)) * ... * (Mv(n) * Mr(n))
120 Mr(1) * Mr(2) * ... * (Mr(n) = V' / (Mv(1) * Mv(2) * ... * Mv(n))
122 if we make all ratios equal (i.e. each master contributes the same
123 fraction of its own gain level to make the final slave gain), then we
126 pow (Mr(n), n) = V' / (Mv(1) * Mv(2) * ... * Mv(n))
130 Mr(n) = pow ((V' / (Mv(1) * Mv(2) * ... * Mv(n))), 1/n)
132 Mr(n) is the new ratio number for the slaves
136 const double nmasters = _masters.size();
137 double masters_total_gain_coefficient = 1.0;
139 for (Masters::iterator mr = _masters.begin(); mr != _masters.end(); ++mr) {
140 masters_total_gain_coefficient *= mr->second.master()->get_value();
143 const double new_universal_ratio = pow ((val / masters_total_gain_coefficient), (1.0/nmasters));
145 for (Masters::iterator mr = _masters.begin(); mr != _masters.end(); ++mr) {
146 mr->second.reset_ratio (new_universal_ratio);
151 GainControl::get_state ()
153 XMLNode& node (AutomationControl::get_state());
156 /* store VCA master IDs */
161 Glib::Threads::RWLock::ReaderLock lm (master_lock);
162 for (Masters::const_iterator mr = _masters.begin(); mr != _masters.end(); ++mr) {
166 str += PBD::to_string (mr->first, std::dec);
171 node.add_property (X_("masters"), str);
179 GainControl::set_state (XMLNode const& node, int version)
181 return AutomationControl::set_state (node, version);