From 73ad5c97f2f988868750936ef466564611488494 Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Thu, 6 Jul 2017 16:15:34 +0200 Subject: [PATCH] Consistently set parameter steps. And it's actually mostly moot. interface_to_internal maps any range to 0..1. The GUI could just hardcode min/max 0, 1 and steps 1/30, 1/300. Except for controls that have explicit range-steps & ctrl surfaces. --- libs/ardour/parameter_descriptor.cc | 57 ++++++++++++++--------------- libs/ardour/vst_plugin.cc | 30 +++++++-------- 2 files changed, 42 insertions(+), 45 deletions(-) diff --git a/libs/ardour/parameter_descriptor.cc b/libs/ardour/parameter_descriptor.cc index 3bbc37e95e..7ba89140e9 100644 --- a/libs/ardour/parameter_descriptor.cc +++ b/libs/ardour/parameter_descriptor.cc @@ -162,12 +162,17 @@ ParameterDescriptor::update_steps() lower = upper / 1000.f; } if (logarithmic && (upper <= lower || lower * upper <= 0)) { + /* log-scale params need upper > lower and both values need the same sign */ logarithmic = false; } if (rangesteps < 2) { rangesteps = 0; } if (enumeration) { + /* enums need scale-points. + * The GUI is more restrictive, a dropdown is displayed + * IIF scale_points.size() == (1 + upper - lower) + */ if (!scale_points || scale_points->empty ()) { enumeration = false; } @@ -178,6 +183,13 @@ ParameterDescriptor::update_steps() } } + /* upper == lower does not make any sense */ + if (lower == upper) { + upper = lower + 0.01; // add some arbitrary value + } + + /* set steps */ + if (unit == ParameterDescriptor::MIDI_NOTE) { step = smallstep = 1; // semitone largestep = 12; // octave @@ -190,43 +202,28 @@ ParameterDescriptor::update_steps() smallstep = step; } else if (rangesteps > 1) { const float delta = upper - lower; - - step = smallstep = (delta / (rangesteps - 1)); // XXX - largestep = std::min ((delta / 5.0f), 10.f * smallstep); // XXX - if (logarithmic) { - smallstep = smallstep / logf (rangesteps); // XXX - step = step / logf (rangesteps); - largestep = largestep / logf (rangesteps); + smallstep = step = (powf (delta, 1.f / (float)rangesteps) - 1.f) * lower; + largestep = (powf (delta, std::max (0.5f, 10.f / (float)rangesteps)) - 1.f) * lower; } else if (integer_step) { - smallstep = 1.0; - step = std::max(1.f, rintf (rangesteps)); - largestep = std::max(1.f, rintf (largestep)); + smallstep = step = 1.0; + largestep = std::max(1.f, rintf (delta / (rangesteps - 1))); + } else { + step = smallstep = delta / (rangesteps - 1); + largestep = std::min ((delta / 4.0f), 10.f * smallstep); // XXX } } else { const float delta = upper - lower; - - /* 30 happens to be the total number of steps for a fader with default - max gain of 2.0 (6 dB), so we use 30 here too for consistency. */ - step = smallstep = (delta / 300.0f); - largestep = (delta / 30.0f); - + /* 30 steps between min/max (300 for fine-grained) */ if (logarithmic) { - /* Steps are linear, but we map them with pow like values (in - internal_to_interface). Thus, they are applied exponentially, - which means too few steps. So, divide to get roughly the - desired number of steps (30). This is not mathematically - precise but seems to be about right for the controls I tried. - If you're reading this, you've probably found a case where that - isn't true, and somebody needs to sit down with a piece of paper - and actually do the math. */ - smallstep = smallstep / logf(30.0f); - step = step / logf(30.0f); - largestep = largestep / logf(30.0f); + smallstep = step = (powf (delta, 1.f / 300.f) - 1.f) * lower; + largestep = (powf (delta, 1.f / 30.f) - 1.f) * lower; } else if (integer_step) { - smallstep = 1.0; - step = std::max(1.f, rintf (step)); - largestep = std::max(1.f, rintf (largestep)); + smallstep = step = 1.0; + largestep = std::max(1.f, rintf (delta / 30.f)); + } else { + step = smallstep = (delta / 300.0f); + largestep = (delta / 30.0f); } } } diff --git a/libs/ardour/vst_plugin.cc b/libs/ardour/vst_plugin.cc index 787210af6a..b61ee4186c 100644 --- a/libs/ardour/vst_plugin.cc +++ b/libs/ardour/vst_plugin.cc @@ -342,27 +342,22 @@ VSTPlugin::get_parameter_descriptor (uint32_t which, ParameterDescriptor& desc) desc.upper = 1.0; } - if (prop.flags & kVstParameterUsesIntStep) { + const float range = desc.upper - desc.lower; + if (prop.flags & kVstParameterUsesIntStep && prop.stepInteger < range) { desc.step = prop.stepInteger; desc.smallstep = prop.stepInteger; desc.largestep = prop.stepInteger; desc.integer_step = true; - - } else if (prop.flags & kVstParameterUsesFloatStep) { - + desc.rangesteps = 1 + ceilf (range / desc.step); + } else if (prop.flags & kVstParameterUsesFloatStep && prop.stepFloat < range) { desc.step = prop.stepFloat; desc.smallstep = prop.smallStepFloat; desc.largestep = prop.largeStepFloat; - // desc.rangesteps = (desc.upper - desc.lower) / prop.smallStepFloat; // XXX - + desc.rangesteps = 1 + ceilf (range / desc.step); } else { - - float range = desc.upper - desc.lower; - - desc.step = range / 100.0f; - desc.smallstep = desc.step / 2.0f; - desc.largestep = desc.step * 10.0f; + desc.smallstep = desc.step = range / 300.0f; + desc.largestep = range / 30.0f; } if (strlen(prop.label) == 0) { @@ -385,11 +380,16 @@ VSTPlugin::get_parameter_descriptor (uint32_t which, ParameterDescriptor& desc) desc.label = Glib::locale_to_utf8 (label); desc.lower = 0.0f; desc.upper = 1.0f; - desc.step = 0.01f; - desc.smallstep = 0.005f; - desc.largestep = 0.1f; + desc.smallstep = desc.step = 1.f / 300.f; + desc.largestep = 1.f / 30.f; } + /* TODO we should really call + * desc.update_steps () + * instead of manually assigning steps. Yet, VST prop is (again) + * the odd one out compared to other plugin formats. + */ + if (_parameter_defaults.find (which) == _parameter_defaults.end ()) { _parameter_defaults[which] = get_parameter (which); } else {