How to un-skew slider values?

I am using a TwoValueVertical slider for a band pass filter. Since it’s a filter, I am using a skew factor of 0.4f to have easy access for the low-end values.

All is good, but now I want to add some custom graphics with big slider thumbs. And this is an issue since if I’m just adding them using LookAndFeel, the thumbs overlap each other and I want to keep a minimal margin between them for aesthetic reasons.

For a slider with a skew factor, this margin will be different for low values vs high values.
For example:

  • If the max thumb is at 1,000Hz, the min thumb can’t be higher than 500Hz
  • If the max thumb is at 15,000Hz, the min thumb can’t be higher than 10,000Hz

These are just random numbers to illustrate the point that the margin between min and max should be different each time and is dependent on both the current max value and the thumb size in pixels.

I’m trying to reverse engineer the skew formula, but getting nowhere. Any math wizards out there that can help?

(to check this issue yourself, simply add a skew factor to any two-value slider, then shift+drag one of the thumbs. As expected, the other thumb will move in an exponential manner, but I want to bypass the skew effect and make the entire top-bottom range move linearly).

The skew formula seems to be

proportionInParamRange = std::exp (std::log (proportionInSliderRange) / skew);

And the reverse of that is

proportionInSliderRange = std::exp (std::log (proportionInParamRange) * skew);

So that tells you what parameter value you should set to have the slider thumb appear e.g. midway.

1 Like

I also needed to un-skew slider values but the previous solution unfortunately didn’t work for me. The following code did:

/** For an EQ, rangeMin and rangeMax could stand for 20 Hz and 22000 Hz respectively and sliderValue for some value in between.
    Output then is the standardized parameter value between 0 and 1.0. */
static float getStandardizedParameterValue(float rangeMin, float rangeMax, float skew, float sliderValue)
{
    return pow(10.0f, skew * std::log10((sliderValue - rangeMin)/(rangeMax - rangeMin)));
}

/** Same as getStandardizedParameterValue( ), only that the input would be a parameter value between 0 and 1.0,
    while the output would be the skewed value between rangeMin and rangeMax. */
static float getSliderValue(float rangeMin, float rangeMax, float skew, float standardizedParamVal)
{
    return rangeMin + (rangeMax - rangeMin) * pow(10.0f, std::log10(standardizedParamVal) / skew);
}

I have ended up with this solution by building on the information from this article:

best way to do that is to actually not have any slider skew in your code but instead rule that out directly on the parameter itself with the normalisableRange constructor that has 3 lambdas. you only have to define the first 2 of them to make it work. normalizing and denormalizing functions. then when getting values from the parameter you have free control if you want one or the other.

the denormalization function just has to be the inverted function of the normalization one. a function that undo-s what the other function did.

check out some examples i have in my code base:

1 Like