Clean up and hopefully fix handling of logarithmic plugin parameters (fixes #3769).
authorCarl Hetherington <carl@carlh.net>
Tue, 15 Feb 2011 01:42:48 +0000 (01:42 +0000)
committerCarl Hetherington <carl@carlh.net>
Tue, 15 Feb 2011 01:42:48 +0000 (01:42 +0000)
git-svn-id: svn://localhost/ardour2/branches/3.0@8850 d708f5d6-7413-0410-9779-e7cbd77b26cf

gtk2_ardour/automation_controller.cc
gtk2_ardour/generic_pluginui.cc
gtk2_ardour/plugin_ui.h
libs/ardour/ardour/automation_control.h
libs/ardour/ardour/plugin.h
libs/ardour/ardour/plugin_insert.h
libs/ardour/automation_control.cc
libs/ardour/ladspa_plugin.cc
libs/ardour/plugin.cc
libs/ardour/plugin_insert.cc
libs/pbd/pbd/controllable.h

index 5c00d5a779296f52362775104e60b7c17986fa27..75239f7f80846577173fb34e24be4b52d844f4a9 100644 (file)
@@ -94,20 +94,20 @@ AutomationController::get_label (double& xpos)
 void
 AutomationController::display_effective_value()
 {
-       float value = _controllable->get_value();
+       double const ui_value = _controllable->user_to_ui (_controllable->get_value());
 
-       if (_adjustment->get_value() != value) {
+       if (_adjustment->get_value() != ui_value) {
                _ignore_change = true;
-               _adjustment->set_value (value);
+               _adjustment->set_value (ui_value);
                _ignore_change = false;
        }
 }
 
 void
-AutomationController::value_adjusted()
+AutomationController::value_adjusted ()
 {
        if (!_ignore_change) {
-               _controllable->set_value(_adjustment->get_value());
+               _controllable->set_value (_controllable->ui_to_user (_adjustment->get_value()));
        }
 }
 
index 9204912a365b5d03d8d7c678419baf7e2d054ce0..fdf0d62482d86cd7a85a806afbf31935e6fb3d77 100644 (file)
@@ -494,19 +494,10 @@ GenericPluginUI::build_control_ui (guint32 port_index, boost::shared_ptr<Automat
                */
 
                 Adjustment* adj = control_ui->controller->adjustment();
+               boost::shared_ptr<PluginInsert::PluginControl> pc = boost::dynamic_pointer_cast<PluginInsert::PluginControl> (control_ui->control);
 
-               adj->set_lower (desc.lower);
-               adj->set_upper (desc.upper);
-
-               control_ui->logarithmic = desc.logarithmic;
-
-               if (control_ui->logarithmic) {
-                       if (adj->get_lower() == 0.0) {
-                               adj->set_lower (adj->get_upper()/10000);
-                       }
-                       adj->set_upper (log(adj->get_upper()));
-                       adj->set_lower (log(adj->get_lower()));
-               }
+               adj->set_lower (pc->user_to_ui (desc.lower));
+               adj->set_upper (pc->user_to_ui (desc.upper));
 
                adj->set_step_increment (desc.step);
                adj->set_page_increment (desc.largestep);
@@ -522,23 +513,14 @@ GenericPluginUI::build_control_ui (guint32 port_index, boost::shared_ptr<Automat
                        control_ui->controller->set_name (X_("PluginSlider"));
                        control_ui->controller->set_style (BarController::LeftToRight);
                        control_ui->controller->set_use_parent (true);
-                        control_ui->controller->set_logarithmic (control_ui->logarithmic);
+                        control_ui->controller->set_logarithmic (desc.logarithmic);
 
                        control_ui->controller->StartGesture.connect (sigc::bind (sigc::mem_fun(*this, &GenericPluginUI::start_touch), control_ui));
                        control_ui->controller->StopGesture.connect (sigc::bind (sigc::mem_fun(*this, &GenericPluginUI::stop_touch), control_ui));
 
                }
 
-               if (control_ui->logarithmic) {
-                        double val = plugin->get_parameter (port_index);
-                        if (isnan (val) || val <= 0.0) {
-                                adj->set_value (0.0);
-                        } else {
-                                adj->set_value (log(val));
-                        }
-               } else{
-                       adj->set_value(plugin->get_parameter(port_index));
-               }
+               adj->set_value (pc->plugin_to_ui (plugin->get_parameter (port_index)));
 
                /* XXX memory leak: SliderController not destroyed by ControlUI
                   destructor, and manage() reports object hierarchy
index cdb29bcd82278e1e3f517ef0d926d75f31f78b9d..31a00ad9b36d2714f20c5d4f63852017a7be6c64 100644 (file)
@@ -213,7 +213,6 @@ class GenericPluginUI : public PlugUIBase, public Gtk::VBox
                boost::shared_ptr<AutomationController> controller;
                Gtkmm2ext::ClickBox*                    clickbox;
                Gtk::Label                              label;
-               bool                                    logarithmic;
                bool                                    update_pending;
                char                                    ignore_change;
                Gtk::Button                             automate_button;
index 006e74346f734d8a7fd4efd9ff82f41cedffb242..d786f28ab6d403fa05198aa43e48369633268f70 100644 (file)
@@ -74,21 +74,26 @@ public:
                return ((ARDOUR::AutomationList*)_list.get())->stop_touch(mark, when);
        }
 
-       /** Set the value and do the right thing based on automation state
-        * (e.g. record if necessary, etc.)
-        */
-       void set_value(double val);
-
-       /** Get the current effective value based on automation state.
-        */
-       double get_value() const;
+       void set_value (double);
+       double get_value () const;
 
         double lower() const { return parameter().min(); }
         double upper() const { return parameter().max(); }
 
         const ARDOUR::Session& session() const { return _session; }
 
+       /** Convert user values to UI values.  See pbd/controllable.h */
+       virtual double user_to_ui (double val) const {
+               return val;
+       }
+
+       /** Convert UI values to user values.  See pbd/controllable.h */
+       virtual double ui_to_user (double val) const {
+               return val;
+       }
+       
 protected:
+       
        ARDOUR::Session& _session;
 };
 
index 00ed6bdc94352d9eb7919d10434d4089fe4bc9cd..f2af0360fca76b4dcba4a25be0e4cd273f7c42a7 100644 (file)
@@ -90,8 +90,8 @@ class Plugin : public PBD::StatefulDestructible, public Latent
                bool logarithmic;
                bool sr_dependent;
                std::string label;
-               float lower;
-               float upper;
+               float lower; ///< if this is a frequency, it will be in Hz (not a fraction of the sample rate)
+               float upper; ///< if this is a frequency, it will be in Hz (not a fraction of the sample rate)
                float step;
                float smallstep;
                float largestep;
index ea7a081c22e921bc5bf8b08fa03c4a9ce935bfac..45a04785842f98b18ace04dea0489df51e9ce816 100644 (file)
@@ -85,13 +85,16 @@ class PluginInsert : public Processor
                double get_value (void) const;
                 XMLNode& get_state();
 
-               bool logarithmic () const {
-                       return _logarithmic;
-               }
+               double user_to_ui (double) const;
+               double ui_to_user (double) const;
+               double plugin_to_ui (double) const;
                 
        private:
+               double user_to_plugin (double) const;
+               
                PluginInsert* _plugin;
                bool _logarithmic;
+               bool _sr_dependent;
                bool _toggled;
        };
 
@@ -117,8 +120,6 @@ class PluginInsert : public Processor
                return _splitting;
        }
 
-        std::string value_as_string (boost::shared_ptr<AutomationControl>) const;
-
        PBD::Signal2<void,BufferSet*, BufferSet*> AnalysisDataGathered;
        /** Emitted when the return value of splitting () has changed */
        PBD::Signal0<void> SplittingChanged;
index a1611337fd78f07262a7f272080c8b10289845de..25a18949ee6da616c96ec2cf4ba5641001c1c652 100644 (file)
@@ -40,6 +40,7 @@ AutomationControl::AutomationControl(
 {
 }
 
+/** Get the current effective `user' value based on automation state */
 double
 AutomationControl::get_value() const
 {
@@ -47,6 +48,10 @@ AutomationControl::get_value() const
        return Control::get_double (from_list, _session.transport_frame());
 }
 
+/** Set the value and do the right thing based on automation state
+ *  (e.g. record if necessary, etc.)
+ *  @param value `user' value
+ */
 void
 AutomationControl::set_value(double value)
 {
index 69feed94813c47f1200d3bc18528468eeab9094b..1ea158d7cdeecd91f08c991be3e9a975e011fb81 100644 (file)
@@ -178,32 +178,17 @@ LadspaPlugin::default_value (uint32_t port)
                }
 
                else if (LADSPA_IS_HINT_DEFAULT_LOW(prh[port].HintDescriptor)) {
-                       if (LADSPA_IS_HINT_LOGARITHMIC(prh[port].HintDescriptor)) {
-                               ret = exp(log(prh[port].LowerBound) * 0.75f + log(prh[port].UpperBound) * 0.25f);
-                       }
-                       else {
-                               ret = prh[port].LowerBound * 0.75f + prh[port].UpperBound * 0.25f;
-                       }
+                       ret = prh[port].LowerBound * 0.75f + prh[port].UpperBound * 0.25f;
                        bounds_given = true;
                        sr_scaling = true;
                }
                else if (LADSPA_IS_HINT_DEFAULT_MIDDLE(prh[port].HintDescriptor)) {
-                       if (LADSPA_IS_HINT_LOGARITHMIC(prh[port].HintDescriptor)) {
-                               ret = exp(log(prh[port].LowerBound) * 0.5f + log(prh[port].UpperBound) * 0.5f);
-                       }
-                       else {
-                               ret = prh[port].LowerBound * 0.5f + prh[port].UpperBound * 0.5f;
-                       }
+                       ret = prh[port].LowerBound * 0.5f + prh[port].UpperBound * 0.5f;
                        bounds_given = true;
                        sr_scaling = true;
                }
                else if (LADSPA_IS_HINT_DEFAULT_HIGH(prh[port].HintDescriptor)) {
-                       if (LADSPA_IS_HINT_LOGARITHMIC(prh[port].HintDescriptor)) {
-                               ret = exp(log(prh[port].LowerBound) * 0.25f + log(prh[port].UpperBound) * 0.75f);
-                       }
-                       else {
-                               ret = prh[port].LowerBound * 0.25f + prh[port].UpperBound * 0.75f;
-                       }
+                       ret = prh[port].LowerBound * 0.25f + prh[port].UpperBound * 0.75f;
                        bounds_given = true;
                        sr_scaling = true;
                }
@@ -314,6 +299,7 @@ LadspaPlugin::set_parameter (uint32_t which, float val)
        Plugin::set_parameter (which, val);
 }
 
+/** @return `plugin' value */
 float
 LadspaPlugin::get_parameter (uint32_t which) const
 {
index 75c471d1a427a78889432c386eb22a2e6ea219da..35e57ab63a25cce8e0fc1bc6fa52cd36cb670b5a 100644 (file)
@@ -277,6 +277,7 @@ Plugin::load_preset (PresetRecord r)
        return true;
 }
 
+/** @param val `plugin' value */
 void
 Plugin::set_parameter (uint32_t which, float val)
 {
index a690cce5ccebdd95adb5542bb8e14266621aad73..43df8cc29d8672268afdb9335e929511f791b28e 100644 (file)
@@ -1030,49 +1030,73 @@ PluginInsert::PluginControl::PluginControl (PluginInsert* p, const Evoral::Param
        Plugin::ParameterDescriptor desc;
        p->plugin(0)->get_parameter_descriptor (param.id(), desc);
        _logarithmic = desc.logarithmic;
+       _sr_dependent = desc.sr_dependent;
        _toggled = desc.toggled;
 }
 
+/** @param val `user' value */
 void
-PluginInsert::PluginControl::set_value (double val)
+PluginInsert::PluginControl::set_value (double user_val)
 {
        /* FIXME: probably should be taking out some lock here.. */
 
-       if (_toggled) {
-               if (val > 0.5) {
-                       val = 1.0;
-               } else {
-                       val = 0.0;
-               }
-       } else {
+       double const plugin_val = user_to_plugin (user_val);
 
-               /*const float range = _list->get_max_y() - _list->get_min_y();
-               const float lower = _list->get_min_y();
+       for (Plugins::iterator i = _plugin->_plugins.begin(); i != _plugin->_plugins.end(); ++i) {
+               (*i)->set_parameter (_list->parameter().id(), plugin_val);
+       }
 
-               if (!_logarithmic) {
-                       val = lower + (range * val);
-               } else {
-                       float log_lower = 0.0f;
-                       if (lower > 0.0f) {
-                               log_lower = log(lower);
-                       }
+       boost::shared_ptr<Plugin> iasp = _plugin->_impulseAnalysisPlugin.lock();
+       if (iasp) {
+               iasp->set_parameter (_list->parameter().id(), plugin_val);
+       }
 
-                       val = exp(log_lower + log(range) * val);
-               }*/
+       AutomationControl::set_value (user_val);
+}
 
+double
+PluginInsert::PluginControl::user_to_plugin (double val) const
+{
+       if (_sr_dependent) {
+               val /= _session.frame_rate ();
        }
+       
+       return val;
+}
 
-       for (Plugins::iterator i = _plugin->_plugins.begin();
-                       i != _plugin->_plugins.end(); ++i) {
-               (*i)->set_parameter (_list->parameter().id(), val);
+double
+PluginInsert::PluginControl::user_to_ui (double val) const
+{
+       if (_logarithmic) {
+               if (val > 0) {
+                       val = log (val);
+               } else {
+                       val = 0;
+               }
        }
 
-       boost::shared_ptr<Plugin> iasp = _plugin->_impulseAnalysisPlugin.lock();
-       if (iasp) {
-               iasp->set_parameter (_list->parameter().id(), val);
+       return val;
+}
+
+double
+PluginInsert::PluginControl::ui_to_user (double val) const
+{
+       if (_logarithmic) {
+               val = exp (val);
+       }
+
+       return val;
+}
+
+/** Convert plugin values to UI values.  See pbd/controllable.h */
+double
+PluginInsert::PluginControl::plugin_to_ui (double val) const
+{
+       if (_sr_dependent) {
+               val = val * _session.frame_rate ();
        }
 
-       AutomationControl::set_value(val);
+       return user_to_ui (val);
 }
 
 XMLNode&
@@ -1164,19 +1188,3 @@ PluginInsert::set_splitting (bool s)
        _splitting = s;
        SplittingChanged (); /* EMIT SIGNAL */
 }
-
-string
-PluginInsert::value_as_string (boost::shared_ptr<AutomationControl> ac) const
-{
-       boost::shared_ptr<PluginControl> pc = boost::dynamic_pointer_cast<PluginControl> (ac);
-       assert (pc);
-
-       stringstream s;
-       if (pc->logarithmic ()) {
-               s << exp (pc->get_value ());
-       } else {
-               s << pc->get_value ();
-       }
-
-       return s.str ();
-}
index d0769ffd01aabb28a90d7d34e4276aacf2bff60d..864a68b1a8f4c2ef2eef446f1d901c771c2576ec 100644 (file)
@@ -45,7 +45,18 @@ class Controllable : public PBD::StatefulDestructible {
        Controllable (const std::string& name, Flag f = Flag (0));
        virtual ~Controllable() { Destroyed (this); }
 
+       /* We express Controllable values in one of three ways:
+        * 1. `user' --- as presented to the user (e.g. dB, Hz etc.)
+        * 2. `UI' --- as used in some cases for the internal representation
+        *    of the UI.  This may be the same as `user', or may be something
+        *    like the natural log of frequency in order that sliders operate
+        *    in a logarithmic fashion.
+        * 3. `plugin' --- as passed to a plugin.
+        */
+
+       /** Set `user' value */
        virtual void set_value (double) = 0;
+       /** @return `user' value */
        virtual double get_value (void) const = 0;
 
        PBD::Signal0<void> LearningFinished;