Is Skew ignored when using slider attachement?

In a standard plugin project I do this in the constructor of AudioProcessorEditor:

freqSlider.setSkewFactorFromMidPoint (100.0);  //range is 20-20000

I then check:

DBG("Skew: " << freqSlider.getSkewFactor());
Reading is: Skew: 0.12556

So there should be skew… but there’s definitely no skew:

I use slider attachement and ValueTree according to the tutorial so the slider elegantly gets it’s range from the AudioParameter.

I do the attachment before setting skew, otherwise I get an assert.

If I reset the range I get a skew:

freqSlider.setRange(20,20000);

But is that really necessary? That means a lot of redundant code restating things I’ve alread set in the AudioParameter.

ADD:
I can even do this right before setting skew and it works:

freqSlider.setRange(freqSlider.getRange().getStart(), freqSlider.getRange().getEnd());

So the slider obviously knows it’s range, but not when setting skew… :no_mouth:

I believe when you create the entry into your APVTS, you can set the skew there. Perhaps try that if using an attachment, as the slider likely just slaves to the parameter entry.

This is how it works:

std::unique_ptr<AudioParameterFloat> newGainParam(String id, String name, TGainValue maxGain)
{
  NormalisableRange<float> range(0.0f, maxGain);
  range.setSkewForCentre(0.5f);
  auto category = AudioProcessorParameter::Category::genericParameter;
  
  auto valueToString = [](float value, int maxStringLength) {
    auto gain = Decibels::gainToDecibels(value, kDecibleSlider_MinusInfinityDb);
    return Decibels::toString(gain, kDecibleSlider_DecimalPlaces, kDecibleSlider_MinusInfinityDb);
  };
  
  auto stringToValue = [](String text) {
    auto decibelText = text.upToFirstOccurrenceOf("dB", false, false).trim();
    return Decibels::decibelsToGain(decibelText.equalsIgnoreCase("-INF") ? kDecibleSlider_MinusInfinityDb : decibelText.getFloatValue(), kDecibleSlider_MinusInfinityDb);
  };
  
  return std::make_unique<juce::AudioParameterFloat>(id, name, range, 1.0f, "", category, valueToString, stringToValue);
}

You can set skew in your parameter tree where your float value will go from

NormalisableRange<float>(min, max, interval);

To

NormalisableRange<float>(min, max, interval, skew factor);

Sorry I don’t get either of these. I just want to set the Skew, it looks like a lot of code.

When creating the AudioProcessor it looks like:

ExtendedTPTAudioProcessor::ExtendedTPTAudioProcessor()
:   parametersVTS(*this, nullptr, juce::Identifier("ExtendedTPTParameters"),{
                    std::make_unique<juce::AudioParameterFloat>("gain", "GAIN", -24.0f, +24.0f, 0.0f),
                    std::make_unique<juce::AudioParameterFloat>("freq", "FREQUENCY", 20.0f, 20000.0f, 1000.0f),
                    std::make_unique<juce::AudioParameterFloat>("q_val", "Q", 0.1f, 30.0f, 0.707f),
                    std::make_unique<juce::AudioParameterBool>("bypass", "BYPASS", 0),
    })

How can I add only Skew to this?

Also, anyone who understands how the slider can know it’s range when asked but not when setting the skew? I mean isn’t it a little bit funny that I can reset the sliders range by asking the slider which range it has?
:thinking:

replace your current apf parameters with a NormalisableRange

std::make_unique<AudioParameterFloat>(“ID”, “NAME”, NormalisableRange<float>(min, max, interval, skew), default_value);

So this would look like

std::make_unique<AudioParameterFloat>(“ID”, “NAME”, NormalisableRange<float>(10.f, 20000.f, 0.01f, 0.5f), 500.f);

also i hate to be a prude, but the better way to use parameter trees is using the layout method.

processor header file

AudioProcessorValueTreeState::ParameterLayout createLayout();
AudioProcessorValueTreeState apvts{*this, nullptr, "my parameters", createLayout()};

processor cpp

AudioProcessorValueTreeState::ParameterLayout YourAudioProcessor::createLayout()
{
    AudioProcessorValueTreeState::ParameterLayout layout;

    // less typing
    using namespace std;
    using Normalise = NormalisableRange<float>;

    // then for all your params you add like this
    layout.add(make_unique<AudioParameterFloat>("filterID", "Filter Name", Normalise(10.f, 20000.f, 0.01f, 0.5f)));

    // finally you return the layout
    return layout;
}

also, dont forget to remove all the gui functions that modify the slider skew, etc. the slider will automatically use the skew from this method. if you dont remove the gui functions changing the sliders function it could mes things up.

in addition to what the others said i’d like to stress that making a skewed parameter just by applying a new mid point might not yield desirable results for frequencies. normalisableRange also has a constructor for inputting conversion lambdas where you can define the skewing behaviour precisely

1 Like

What happens is, the NormalisableRange together with the mapping and skewing is forwarded from the AudioProcessorParameter to the Slider when you attach it.
Settings like setRange or setSkew are used on Slider, when you set them AFTER creating the SliderAttachment. However it is not adviseable, because the behaviour of the Slider is now different from the behaviour of the Parameter itself, which is normally not desired.

Great, that makes sense. Maybe I finally get the full idea behind NormalizableRange as a side effect. :innocent:

That’s excellent, I will save this for later when I’m into building bigger things.

Thanks everyone. :smiley: