13
0

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.
This commit is contained in:
Robin Gareus 2017-07-06 16:15:34 +02:00
parent f66b863a2d
commit 73ad5c97f2
2 changed files with 42 additions and 45 deletions

View File

@ -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);
}
}
}

View File

@ -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 {