(PART TWO, continuation of the main post, as there is a body limit of 32000 characters)
Template script
Below is the entire template script, chopped up in pieces for more explanation.
Feel free to use my script as you like. Also, if you have improvements or questions, feel free to ask.
/*
Created by Michel Keijzers
v1.0
*/
Below are all ‘global variables’ which I use, the first part constants (in capitals as by convention), the others normal global variables. I also used as many constants as possible, to make it easier for you to adapt the script to your needs.
Due to the spaces/tabs, the alignment is sometimes a big awkward.
Var
SLIDER_CC_START : integer = 81 // CC of first slider on the Oxygen 61,
// consecutive
NR_OF_SLIDERS : integer = 9 // Number of physical sliders on the
// Oxygen 61
NR_OF_AUDIO_MIXER_CHANNELS : integer = 8 // Number of audio mixer channels
PANEL_TOGGLE_ON_VALUE : double = 0.6 // On value for hammond/audio
// mixer toggle
Use here the CC values from your Hammond plugin.
HAMMOND_PLUGIN_UPPER_DRAWBARS_PARAMETER_START : integer = 20 // 16' Upper,
// 5 1/3' Upper, 8' Upper etc.
These are the parameter numbers from the GigPerformer Audio Mixer plugin. I wish there was also a parameter for the label strip of each channel.
AUDIO_MIXER_PARAMETERS : integer = 7
AUDIO_MIXER_VOLUME_PARAMETER : integer = 0
AUDIO_MIXER_BALANCE_PARAMETER : integer = 1
AUDIO_MIXER_SOLO_PARAMETER : integer = 2
AUDIO_MIXER_MUTE_PARAMETER : integer = 3
AUDIO_MIXER_OUTPUT_PARAMETER : integer = 4
Various plugins I use which are affected by my script.
MidiInOxygen61 : MidiInBlock
MidiInFcb1010 : MidiInBlock
HammondPlugin : PluginBlock
AudioMixerFadersPlugin: PluginBlock
AudioMixerExprPedalsPlugin: PluginBlock
GainAndBalanceTotalPlugin: PluginBlock
All Hammond widgets I use.
HammondBox: widget
RotatorSpeedLed, RotatorSpeedSustainPedal, DriveKnob: widget
Drawbar1, Drawbar2, Drawbar3, Drawbar4, Drawbar5, Drawbar6, Drawbar7,
Drawbar8, Drawbar9: widget
These are the widgets for the sliders part of the audio mixer.
Keyboard61MixerBox, Keyboard88MixerBox, MainMixerBox: widget
Slider1, Slider2, Slider3, Slider4, Slider5, Slider6, Slider7, Slider8,
Slider9: widget
And here the array for the Hammond widgets.
HammondArray : widget array =
[
Drawbar1, Drawbar2, Drawbar3, Drawbar4, Drawbar5, Drawbar6, Drawbar7,
Drawbar8, Drawbar9,
HammondBox, RotatorSpeedLed, RotatorSpeedSustainPedal, DriveKnob
]
And the widgets and array for the expression pedals.
ExpressionPedal1, ExpressionPedal2, ExpressionPedal3, ExpressionPedal4,
ExpressionPedal5, ExpressionPedal6, ExpressionPedal7, ExpressionPedal8,
ExpressionPedalUpperBox, ExpressionPedalLowerBox: widget
ExpressionPedalArray : widget array =
[
ExpressionPedal1, ExpressionPedal2, ExpressionPedal3, ExpressionPedal4,
ExpressionPedal5, ExpressionPedal6, ExpressionPedal7, ExpressionPedal8
]
VolumeKnob1, VolumeKnob2, VolumeKnob3, VolumeKnob4,
VolumeKnob5, VolumeKnob6, VolumeKnob7, VolumeKnob8 : widget
The volume knobs are used for the same function as the expression pedals.
VolumeKnobArray : widget array =
[
VolumeKnob1, VolumeKnob2, VolumeKnob3, VolumeKnob4,
VolumeKnob5, VolumeKnob6, VolumeKnob7, VolumeKnob8
]
MixerArray : widget array =
[
Slider1, Slider2, Slider3, Slider4, Slider5, Slider6, Slider7, Slider8,
Slider9,
Keyboard61MixerBox, Keyboard88MixerBox, MainMixerBox
]
PanelToggle : widget // Toggles between Hammond widgets and volume sliders
// widgets
ChordsWidget : widget // Shows Chords in the Chords panel (unrelated to the
// mixer)
This function shows or hides a group of widgets, which is typically the Hammond widgets array or the Audio mixer widgets array to be toggled.
function ShowWidgets(group : widget array, show : boolean)
var index : integer
for index = 0; index < Size(group); index = index + 1 do
SetWidgetHideOnPresentation(group[index], !show)
end
end
This function returns the enabled channels concatenated, in my example for this song and defined in the rackspace script for the song, e.g. in this case “1” for the upper keyboard and “567” for the lower keyboard, resulting in “1567”.
function GetEnabledChannels() returns string
result = TrimString(GetEnabledUpperAudioMixerChannels()) +
TrimString(GetEnabledLowerAudioMixerChannels())
end
This functions shows or hides the audio mixer faders, based on which channels are enabled in the user script. The second part is for the gain slider and the three boxes.
function ShowUsedMixerChannels()
var
enabledChannels : string = GetEnabledChannels()
enabledChannel : integer
index : integer
for index = 0; index < Length(enabledChannels); index = index + 1 do
enabledChannel = StringToInt(CopySubstring(enabledChannels, index, 1))
if enabledChannel >= 1 and
enabledChannel <= NR_OF_AUDIO_MIXER_CHANNELS then
SetWidgetHideOnPresentation(MixerArray[enabledChannel - 1], false)
end
end
for index = NR_OF_AUDIO_MIXER_CHANNELS; index < Size(MixerArray);
index = index + 1 do
SetWidgetHideOnPresentation(MixerArray[index], false)
end
end
This function toggles between the Hammond and audio mixer widgets.
function PanelToggleValueChanged(panelToggleValue : double)
if panelToggleValue > PANEL_TOGGLE_ON_VALUE then
ShowWidgets(HammondArray, true)
ShowWidgets(MixerArray, false)
else
ShowWidgets(HammondArray, false)
ShowWidgets(MixerArray, false)
ShowUsedMixerChannels()
end
end
This function moves the Hammond or audio mixer fader depending on which one is active.
function MoveFader(
index : integer, ccNumber_unused : integer, ccValue : integer)
if IsHammondPresent() and
GetWidgetValue(PanelToggle) > PANEL_TOGGLE_ON_VALUE then
SetWidgetValue(HammondArray[index], MidiToParam(ccValue))
else
SetWidgetValue(MixerArray[index], MidiToParam(ccValue))
end
end
Returns the lowest channel number, which typically is the first character of the string, but to not make this assumption, the string is iterated. Typically, the argument is the lower keyboard string, in the song defined as “567”, resulting in the 4th channel.
function GetLowestChannel(enabledChannels: string) returns integer
var
lowestChannel : integer = NR_OF_AUDIO_MIXER_CHANNELS + 1
enabledChannel : integer
index : integer
for index = 0; index < Length(enabledChannels); index = index + 1 do
enabledChannel = StringToInt(CopySubstring(enabledChannels, index, 1))
lowestChannel = Round(Min(lowestChannel, enabledChannel))
end
result = lowestChannel
end
Draws the widgets for the Hammond drawbars. As the other Hammond related widgets do not change, I decided not to ‘redraw’ them.
function DrawDrawbars()
var index : integer
for index = 0; index < NR_OF_SLIDERS; index = index + 1 do
SetWidgetBounds(HammondArray[index], [5 + 43 * index, 5, 50, 370])
end
SetWidgetBounds(HammondBox, [0, 0, 480, 380])
// RotatorSpeedLed, RotatorSpeedSustainPedal, DriveKnob
end
Draws the faders.
function DrawSliders(lowestLowerChannel: integer)
var
index : integer
width : integer = 53
for index = 0; index < NR_OF_SLIDERS; index = index + 1 do
SetWidgetBounds(MixerArray[index], [width * index, 10, width, 370])
end
SetWidgetBounds(Keyboard61MixerBox,
[ 0, 0, width * (lowestLowerChannel - 1), 380 ])
SetWidgetBounds(Keyboard88MixerBox,
[ width * (lowestLowerChannel - 1), 0,
width * (9 - lowestLowerChannel), 380])
SetWidgetBounds(MainMixerBox, [ width * 8, 0, width, 380 ])
end
This function formats the audio mixer widgets.
function FormatAudioMixerWidgets(lowestLowerChannel : integer)
DrawDrawbars()
DrawSliders(lowestLowerChannel)
end
This parameter enables an audio mixer channel, by unmuting it, or disabling by muting it, setting the volume to 0, resetting the balance knob and the solo button.
I wish, I also could change the channel strip label, but there is no parameter for this.
function EnableChannel(plugin: PluginBlock, index : integer, enable : boolean)
var parameterOffset : integer
parameterOffset = AUDIO_MIXER_PARAMETERS * (index - 1)
if (enable) then
SetParameter(plugin, parameterOffset + AUDIO_MIXER_MUTE_PARAMETER, 0)
else
SetParameter(plugin, parameterOffset + AUDIO_MIXER_VOLUME_PARAMETER, 0)
SetParameter(plugin, parameterOffset + AUDIO_MIXER_BALANCE_PARAMETER,
0.5)
SetParameter(plugin, parameterOffset + AUDIO_MIXER_MUTE_PARAMETER, 1)
SetParameter(plugin, parameterOffset + AUDIO_MIXER_SOLO_PARAMETER, 0)
// There is no parameter for the label of each channel
end
end
This function disables the unused audio mixer channels.
function DisableUnusedMixerChannels()
var
enabledChannels : string = GetEnabledChannels()
enabledChannel : integer
enable : boolean
index : integer
for index = 1; index <= NR_OF_AUDIO_MIXER_CHANNELS; index = index + 1 do
enable = IndexOfSubstring(
enabledChannels, IntToString(index), false) >= 0
EnableChannel(AudioMixerFadersPlugin , index, enable)
EnableChannel(AudioMixerExprPedalsPlugin, index, enable)
end
end
This function formats the expresson pedal and knobs widgets for the volume.
The expression pedals/knobs are assigned to each of the audio mixer sliders.
Only two expression pedals are shown, the first for the upper keyboard, and the first for the lower keyboard (depending which is the first active audio mixer channel).
The other expression pedal widgets are drawn in small on the right margin, and the knobs are drawn in small left of the corresponding expression pedals.
function FormatExpressionPedalWidgets(lowestLowerChannel : integer)
var
EDGE_MARGIN : integer = 5
LEFT_MARGIN_MAIN_EXPRESSION_PEDAL : integer = 980
LEFT_MARGIN_MAIN_VOLUME_KNOB : integer =
LEFT_MARGIN_MAIN_EXPRESSION_PEDAL -
20
WIDTH_MAIN : integer = 120
HEIGHT_BOX : integer = 190
HEIGHT_MAIN : integer =
HEIGHT_BOX - 2 * EDGE_MARGIN
LEFT_MARGIN_EXPRESSION_PEDAL : integer = 1050
LEFT_MARGIN_VOLUME_KNOB : integer =
LEFT_MARGIN_EXPRESSION_PEDAL - 30
WIDTH_OTHERS : integer = 30
HEIGHT_OTHERS : integer = WIDTH_OTHERS
index : integer
for index = 0; index < NR_OF_SLIDERS - 1; index = index + 1 do
if index == 0 then
SetWidgetBounds(ExpressionPedalArray[index],
[ LEFT_MARGIN_MAIN_EXPRESSION_PEDAL, EDGE_MARGIN,
WIDTH_MAIN, HEIGHT_MAIN ])
SetWidgetBounds(VolumeKnobArray[index],
[ LEFT_MARGIN_MAIN_VOLUME_KNOB, EDGE_MARGIN,
WIDTH_OTHERS, HEIGHT_OTHERS ])
SetWidgetHideOnPresentation(ExpressionPedalArray[index], false)
elsif index == lowestLowerChannel - 1 then
SetWidgetBounds(ExpressionPedalArray[index],
[ LEFT_MARGIN_MAIN_EXPRESSION_PEDAL, HEIGHT_BOX + EDGE_MARGIN,
WIDTH_MAIN, HEIGHT_MAIN ])
SetWidgetBounds(VolumeKnobArray[index],
[ LEFT_MARGIN_MAIN_VOLUME_KNOB, HEIGHT_BOX,
WIDTH_OTHERS, HEIGHT_OTHERS ])
SetWidgetHideOnPresentation(ExpressionPedalArray[index], false)
elsif index < lowestLowerChannel then
SetWidgetBounds(ExpressionPedalArray[index],
[ LEFT_MARGIN_EXPRESSION_PEDAL,
HEIGHT_BOX / lowestLowerChannel * (index - 1),
WIDTH_OTHERS, HEIGHT_OTHERS ])
SetWidgetBounds(VolumeKnobArray[index],
[ LEFT_MARGIN_VOLUME_KNOB,
HEIGHT_BOX / lowestLowerChannel * (index - 1),
WIDTH_OTHERS, HEIGHT_OTHERS ])
SetWidgetHideOnPresentation(ExpressionPedalArray[index], true)
else
SetWidgetBounds(ExpressionPedalArray[index],
[ LEFT_MARGIN_EXPRESSION_PEDAL,
HEIGHT_BOX + (HEIGHT_BOX - EDGE_MARGIN) /
(NR_OF_AUDIO_MIXER_CHANNELS - lowestLowerChannel + 1) *
(index - lowestLowerChannel),
WIDTH_OTHERS, HEIGHT_OTHERS ])
SetWidgetBounds(VolumeKnobArray[index],
[ LEFT_MARGIN_VOLUME_KNOB,
HEIGHT_BOX + (HEIGHT_BOX - EDGE_MARGIN) /
(NR_OF_AUDIO_MIXER_CHANNELS - lowestLowerChannel + 1) *
(index - lowestLowerChannel),
WIDTH_OTHERS, HEIGHT_OTHERS ])
SetWidgetHideOnPresentation(ExpressionPedalArray[index], true)
end
SetWidgetHideOnPresentation(VolumeKnobArray[index], true)
end
SetWidgetBounds(ExpressionPedalUpperBox,
[ LEFT_MARGIN_MAIN_VOLUME_KNOB, 0, WIDTH_MAIN, HEIGHT_BOX ])
SetWidgetBounds(ExpressionPedalLowerBox,
[ LEFT_MARGIN_MAIN_VOLUME_KNOB, HEIGHT_BOX, WIDTH_MAIN, HEIGHT_BOX ])
end
This is the initialization function of the script, which handles the toggle value, mapping the hammond widgets to the Hammond plugin, mapping the audio mixer sliders to the audio mixer plugin, setting the Chords widget, and formatting the layout of most of the widgets.
initialization
var
initialPanelToggleValue : double = 0.0
index : integer
lowestLowerChannel : integer
for index = 0; index < NR_OF_SLIDERS; index = index + 1 do
MapWidgetToPlugin(HammondArray[index], HammondPlugin,
HAMMOND_PLUGIN_UPPER_DRAWBARS_PARAMETER_START + index)
end
for index = 0; index < NR_OF_SLIDERS - 1; index = index + 1 do
MapWidgetToPlugin(MixerArray[index],
AudioMixerFadersPlugin,
AUDIO_MIXER_PARAMETERS * index + AUDIO_MIXER_VOLUME_PARAMETER)
MapWidgetToPlugin(ExpressionPedalArray[index],
AudioMixerExprPedalsPlugin,
AUDIO_MIXER_PARAMETERS * index + AUDIO_MIXER_VOLUME_PARAMETER)
end
MapWidgetToPlugin(Slider9, GainAndBalanceTotalPlugin, 0)
if IsHammondPresent() then
initialPanelToggleValue = 1.0
end
PanelToggleValueChanged(initialPanelToggleValue)
SetWidgetValue(PanelToggle, initialPanelToggleValue)
SetWidgetLabel(ChordsWidget, GetChordsText())
lowestLowerChannel = GetLowestChannel(GetEnabledLowerAudioMixerChannels())
FormatAudioMixerWidgets(lowestLowerChannel)
DisableUnusedMixerChannels()
FormatExpressionPedalWidgets(lowestLowerChannel)
end
This function sets the audio mixer slider when an incoming CC event is received. In case the functionality is overridden, it is calling the user script function, otherwise the volume control will be used. To make sure when the expression pedal of the FCB1010 is down, that the volume is off, it is automatically set to 0 when under a certain threshold value, and set to max volume when the expression is not down, so the overridden functionality is active.
function SetAudioMixerSlider(
firstSlider : integer, lastSlider : integer, ccValue: integer)
var
FCB1010_FULL_DOWN_RANGE : integer = 10 // FCB1010 expression pedal is
// not so exact
MIDI_VALUE_NO_VOLUME : integer = 0
MIDI_VALUE_MAX_VALUE : integer = 127
AUDIO_CHANNEL_NOT_MUTED : integer = 0
index : integer
parameterOffset : integer
isOverridden : boolean
for index = firstSlider; index < lastSlider; index = index + 1 do
parameterOffset = AUDIO_MIXER_PARAMETERS * index
if GetParameter(AudioMixerFadersPlugin,
parameterOffset + AUDIO_MIXER_MUTE_PARAMETER) ==
AUDIO_CHANNEL_NOT_MUTED then
isOverridden = OverrideSlider(index + 1, ccValue)
if isOverridden == true then
if ccValue <= FCB1010_FULL_DOWN_RANGE then
SetWidgetValue(ExpressionPedalArray[ index ],
MidiToParam(MIDI_VALUE_NO_VOLUME))
else
SetWidgetValue(ExpressionPedalArray[ index ],
MidiToParam(MIDI_VALUE_MAX_VALUE))
end
else
SetWidgetValue(ExpressionPedalArray[ index ],
MidiToParam(ccValue))
end
end
end
end
This function process incoming CC events from the Oxygen 61. There are four cases:
-
A slider is changed on the Oxygen 61, this results in a change of a Hammond drawbar or audio mixer
-
Knob 4 is changed, resulting in changing the upper keyboard audio mixer volumes
-
Knob 8 is changed, resulting in changing the lower keyboard audio mixer volumes
-
Else, the CC is forwarded as normal
on ControlChangeEvent(ccMsg : ControlChangeMessage) from MidiInOxygen61
var
OXYGEN61_KNOB_4_CC_NUMBER : integer = 93
OXYGEN61_KNOB_8_CC_NUMBER : integer = 97ccNumber : integer = GetCCNumber(ccMsg) ccValue : integer = GetCCValue(ccMsg) lowestLowerChannel : integer = GetLowestChannel( GetEnabledLowerAudioMixerChannels()) if ccNumber >= SLIDER_CC_START and ccNumber < SLIDER_CC_START + NR_OF_SLIDERS then MoveFader(ccNumber - SLIDER_CC_START, ccNumber, ccValue) elsif ccNumber == OXYGEN61_KNOB_4_CC_NUMBER then SetAudioMixerSlider(0, lowestLowerChannel - 1, ccValue) elsif ccNumber == OXYGEN61_KNOB_8_CC_NUMBER then SetAudioMixerSlider(lowestLowerChannel - 1, NR_OF_SLIDERS - 1, ccValue) else SendNow(MidiInOxygen61, MakeControlChangeMessage(ccNumber, ccValue)) end
end
This function process the Behringer FCB1010 CC messages. The left pedal is set to CC 94, and the right pedal to CC 95. As with the knobs, the upper audio mixer volumes are changed (in case of CC 94), the lower audio mixer volumes are changed (in case of CC 95), or the CC message is processed normally.
on ControlChangeEvent(ccMessage : ControlChangeMessage) from MidiInFcb1010
var
FCB1010_LEFT_EXPRESSION_PEDAL_CC_NUMBER : integer = 94
FCB1010_RIGHT_EXPRESSOIN_PEDAL_CC_NUMBER : integer = 95
ccNumber : integer = GetCCNumber(ccMessage)
ccValue : integer = GetCCValue(ccMessage)
lowestLowerChannel : integer = GetLowestChannel(
GetEnabledLowerAudioMixerChannels())
if ccNumber == FCB1010_LEFT_EXPRESSION_PEDAL_CC_NUMBER then
SetAudioMixerSlider(0, lowestLowerChannel - 1, ccValue)
elsif ccNumber == FCB1010_RIGHT_EXPRESSOIN_PEDAL_CC_NUMBER then
SetAudioMixerSlider(lowestLowerChannel - 1, NR_OF_SLIDERS - 1, ccValue)
else
SendNow(MidiInFcb1010, MakeControlChangeMessage(ccNumber, ccValue))
end
end
This function is called when Switch 2 of the Oxygen 61 is pressed and results in toggling the Hammond faders and the Audio Mixer faders, depending if there is a Hammond present.
on WidgetValueChanged(panelToggleValue : double) from PanelToggle
if IsHammondPresent() then
PanelToggleValueChanged(panelToggleValue)
end
end
Gig File and Script
Future ideas
- Also making it possible to switch between the two modes (drawbar/volume faders) with a foot switch on my Behringer.
- In general: a way to copy this script to ALL rackspaces, with as less possible time to spend on changes.
Script adaptability
In case you want to use the entire script, you probably need to change some things:
- I’m using the Native Instruments Vintage Organ (Kontakt) library, change the CC numbers for your Hammond plugin
- I’m using an M-Audio Oxygen 61, where you like want to use your own CCs for the sliders and toggling between the panels
- I’m using a Behringer FCB1010 midi foot controller, where you want to use your own CCs for the MIDI fool pedals.
- My laptop has high likely different screen dimensions, so the coordinates also have to be changed.
However, the article is more intended to give ideas and copy parts from which you think are useful.