Need help with smooth fader-reset


Originally published at:

Hi folks,
i would like to take advantage of the X/Y-pad on my master keyboard to control two (filter) values at once.
My plan is to use two fader widgets (one for X, one for Y). So far so easy… no script needed yet. :slight_smile:
Those two faders should be automatically re-centered when i press a controller-button.
Not the problem.

BUT i want this re-centering movement to be “smooth” (maybe even with adjustable speed) and evenly,
so that both faders reach the center at the same time (no matter where they stood before).

And this is something i never did with scripting/programming, so i have absolutely no idea where to start
or how to realize something like this (timing/time-based movement) in GP-script.

So any help, hints or ideas for my (supposedly) small problem are very much appreciated. :slight_smile:

Thanks a lot.


I’m not in a position to write your script for you but I can demo the mechanisms that you might find useful.

I’ve just checked the documentation for GP Script and realized that I didn’t mention a very important callback called TimePassing which can be tied to generators such as Ramps and ADSRs. It hasn’t really had that much testing so consider this stuff to be experimental!

Take a look at this screenshot (I’ve pasted the actual code as well, but the screen shot has syntax coloring which makes it easier to read. In particular

I’ve created three widgets, two of which represent your X and Y faders and the third is a “trigger”

Following is a variable of type Ramp. A ramp is a function generator that generates a sequence of values over time where the Y access goes from 0.0 to 1.0

In the initialization, we configure the ramp so that it is a one shot. That means that it will only run ONCE each time you trigger it.

The Trigger widget callback is used to configure the ramp and start it. Here, when you press the trigger button, we set the length to 2 seconds (2000 milliseconds). That means that when the ramp is running, the X value will range from 0 to 1999 and the amplitude (y value) will go from 0.0 to 1.0 linearly over the 2000 milliseconds.

We then enable the rackspace timer for generators. I’m doing this because whenever you leave a rackspace, that timer gets turned off and needs to be turned on manually (normally this would be done in an On Activate callback)

Finally, the On TimePassing callback gets triggered periodically (you can define how fine-grained that callback should be but be careful, if you make it too fine-grained you’ll suck up a lot of CPU cycles)
In the callback, I’m scaling the amplitude individually for each widget so they change accordingly.


   Trigger : Widget // A button widget used to trigger the ramp
   xWidget : Widget // My x knob
   yWidget : Widget // My y knob

   myRamp : Ramp // A generator that moves smoothly from 0.0 to 1.0 over some specified time
   SetGeneratorOneShot(myRamp, true) // Generator will only run once when triggered
   // Also, check the SetGeneratorCoarseness function
   // which can be used to control how often we get called back
   // Choose values wisely! You're trading accuracy against CPU cycles


// Use this to trigger the ramp
On WidgetValueChanged(newValue : double) from Trigger
   if newValue > 0.5
         myRamp.SetGeneratorLength(2000); // Two seconds

// This gets called by the ramp generator as time passes
on TimePassing(timeX : integer, amplitudeY : double) from myRamp

   SetWidgetValue(xWidget, Scale(amplitudeY, 0, 1, 1, 0)) 
   SetWidgetValue(yWidget, Scale(amplitudeY, 0, 1, 0.3, 0.7))

   //Print("X = " + timeX + " Y = " + timeY) 
   if (amplitudeY > 0.95)
      then SetWidgetValue(Trigger, 0)


I’ve been using the ramps and ADSRs in combination with the TimePassing callback since April and it really works great and reliably in my usecases.

OT: David, didn’t you think about adding a “On Beat” and a “On Time” callback? Would be highly appreciated :wink: I know…priorities…


Hmm, I guess I don’t need a “get out of jail free” card, (also known as “experimental”) anymore for that stuff. I haven’t done much with those things myself so didn’t feel they had sufficient testing. Good to know you’re finding it reliable.

There actually is a timer callback. I think it’s

On Timer(ms: integer)


Beat callback is a bit more complicated but it’s on our list


I’ve played about ten gigs with it and it hasn’t done anything unexpected yet.

How does the timer callback work? Is it independent from the Generator objects? And will it be called every millisecond?!


Well, I lied… first of all, syntax wise it’s called

OnTimerTick(ms : double)

and secondly, it doesn’t work. I just looked at the code and I never actually implemented it. I remember now that I realized that you could just use a repeating Ramp generator and if you need to know the actual number of milliseconds that has passed, then you can use the TimeNow() function


Besides your discussion, i want to say “Thanks a lot!” to David. :slight_smile:
I think, this is exactly what i need for my purpose.
I haven’t tested it yet, but it is quite clear how to use it.
Thanks again.


Yeah, the thing you’ll need to do is adjust the length of the ramp based on how far away your fader is from center if you want the time to return to be a function of the distance away from center. You could use two ramps or you could just do one ramp and use the Scale function to control the rate.


BTW: I managed to build the script exactly how i wanted it to be. Nice thing! :sunglasses:
Thank you for your help, David.


Glad it worked. Feel free to share your script in the script section if you want


Always great to see more functionality added to GP @schamass :wink: