mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-09 00:04:56 +01:00
Clean up and hopefully fix handling of logarithmic plugin parameters (fixes #3769).
git-svn-id: svn://localhost/ardour2/branches/3.0@8850 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
4aaa507472
commit
ea11968f95
11 changed files with 105 additions and 107 deletions
|
|
@ -94,20 +94,20 @@ AutomationController::get_label (double& xpos)
|
||||||
void
|
void
|
||||||
AutomationController::display_effective_value()
|
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;
|
_ignore_change = true;
|
||||||
_adjustment->set_value (value);
|
_adjustment->set_value (ui_value);
|
||||||
_ignore_change = false;
|
_ignore_change = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
AutomationController::value_adjusted()
|
AutomationController::value_adjusted ()
|
||||||
{
|
{
|
||||||
if (!_ignore_change) {
|
if (!_ignore_change) {
|
||||||
_controllable->set_value(_adjustment->get_value());
|
_controllable->set_value (_controllable->ui_to_user (_adjustment->get_value()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -494,19 +494,10 @@ GenericPluginUI::build_control_ui (guint32 port_index, boost::shared_ptr<Automat
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Adjustment* adj = control_ui->controller->adjustment();
|
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_lower (pc->user_to_ui (desc.lower));
|
||||||
adj->set_upper (desc.upper);
|
adj->set_upper (pc->user_to_ui (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_step_increment (desc.step);
|
adj->set_step_increment (desc.step);
|
||||||
adj->set_page_increment (desc.largestep);
|
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_name (X_("PluginSlider"));
|
||||||
control_ui->controller->set_style (BarController::LeftToRight);
|
control_ui->controller->set_style (BarController::LeftToRight);
|
||||||
control_ui->controller->set_use_parent (true);
|
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->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));
|
control_ui->controller->StopGesture.connect (sigc::bind (sigc::mem_fun(*this, &GenericPluginUI::stop_touch), control_ui));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (control_ui->logarithmic) {
|
adj->set_value (pc->plugin_to_ui (plugin->get_parameter (port_index)));
|
||||||
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));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* XXX memory leak: SliderController not destroyed by ControlUI
|
/* XXX memory leak: SliderController not destroyed by ControlUI
|
||||||
destructor, and manage() reports object hierarchy
|
destructor, and manage() reports object hierarchy
|
||||||
|
|
|
||||||
|
|
@ -213,7 +213,6 @@ class GenericPluginUI : public PlugUIBase, public Gtk::VBox
|
||||||
boost::shared_ptr<AutomationController> controller;
|
boost::shared_ptr<AutomationController> controller;
|
||||||
Gtkmm2ext::ClickBox* clickbox;
|
Gtkmm2ext::ClickBox* clickbox;
|
||||||
Gtk::Label label;
|
Gtk::Label label;
|
||||||
bool logarithmic;
|
|
||||||
bool update_pending;
|
bool update_pending;
|
||||||
char ignore_change;
|
char ignore_change;
|
||||||
Gtk::Button automate_button;
|
Gtk::Button automate_button;
|
||||||
|
|
|
||||||
|
|
@ -74,21 +74,26 @@ public:
|
||||||
return ((ARDOUR::AutomationList*)_list.get())->stop_touch(mark, when);
|
return ((ARDOUR::AutomationList*)_list.get())->stop_touch(mark, when);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Set the value and do the right thing based on automation state
|
void set_value (double);
|
||||||
* (e.g. record if necessary, etc.)
|
double get_value () const;
|
||||||
*/
|
|
||||||
void set_value(double val);
|
|
||||||
|
|
||||||
/** Get the current effective value based on automation state.
|
|
||||||
*/
|
|
||||||
double get_value() const;
|
|
||||||
|
|
||||||
double lower() const { return parameter().min(); }
|
double lower() const { return parameter().min(); }
|
||||||
double upper() const { return parameter().max(); }
|
double upper() const { return parameter().max(); }
|
||||||
|
|
||||||
const ARDOUR::Session& session() const { return _session; }
|
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:
|
protected:
|
||||||
|
|
||||||
ARDOUR::Session& _session;
|
ARDOUR::Session& _session;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -90,8 +90,8 @@ class Plugin : public PBD::StatefulDestructible, public Latent
|
||||||
bool logarithmic;
|
bool logarithmic;
|
||||||
bool sr_dependent;
|
bool sr_dependent;
|
||||||
std::string label;
|
std::string label;
|
||||||
float lower;
|
float lower; ///< if this is a frequency, it will be in Hz (not a fraction of the sample rate)
|
||||||
float upper;
|
float upper; ///< if this is a frequency, it will be in Hz (not a fraction of the sample rate)
|
||||||
float step;
|
float step;
|
||||||
float smallstep;
|
float smallstep;
|
||||||
float largestep;
|
float largestep;
|
||||||
|
|
|
||||||
|
|
@ -85,13 +85,16 @@ class PluginInsert : public Processor
|
||||||
double get_value (void) const;
|
double get_value (void) const;
|
||||||
XMLNode& get_state();
|
XMLNode& get_state();
|
||||||
|
|
||||||
bool logarithmic () const {
|
double user_to_ui (double) const;
|
||||||
return _logarithmic;
|
double ui_to_user (double) const;
|
||||||
}
|
double plugin_to_ui (double) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
double user_to_plugin (double) const;
|
||||||
|
|
||||||
PluginInsert* _plugin;
|
PluginInsert* _plugin;
|
||||||
bool _logarithmic;
|
bool _logarithmic;
|
||||||
|
bool _sr_dependent;
|
||||||
bool _toggled;
|
bool _toggled;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -117,8 +120,6 @@ class PluginInsert : public Processor
|
||||||
return _splitting;
|
return _splitting;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string value_as_string (boost::shared_ptr<AutomationControl>) const;
|
|
||||||
|
|
||||||
PBD::Signal2<void,BufferSet*, BufferSet*> AnalysisDataGathered;
|
PBD::Signal2<void,BufferSet*, BufferSet*> AnalysisDataGathered;
|
||||||
/** Emitted when the return value of splitting () has changed */
|
/** Emitted when the return value of splitting () has changed */
|
||||||
PBD::Signal0<void> SplittingChanged;
|
PBD::Signal0<void> SplittingChanged;
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ AutomationControl::AutomationControl(
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Get the current effective `user' value based on automation state */
|
||||||
double
|
double
|
||||||
AutomationControl::get_value() const
|
AutomationControl::get_value() const
|
||||||
{
|
{
|
||||||
|
|
@ -47,6 +48,10 @@ AutomationControl::get_value() const
|
||||||
return Control::get_double (from_list, _session.transport_frame());
|
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
|
void
|
||||||
AutomationControl::set_value(double value)
|
AutomationControl::set_value(double value)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -178,32 +178,17 @@ LadspaPlugin::default_value (uint32_t port)
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (LADSPA_IS_HINT_DEFAULT_LOW(prh[port].HintDescriptor)) {
|
else if (LADSPA_IS_HINT_DEFAULT_LOW(prh[port].HintDescriptor)) {
|
||||||
if (LADSPA_IS_HINT_LOGARITHMIC(prh[port].HintDescriptor)) {
|
ret = prh[port].LowerBound * 0.75f + prh[port].UpperBound * 0.25f;
|
||||||
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;
|
|
||||||
}
|
|
||||||
bounds_given = true;
|
bounds_given = true;
|
||||||
sr_scaling = true;
|
sr_scaling = true;
|
||||||
}
|
}
|
||||||
else if (LADSPA_IS_HINT_DEFAULT_MIDDLE(prh[port].HintDescriptor)) {
|
else if (LADSPA_IS_HINT_DEFAULT_MIDDLE(prh[port].HintDescriptor)) {
|
||||||
if (LADSPA_IS_HINT_LOGARITHMIC(prh[port].HintDescriptor)) {
|
ret = prh[port].LowerBound * 0.5f + prh[port].UpperBound * 0.5f;
|
||||||
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;
|
|
||||||
}
|
|
||||||
bounds_given = true;
|
bounds_given = true;
|
||||||
sr_scaling = true;
|
sr_scaling = true;
|
||||||
}
|
}
|
||||||
else if (LADSPA_IS_HINT_DEFAULT_HIGH(prh[port].HintDescriptor)) {
|
else if (LADSPA_IS_HINT_DEFAULT_HIGH(prh[port].HintDescriptor)) {
|
||||||
if (LADSPA_IS_HINT_LOGARITHMIC(prh[port].HintDescriptor)) {
|
ret = prh[port].LowerBound * 0.25f + prh[port].UpperBound * 0.75f;
|
||||||
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;
|
|
||||||
}
|
|
||||||
bounds_given = true;
|
bounds_given = true;
|
||||||
sr_scaling = true;
|
sr_scaling = true;
|
||||||
}
|
}
|
||||||
|
|
@ -314,6 +299,7 @@ LadspaPlugin::set_parameter (uint32_t which, float val)
|
||||||
Plugin::set_parameter (which, val);
|
Plugin::set_parameter (which, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @return `plugin' value */
|
||||||
float
|
float
|
||||||
LadspaPlugin::get_parameter (uint32_t which) const
|
LadspaPlugin::get_parameter (uint32_t which) const
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -277,6 +277,7 @@ Plugin::load_preset (PresetRecord r)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @param val `plugin' value */
|
||||||
void
|
void
|
||||||
Plugin::set_parameter (uint32_t which, float val)
|
Plugin::set_parameter (uint32_t which, float val)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1030,49 +1030,73 @@ PluginInsert::PluginControl::PluginControl (PluginInsert* p, const Evoral::Param
|
||||||
Plugin::ParameterDescriptor desc;
|
Plugin::ParameterDescriptor desc;
|
||||||
p->plugin(0)->get_parameter_descriptor (param.id(), desc);
|
p->plugin(0)->get_parameter_descriptor (param.id(), desc);
|
||||||
_logarithmic = desc.logarithmic;
|
_logarithmic = desc.logarithmic;
|
||||||
|
_sr_dependent = desc.sr_dependent;
|
||||||
_toggled = desc.toggled;
|
_toggled = desc.toggled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @param val `user' value */
|
||||||
void
|
void
|
||||||
PluginInsert::PluginControl::set_value (double val)
|
PluginInsert::PluginControl::set_value (double user_val)
|
||||||
{
|
{
|
||||||
/* FIXME: probably should be taking out some lock here.. */
|
/* FIXME: probably should be taking out some lock here.. */
|
||||||
|
|
||||||
if (_toggled) {
|
double const plugin_val = user_to_plugin (user_val);
|
||||||
if (val > 0.5) {
|
|
||||||
val = 1.0;
|
|
||||||
} else {
|
|
||||||
val = 0.0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
|
|
||||||
/*const float range = _list->get_max_y() - _list->get_min_y();
|
for (Plugins::iterator i = _plugin->_plugins.begin(); i != _plugin->_plugins.end(); ++i) {
|
||||||
const float lower = _list->get_min_y();
|
(*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);
|
|
||||||
}
|
|
||||||
|
|
||||||
val = exp(log_lower + log(range) * val);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Plugins::iterator i = _plugin->_plugins.begin();
|
|
||||||
i != _plugin->_plugins.end(); ++i) {
|
|
||||||
(*i)->set_parameter (_list->parameter().id(), val);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::shared_ptr<Plugin> iasp = _plugin->_impulseAnalysisPlugin.lock();
|
boost::shared_ptr<Plugin> iasp = _plugin->_impulseAnalysisPlugin.lock();
|
||||||
if (iasp) {
|
if (iasp) {
|
||||||
iasp->set_parameter (_list->parameter().id(), val);
|
iasp->set_parameter (_list->parameter().id(), plugin_val);
|
||||||
}
|
}
|
||||||
|
|
||||||
AutomationControl::set_value(val);
|
AutomationControl::set_value (user_val);
|
||||||
|
}
|
||||||
|
|
||||||
|
double
|
||||||
|
PluginInsert::PluginControl::user_to_plugin (double val) const
|
||||||
|
{
|
||||||
|
if (_sr_dependent) {
|
||||||
|
val /= _session.frame_rate ();
|
||||||
|
}
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
double
|
||||||
|
PluginInsert::PluginControl::user_to_ui (double val) const
|
||||||
|
{
|
||||||
|
if (_logarithmic) {
|
||||||
|
if (val > 0) {
|
||||||
|
val = log (val);
|
||||||
|
} else {
|
||||||
|
val = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 ();
|
||||||
|
}
|
||||||
|
|
||||||
|
return user_to_ui (val);
|
||||||
}
|
}
|
||||||
|
|
||||||
XMLNode&
|
XMLNode&
|
||||||
|
|
@ -1164,19 +1188,3 @@ PluginInsert::set_splitting (bool s)
|
||||||
_splitting = s;
|
_splitting = s;
|
||||||
SplittingChanged (); /* EMIT SIGNAL */
|
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 ();
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,18 @@ class Controllable : public PBD::StatefulDestructible {
|
||||||
Controllable (const std::string& name, Flag f = Flag (0));
|
Controllable (const std::string& name, Flag f = Flag (0));
|
||||||
virtual ~Controllable() { Destroyed (this); }
|
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;
|
virtual void set_value (double) = 0;
|
||||||
|
/** @return `user' value */
|
||||||
virtual double get_value (void) const = 0;
|
virtual double get_value (void) const = 0;
|
||||||
|
|
||||||
PBD::Signal0<void> LearningFinished;
|
PBD::Signal0<void> LearningFinished;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue