# I need discrete stopping points on a knob

**URL:** <https://forum.juce.com/t/i-need-discrete-stopping-points-on-a-knob/59561>\
**Category:** General JUCE discussion\
**Created:** [January 17, 2024, 10:13am UTC](https://forum.juce.com/t/i-need-discrete-stopping-points-on-a-knob/59561 "2024-01-17T10:13:52Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![SpockAndStep](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/spockandstep/32/16739_2.png) [@SpockAndStep](https://forum.juce.com/u/SpockAndStep)\
**Post date:** [January 17, 2024, 10:13am UTC](https://forum.juce.com/t/i-need-discrete-stopping-points-on-a-knob/59561/1 "2024-01-17T10:13:52Z")

</div>

ok so, I am trying to update my plugin with what my client wants. he wants discrete stopping points on a certain knob but i’ve been looking on the forums and i can’t find how to do it. can someone help me out here?

---

<div class="post-metadata">

**Author:** ![kerfuffle](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/kerfuffle/32/11805_2.png) [@kerfuffle](https://forum.juce.com/u/kerfuffle)\
**Post date:** [January 17, 2024, 10:18am UTC](https://forum.juce.com/t/i-need-discrete-stopping-points-on-a-knob/59561/2 "2024-01-17T10:18:12Z")

</div>

Using an AudioParameterInt or AudioParameterChoice instead of an AudioParamerFloat will automatically give you discrete stopping points.

---

<div class="post-metadata">

**Author:** ![SpockAndStep](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/spockandstep/32/16739_2.png) [@SpockAndStep](https://forum.juce.com/u/SpockAndStep)\
**Post date:** [January 17, 2024, 10:19am UTC](https://forum.juce.com/t/i-need-discrete-stopping-points-on-a-knob/59561/3 "2024-01-17T10:19:42Z")

</div>

but I need it at a specific incriment of 0.1 from a range of -100 db to +60, would it still do that or do i need to define it

---

<div class="post-metadata">

**Author:** ![otristan](https://avatars.discourse-cdn.com/v4/letter/o/f0a364/32.png) [@otristan](https://forum.juce.com/u/otristan)\
**Post date:** [January 17, 2024, 10:21am UTC](https://forum.juce.com/t/i-need-discrete-stopping-points-on-a-knob/59561/4 "2024-01-17T10:21:33Z")

</div>

that or you just fix the display to only show one number after the floating point separator 🙂

---

<div class="post-metadata">

**Author:** ![SpockAndStep](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/spockandstep/32/16739_2.png) [@SpockAndStep](https://forum.juce.com/u/SpockAndStep)\
**Post date:** [January 17, 2024, 10:25am UTC](https://forum.juce.com/t/i-need-discrete-stopping-points-on-a-knob/59561/5 "2024-01-17T10:25:22Z")

</div>

ok i tried this and it just showed a ton of errors

---

<div class="post-metadata">

**Author:** ![SpockAndStep](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/spockandstep/32/16739_2.png) [@SpockAndStep](https://forum.juce.com/u/SpockAndStep)\
**Post date:** [January 17, 2024, 10:31am UTC](https://forum.juce.com/t/i-need-discrete-stopping-points-on-a-knob/59561/6 "2024-01-17T10:31:40Z")

</div>

ok i think i got it… I just needed to change a decimal point

---

<div class="post-metadata">

**Author:** ![daniel](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/daniel/32/790_2.png) [@daniel](https://forum.juce.com/u/daniel)\
**Post date:** [January 17, 2024, 10:31am UTC](https://forum.juce.com/t/i-need-discrete-stopping-points-on-a-knob/59561/7 "2024-01-17T10:31:44Z")

</div>

The Slider uses the NormalisableRange of the parameter.  
When you setup the [NormalisableRange](https://docs.juce.com/master/classNormalisableRange.html#ad8156ee5d7f2650156263a6f743f6886) you can also supply a step range, as well with a lambda to create programmatic legal positions to snap to.

 ![Screenshot 2024-01-17 at 11.29.02](https://us1.discourse-cdn.com/flex026/uploads/juce/original/3X/5/c/5ca1a5804123a6b61d80bc5ef9b81ed81cf59011.png)

The signature of the remap function is:

```auto
std::function<ValueType(ValueType rangeStart, ValueType rangeEnd, ValueType valueToRemap)>

auto snapToValue = [](float start, float end, float value)
{
    // do your logic here and return the snapped value
};

```

Note the decimal point probably only works visually, so the user can still dial in values that don’t snap

---

<div class="post-metadata">

**Author:** ![SpockAndStep](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/spockandstep/32/16739_2.png) [@SpockAndStep](https://forum.juce.com/u/SpockAndStep)\
**Post date:** [January 17, 2024, 10:38am UTC](https://forum.juce.com/t/i-need-discrete-stopping-points-on-a-knob/59561/8 "2024-01-17T10:38:39Z")

</div>

gotcha, thanks so much for the help

---

<div class="post-metadata">

**Author:** ![SpockAndStep](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/spockandstep/32/16739_2.png) [@SpockAndStep](https://forum.juce.com/u/SpockAndStep)\
**Post date:** [January 17, 2024, 12:46pm UTC](https://forum.juce.com/t/i-need-discrete-stopping-points-on-a-knob/59561/9 "2024-01-17T12:46:54Z")

</div>

ok so im still having errors pop up: here’s my code:  
juce::AudioProcessorValueTreeState::ParameterLayout OnlyGainsAudioProcessor::createParameterLayout()  
{  
APVTS::ParameterLayout layout;

```
// Define snapToValue function before using it
std::function<float(float, float, float)> snapToValue = [](float start, float end, float value)
{
    // Snap to increments of 0.1
    return std::round(value / 0.1f) * 0.1f;
};

using namespace juce;

layout.add(std::make_unique<AudioParameterFloat>(juce::ParameterID{ "Gain", 1 }, "Gain", NormalisableRange<float>(-100.0f, 60.0f, snapToValue), 0));

auto strFromValDb = [](float val, int)
{
    return juce::String(val, 2) + "Gain";
};

return layout;

```

}  
and heres the errors:

 ![image](https://us1.discourse-cdn.com/flex026/uploads/juce/original/3X/d/3/d3f840cd6a7d9434a2cc66462d859f6de09a051c.png)

---

<div class="post-metadata">

**Author:** ![static-cats](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/static-cats/32/11285_2.png) [@static-cats](https://forum.juce.com/u/static-cats)\
**Post date:** [January 17, 2024, 1:07pm UTC](https://forum.juce.com/t/i-need-discrete-stopping-points-on-a-knob/59561/10 "2024-01-17T13:07:59Z")

</div>

The compiler tells you that it cannot find a constructor that matches the arguments you give to `NormalisableRange`. Indeed you only pass 3 arguments (`float`, `float`, `ValueRemapFunction`) and there’s no such constructor like this mentioned in the documentation…

What you want to use is this one as Daniel pointed out: [JUCE: NormalisableRange\< ValueType \> Class Template Reference](https://docs.juce.com/master/classNormalisableRange.html#ad8156ee5d7f2650156263a6f743f6886)

I suppose you want to pass your `snapToValue` lambda as the 5th argument. The 3rd argument is also a lambda to describe how you convert from [0,1] (i.e. normalised values) to your expanded range (i.e. your -100dB to 60dB in your case). The 4th is the other way around (from [-100, 60] to [0,1]).

---

<div class="post-metadata">

**Author:** ![daniel](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/daniel/32/790_2.png) [@daniel](https://forum.juce.com/u/daniel)\
**Post date:** [January 17, 2024, 2:58pm UTC](https://forum.juce.com/t/i-need-discrete-stopping-points-on-a-knob/59561/11 "2024-01-17T14:58:37Z")

</div>

> [@SpockAndStep](#):
>
> `layout.add(std::make_unique<AudioParameterFloat>(juce::ParameterID{ "Gain", 1 }, "Gain", NormalisableRange<float>(-100.0f, 60.0f, snapToValue), 0));`

If you only need to set the slider/parameter’s sensitivity to 0.1 it is as easy as:

```auto
layout.add(std::make_unique<AudioParameterFloat>(juce::ParameterID{ "Gain", 1 }, "Gain", 
    NormalisableRange<float>(-100.0f, 60.0f, 0.1f), 0.0f));

```

I had a usecase in mind, where the interval changes, e.g. I used in an equalizer in 1 Hz up to 1kHz, then I switched to the interval of 0.01 kHz and so on…  
But in that case you have to supply ALL mapping functions to satisfy the constructor:

```auto
juce::NormalisableRange<float> range(-100.0f, 60.0f,
    [](float start, float end, float value) { return juce::jmap (value, start, end); },
    [](float start, float end, float value) { return juce::jmap (value, start, end, 0.0f, 1.0f); },
    [](float start, float end, float value) { return juce::roundToInt (value * 10.0f) * 0.1f; });
layout.add(std::make_unique<AudioParameterFloat>(juce::ParameterID{ "Gain", 1 }, "Gain", range, 0.0f));

```

With the later approach you have tons of options
