Idea to mimic a knob by a button/switch

My use case for this idea, is that sometimes I want to add vibrato to a sound, without having to remove my hands (and using that sound one keyboard which does not have keyboard). In that case I can assign a switch of my MIDI pedal board to mimic the vibrato setting of a plugin (IK Multimedia MixBox in my case). But this idea can be used for all cases where a button is needed instead a knob.

However, when pressing the switch the vibrato gets immediately at 100% which sounds unnatural. Also, many other effects causes crackles/distortion when changing too fast.

This script slowly moves the knob towards the correct direction. When the button is pressed, it slowly goes to a set maximum value, and when released iti goes slowly to a set minimum value (even when halfway and changing the switch of course).

See the video for a small demo.

The script is shown below.

var
   Switch : Widget
   MixBoxPlugin : PluginBlock
   MidiIn : MidiInBlock
   currentValue : double = 0.0
   minValue : double = 0.2
   maxValue : double = 0.8
   speed : double = 2.0 // sec
   lastMs : double = 0.0
   direction : integer = 0 // -1 = down, 0 = stay, 1 = up
   // nt : NoteTracker
   
const
   PARAMETER_INDEX : integer = 3

Function SetParameterValue()
   SetParameter(MixBoxPlugin, PARAMETER_INDEX, currentValue)
end
   
Initialization
   currentValue = minValue
   SetParameterValue()
End

On WidgetValueChanged(newValue : double) from Switch
    direction = if newValue == 0.0 then -1 else 1 end
    lastMs = TimeSinceStartup()
    SetTimersRunning(true)
End

On TimerTick(ms : double)
    // var notes : integer array
    if direction != 0 then
       // if NoteTracker_NoteOnCount(nt) == 0 then
       //  currentValue = if direction == -1 then minValue else maxValue end
       //   direction = 0
       // else
       currentValue = currentValue - (((lastMs - ms) / 1000) / speed * ((maxValue - minValue) * direction))
       lastMs = ms
   
       if currentValue <= minValue then
           currentValue = minValue
           direction = 0
       elsif currentValue >= maxValue then
           currentValue = maxValue
           direction = 0
       end
       // end

       if direction == 0 then
           SetTimersRunning(false)
       end
       SetParameterValue()
    end
End


// On NoteEvent(m: NoteMessage) from MidiIn
//    var notes : integer array
//    
//    if IsNoteOn(m) then
//        NoteTracker_GotNoteOn(nt, GetNoteNumber(m))
//    else
//        NoteTracker_GotNoteOff(nt, GetNoteNumber(m))
  // end
//   
//    notes = NoteTracker_GetHeldNotes(nt)
//    NoteTracker_GotNote(nt, m)
//    SendNow(MidiIn, m)
// End

The commented out lines are for the NoteTracker, in case you want to have it immediately to the min/max value when no keys are pressed, but I found out this works too tricky so I commented it.

The variables which can be set are:

Switch : Widget: The name of the switch (needs to be assigned to be accessible by GPScript).
MixBoxPlugin : PluginBlock: The plugin block that contains the plugin parameter to be changed
// MidiIn : MidiInBlock: The MIDI in block where the keys are checked for the note tracker
minValue : double = 0.2: The minimum value of the parameter value (0-1)
maxValue : double = 0.8: The maximum value of the parameter value (0-1)
speed : double = 2.0 // sec: The amount of seconds between moving from minimum to maximum or vice versa

const PARAMETER_INDEX : integer = 3: The parameter index of the plugin (MixBoxPlugin in my case) to be set

Future improvements

  • It uses the timer tick function, which is not too precise (when called). Maybe using a generator (ramp) would be better/more precise.
  • The upward and downward speed are equal. This could be two different values. See below.

UPDATE
(Below is a version with the note tracker code removed and with separate up/downward speeds, and a few small code improvements.

var
   Switch : Widget
   MixBoxPlugin : PluginBlock
   currentValue : double = 0.0
   minValue : double = 0.2
   maxValue : double = 0.8
   upSpeed : double = 2.0 // sec
   downSpeed : double = 0.5 // sec
   lastMs : double = 0.0
   direction : integer = 0 // -1 = down, 0 = stay, 1 = up
   
const
   PARAMETER_INDEX : integer = 3

Function SetParameterValue()
   SetParameter(MixBoxPlugin, PARAMETER_INDEX, currentValue)
end
   
Initialization
   currentValue = minValue
   SetParameterValue()
End

On WidgetValueChanged(newValue : double) from Switch
    direction = if newValue == 0.0 then -1 else 1 end
    lastMs = TimeSinceStartup()
    SetTimersRunning(true)
End

On TimerTick(ms : double)
    var multiplier : double = 0.0
    if direction != 0 then
       multiplier = (ms - lastMs) * (maxValue - minValue) / 1000.0
       if direction == 1 then
          currentValue = currentValue + multiplier / upSpeed
       else
          currentValue = currentValue - multiplier / downSpeed
       end
       lastMs = ms
   
       if currentValue <= minValue then
           currentValue = minValue
           direction = 0
       elsif currentValue >= maxValue then
           currentValue = maxValue
           direction = 0
       end

       if direction == 0 then
           SetTimersRunning(false)
       end
       SetParameterValue()
    end
End
2 Likes