How to do "pass-through" knobs on synth with presets?

gatheround

Well-known member
Just wondering if anyone has any tips on programming "pass through" knobs?

After a preset is loaded, the knob position no longer represents the loaded value. pass-through knob behavior means that when the user turns the knob, it isn't updated until it "passes through" the loaded value and then the knob becomes live.

Sounds pretty simple, but it's baking my noodle thinking about how this might get programmed.
 
Something like this?
C++:
float getval(int channel) { return 0.5f;}

class Knob
{
    enum {below,above,track} state;
    int channel;
    float physicalValue;
    float returnedValue;
  public:
    Knob(int ch) : state(track) { channel = ch; }
    void loadPreset(float value)
    {
        returnedValue = value;
        if (value < physicalValue)
            state = below;
        else if (value > physicalValue)
            state = above;
    }
 
    float getValue(void)
    {
        physicalValue = getval(channel); // get actual knob position
        switch(state)
        {
            case below: // preset value was < knob
                if (physicalValue <= returnedValue)
                    state = track;
                break;                
             
            case above: // preset value was > knob
                if (physicalValue >= returnedValue)
                    state = track;
                break;                
             
            default:
                break;
        }
        if (track == state)
            returnedValue = physicalValue;
         
        return returnedValue;        
    }
};


Knob knob1(A0);
Knob slider1(A3);
Change the getval(channel) to access your physical hardware. When you load a preset, load its values to your controls, e.g. knob1.loadPreset(0.75); Turning the knob shouldn't affect the result of knob1.getvalue() until it physically passes 0.75 in whichever direction that is.

DISCLAIMER: I've written code like this, but not tested this actual class! Even if debugged, there are lots of improvements you could make, like abstracting the source of the physical control to analogue, MIDI etc.

EDITED: initialise state to track
 
Last edited:
The Responsive Analog library can help with this. It has an knob.hasChanged() method (taking knob as the object) and in there you can check if you have a preset loaded and if the value of the knob has reached the value of the preset, only then affect the parameter with the new value. This is cool because will only do the checking when the knob changes, if using the standard analogRead, when the knob is beyond the preset value will automatically update the parameter to that value.

C++:
knob.update();

if(knob.hasChanged())
{
  int aux = knob.getValue();
  if(presetLoaded)
  {
    if(parameterValue >= aux)
      parameterValue = aux;
  }
  else
  {
    parameterValue = aux;
  }
}

Something like that (quick and dirty coding to show the idea). When the library detects the knob changes reads the knob value and checks if you're in presetMode or not. If not, apply the knob value to the parameter. If you're in preset mode checks if the value of the knob is greater or equal to the parameter value and applies it only when that condition is true.

You might want to cast to float to apply it to an audio object parameter.
 
You would normally want to be able to pass the preset value in both directions (if increasing the knob, where the preset value is higher than currently; and if decreasing the knob, where the preset value is lower than currently).
 
Back
Top