XY-controller with smooth re-centering

Ok… then i am the first one to post here.
I built a rackspace to take advantage of the XY-pad on my keyboard and to conrol two parameters at once.
I used two faders which reresent the x/y axis of the pad. The values from these faders are recalculated in script to optimally scale the ranges of the pad/faders and the controller values.
On activation of the rackspace, the momentary position of the x_val and y_val controllers are buffered by two auxiliary widgets buf_x and buf_y to preserve the original sound (ok i could use variables instead, but variables are not visible).
To re-center the faders in a smooth manner, there is button with a script behind it which brings the two faders back to the center equally - means, they always reach the center at the same moment.

Here is the link to the rackspace (i put it in my dropbox):

The plugins i used for it are both free and for WIN 32/64 and Mac:
Digits (Free Synth)
http://www.extentofthejam.com/

HY-SEQ (Step-Sequencer / Free Version)
https://hy-plugins.com/product/hy-seq16x3/#tab-tab2

I also recorded a short video to show you all that in action:
https://youtu.be/ZYpzL7BL010

And this is the script behind it… maybe it’s useful for one or the other. :sunglasses:

Var
   btn_center : Widget // A button widget used to trigger the ramp
   fdr_x : Widget // My x knob
   fdr_y : Widget // My y knob
    buf_x : Widget
    buf_y : Widget
    val_x : Widget
    val_y : Widget
    
var
   myRamp : Ramp // A generator that moves smoothly from 0.0 to 1.0 over some specified time
   
var
    start_x : double
    start_y : double

   
initialization
   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

end   

On Activate
//buffer the values of x_val and y_val to get back to the original sound when centering
   SetWidgetValue(buf_x,GetWidgetValue(val_x))
   SetWidgetValue(buf_y,GetWidgetValue(val_y))
End


// Use this to trigger the ramp / re-center the faders
On WidgetValueChanged(newValue : double) from btn_center
   if newValue > 0.5
      then
        //catch the values where to start from, when re-centering
        start_x=GetWidgetValue(fdr_x)
        start_y=GetWidgetValue(fdr_y)
        
         myRamp.SetGeneratorLength(1500); // in milliseconds
         
         SetTimersRunning(true)
         myRamp.EnableGenerator(True)
   end      
End


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

    //wandering back to center with range scaled from actual starting-point to center(=0.5)
    SetWidgetValue(fdr_x, Scale(amplitudeY, 0, 1, start_x, 0.5)) 
    SetWidgetValue(fdr_y, Scale(amplitudeY, 0, 1, start_y, 0.5)) 

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



//scaling the available ranges (upper/lower) of the value-widgets to the full range of the xy-faders
//so the center of x/y is always the "original sound" where to start from and the full range of the
//faders can used to change the values

on WidgetValueChanged(newx : double) from fdr_x
        if (newx <= 0.5) Then
            SetWidgetValue(val_x, GetWidgetValue(buf_x) * GetWidgetValue(fdr_x) *2 )
        End
    
        if (newx > 0.5) Then
            SetWidgetValue(val_x, GetWidgetValue(buf_x) + (( 1.0 - GetWidgetValue(buf_x)) * (GetWidgetValue(fdr_x) - 0.5)) * 2)
        End
End

on WidgetValueChanged(newy : double) from fdr_y
        if (newy <= 0.5) Then
            SetWidgetValue(val_y, GetWidgetValue(buf_y) * GetWidgetValue(fdr_y) *2 )
        End
    
        if (newy > 0.5) Then
            SetWidgetValue(val_y, GetWidgetValue(buf_y) + (( 1.0 - GetWidgetValue(buf_y)) * (GetWidgetValue(fdr_y) - 0.5)) * 2)
        End
End
3 Likes