Hello, fellow GPers!
I’ve created a Rackspace script that bends a note up a half step when the note is played. The goal is to emulate the pitch bend in Garbage’s version of “Cities in Dust” as heard here, but it can be adapted to other situations where you can’t spare a free hand to work the mod wheel.
Prerequisites:
- In the Wiring view, create a MIDI In block and give it a name to reference in a script. I went with “MIB” for the name.
- In the Wiring view, connect the MIDI In block to a virtual instrument that supports pitch bend. Note the pitch bend range on that virtual instrument. In my case it’s a whole step up or down, but yours might be different.
- In the Panels view/editor, create a widget and map it to your virtual instrument’s pitch bend controller. I went with a slider but any continuous controller should work. Note that sliders go from 0.0 to 1.0 by default.
- Set the widget’s OSC/GPScript Handle to “PBENDER” in the Widget Properties (Advanced tab).
- From Gig Performer’s Window menu, select “Current Rackspace Script Editor”
- Paste the code below. Tweak any Const or Var values as indicated in the comments to suit your needs.
- Compile the code.
- Profit!
Const
PBEND_CENTER : double = 0.5 // "Center" on the pitch bend widget (slider).
PBEND_MAX : double = 0.75 // Furthest value to which the pitch bender will bend.
// In this case, we just want a half step up.
// Note: my virtual instrument's pitch bend range is
// +/- one whole step - adjust PBEND_MAX depending
// on your virtual instrument's pitch bend range and
// desired bend and direction.
Var
PBENDER : Widget // A widget (slider in this case) mapped to the
// pitch bend controller on the virtual synth.
MIB : MidiInBlock // The Midi In Block from which the note will come.
bendTimeMillis : Integer = 1000 // Set our pitch bend time to one second. Adjust
// as needed.
// TODO: Map this to a widget too!
myRamp : Ramp // A generator that moves smoothly from
// 0.0 to 1.0 over some specified time.
initialization
// Set up the ramp generator.
SetGeneratorOneShot(myRamp, true)
// Set the length of time we want the ramp to span.
myRamp.SetGeneratorLength(bendTimeMillis)
end
// This gets called when a note is played or released.
On NoteEvent (m : NoteMessage) From MIB
If IsNoteOn(m) Then
// Arm the ramp function generator.
myRamp.EnableGenerator(True)
// Start the ramp function generator.
SetTimersRunning(true)
// Send the note downstream. Note that we have to pass
// MIB as well since this is at the Rackspace level.
SendNow(MIB,m)
Elsif IsNoteOff(m) Then
// Send the note off message downstream.
SendNow(MIB, m)
// Pause a bit to let the note die out before resetting the widget. If we
// don't do this we'll get a last-second bend back to PBEND_CENTER.
// Adjust as needed depending on your sound's decay settings.
Sleep(250) // Quarter of a second.
// Reset the pitch bend to PBEND_CENTER.
SetWidgetValue(PBENDER, PBEND_CENTER)
End
End
// This gets called by the ramp generator as time passes.
On GeneratorRunning(time : integer, amplitude : double) from myRamp
// The amplitude of the ramp goes from 0.0 to 1.0 so if we map that to the gap
// between PBEND_CENTER and PBEND_MAX, we generate a value that gets closer to the
// PBEND_MAX value over time.
SetWidgetValue(PBENDER, Scale(amplitude, 0.0, 1.0, PBEND_CENTER, PBEND_MAX))
End
Note that this script bends up a half step from the note that was played. If you prefer to play the target note and have the pitch bend slide up a half step to meet it, set these values for the constants instead:
PBEND_CENTER : double = 0.25 // "Center" on the pitch bend widget (slider).
PBEND_MAX : double = 0.5 // Furthest value to which the pitch bender will bend.
Doing this will set the pitch bend slider widget at a half-step down when the note is released, so you may also want to change the “reset” command in the IsNoteOff() section to 0.5 instead of PBEND_CENTER:
// Reset the pitch bend to PBEND_CENTER.
SetWidgetValue(PBENDER, 0.5)
Enjoy!