Wotja contains a powerful scripting engine which, while entirely optional to use, offers tremendous power.
The Wotja Script Editor is accessed from Wotja as follows:
The Wotja Script Sandbox is accessed from Wotja as follows:
Wotja Scripting is aimed at generative music fans who want to "hack" Wotja, coders and hackers who want to play with music, and anybody who uses Wotja and wants to push the outer limits of what Wotja can do out of the box.
The Wotja Script language is based on the widely used ECMAScript scripting langauge (ECMAScript E5/E5.1). ECMAScript (also referred to commonly by the name JavaScript), is very powerful, fast and easy to learn. ECMAScript is a very popular embedded scripting langage, and is widely used in the web, gaming and multimedia worlds. Wotja adds various Wotja-specific functions to the language. These extensions are outlined later in this document; we call them "Event Handler Script Functions" or "Triggers". We give you lots of examples to get you started.
Wotja Scripts and Wotja Scripting (hereafter just "scripts", scripting etc.) can be used in two separate contexts:
Event Handler Script Functions ("Triggers")
The most common way to use scripting in Wotja is to use the Script Editor Window accessed from the IME Voice Scripts and Mix Scripts cells. This allows you to create Event Handler Script Functions ("Triggers"), which are small bits of code in the widely used ECMAScript language. The specially named Event Handler Script Functions in these scripts are triggered when various events happen when a piece is playing. Using Event Handler Script Functions allows you to tell the Voice or Piece Objects to behave in very powerful ways while the piece is playing.
Sandbox Scripts
You can use the Wotja Sandbox script window to experiment with Script code. You can show the Wotja Sandbox from the main Mix screen (press the Action menu button, and select the Script Sandbox item).
Are you a generative music fan who wants to see what your own custom code can achieve when leveraging a hugely powerful app such as Wotja? Are you code hacker who want to play with music? Are you a Wotja expert who wants to push the outer limits of what Wotja can do out of the box?
With careful use of Wotja's Event Handler Script Functions, you can do a lot of cool things, while turning Wotja into a custom hyperinstrument.
You can, if you wish, create Event Handler Script Functions to run in response to the following events:
Every script can manipulate a large number of things in Wotja in real-time. Some examples: manipulating music rules, playing with mutation, altering patterns; and what have you.
By creating code to respond to external MIDI events, you can in turn manipulate various properties of Wotja, such as auto-chording parameters, rule settings etc.
If you change a property with a script function such as imeParameterSet, the user interface doesn't always update to reflect your call; you'd need to refresh the table that displays your updated parameter, to see the change in the user interface. We hope to be able to improve this behaviour at some future point.
If you change a parameter with the user interface, and that parameter is later changed by a script; the latter script call will override your user interface change. Don't get confused by this!
If you have a script which copies a parameter value at start, and then resets it when the piece stops; where you've in between changed the parameter through the user interface; the latter script call will override your user interface change. Don't get confused by this!
The IME composes events a little bit in advance of when you'll hear them. This is to ensure that the notes are composed, in time for them to be picked-up by the ISE; the system also does the audio processing required by the ISE a little ahead of time before you actually hear it. Added together, this means that script code run in response to, say, onImeBar won't always appear precisely synchronized to what you're listening to!
Please be careful not to implement so-called Infinite Loops in your script code, as that might cause the Wotja application to crash.
Please be careful not to write script code that results in a lot of Recursion, as that might cause the Wotja application to crash.
When you decide to edit a Piece Script or Voice Script parameter, or if you select the Script Sandbox menu item, you are presented with the Script Editor window. It supports syntax-colored code editing and a console window at the bottom lets you capture logs from your scripts.
In this mode, the top panel allows you to edit Wotja Script Functions associated with your Piece or Voice..
In this mode, it is used to create and run scripts that aren't saved, and that don't access Mix properties. It is there for you to experiment with Wotja Script!
The top panel allows you to edit Wotja Script Functions associated with your object.
The panel can contain as many functions as you want, or as few as you want. Leave it blank if you don't want to use any scripting.
Here is an example with just one trigger script function:
// Just one function!
function onImeBar(bar) {
wjsLog ("onImeBar: Bar number=" + bar)
}
Here is an example with three trigger script functions:
// Three functions!
function onImeStart() {
wjsLog ("onImeStart!")
}
function onImeBar(bar) {
wjsLog ("onImeBar: Bar number=" + bar)
}
function onImeStop() {
wjsLog ("onImeStop!")
}
Pressing this button will compile any Wotja Script that you type in the large text area at the top of the window, and if the script looks valid, it will send the script to be stored within the Mix. It will take effect immediately (if your Mix is running).
Pressing this button will compile any Wotja Script that you type in the large text area at the top of the window, and display any results in the bottom panel. Use Run Script to quickly check your script for obvious syntax errors.
Note that any changes you make here aren't saved within the mix.
Pressing the Open button displays the Wotja Scripts Window, where you can select a Wotja Script file from either built-in examples, or from ones you've saved yourself (which have a .wotjascript extension). Your saved custom scripts are listed in the top section; you can save your own custom scripts in this section, by using the Save button.
Pressing the Save button lets you save the contents of your Script editor window to a document with the .wotjascript extension. You can then easily find and re-open that Script using the Open button (your saved custom scripts are listed in the top section).
Pressing the Help button displays help on Wotja Scripting system!
Pressing the Back (<) button will close the screen. If you're editing a Voice or Piece script, you'll first be prompted to save or discard any changes you might have made.
Pressing the Cancel button will discard your changes.
Any test results are displayed in the Test Results area at the bottom.
Pressing the Clear button in the bottom area, quickly erases the text in the bottom panel.
Triggers can be assigned to most Objects, including the Piece and Voice Objects.
You can enter these scripts using the following parameter groups / views:
The wjsLog function may be used to write text to the Script Console; this is very useful for debugging your scripts!
The Wotja Scripts window lets you select from a number of built-in scripts that are provided by Intermorphic. There are simple implementations of each of the Event Triggers functions for both Voice and Piece scripts, and there are a large number of Cookbook scripts for both Voice and Piece. The Cookbook scripts which are often quite detailed, and which are designed to help you get started with writing your own scripts.
When in this Window, select the item you wish to use in the Script Editor.
The top section lists any Scripts that you might have saved yourself; you can press the "Trash Can" icon to delete your user script.
The Voice Scripts parameter allows you to embed small Event Handler Script Functions, which are small bits of code in the widely used JavaScript language, that are triggered when various events happen when the Voices is playing. Specially named Event Handler Script Functions in these scripts are triggered when various events happen when a piece is playing.
The onImeStart Event Handler Script Function is called once at the start of the Voice's owning cell, when that cell starts playing.
The function has no parameters.
function onImeStart() {
wjsLog ("Voice start!")
}
The onImeBar Event Handler Script Function is called at the start of every bar while the piece is playing in its cell, starting from 1.
The function has one parameter:
function onImeBar(bar) {
wjsLog ("Voice Bar number=" + bar)
}
The onImeStop Event Handler Script Function is called once at the end of the Voice's owning cell, just as that Cell stops playing.
The function has no parameters.
function onImeStop() {
wjsLog ("Piece stop!")
}
The onImeVoiceComposed Event Handler Script Function is called when the Voice composes a note. Use this to emit MIDI CC events and what have you.
The function has five parameters:
function onImeVoiceComposed(voiceIndex, noteon, channel, pitch, velocity) {
wjsLog ("Voice Composed index=" + voiceIndex + ", noteon=" + noteon + ", channel=" + channel + ", pitch=" + pitch + ", velocity" + velocity)
}
The onImeVoiceUserController Event Handler Script Function is called when either of the Voice's User Controllers output value changes.
The function has three parameters:
function onImeVoiceUserController(voiceIndex, controllerIndex, value) {
wjsLog ("onImeVoiceUserController, voiceIndex=" + voiceIndex + ", controllerIndex=" + controllerIndex + ", value=", + value)
}
The onMIDIInCC Event Handler Script Function is called whenever a MIDI CC event is received by the MIDI Input device.
The function has three parameters:
Note that your script will only respond to MIDI In CC Events that target the MIDI Channel that your voice is attached to.
function onMIDIInCC(channel, cc, value) {
wjsLog ("Voice onMIDIInCC channel=" + channel + ", " + cc + ", " + value)
}
The onMIDIInNote Event Handler Script Event Handler Script Function is called whenever a MIDI Note On or Off event is received by the MIDI Input device.
The function has four parameters:
Note that your script will only respond to MIDI In Note Events that target the MIDI Channel that your voice is attached to.
function onMIDIInNote(channel, noteon, pitch, velocity) {
wjsLog ("Voice onMIDIInNote channel=" + channel + ", noteon=" + noteon + ", " + pitch + ", " + velocity)
}
The Piece Scripts parameters allow you to embed small Event Handler Script Functions, which are small bits of code in the widely used JavaScript language, that are triggered when various events happen when the piece is playing. Using Event Handler Script Functions allows you to tell the piece to behave in very powerful ways while it is playing.
The onImeStart Event Handler Script Function is called once at the start of the Piece's owning cell, when that cell starts playing.
The function has no parameters.
function onImeStart() {
wjsLog ("Piece start!")
}
The onImeBar Event Handler Script Function is called at the start of every bar while the piece is playing, starting from 1.
The function has one parameter:
function onImeBar(bar) {
wjsLog ("Bar number=" + bar)
}
The onImeStop Event Handler Script Function is called once at the end of the Piece's owning cell, just as that Cell stops playing.
The function has no parameters.
function onImeStop() {
wjsLog ("Piece stop!")
}
The onMIDIInCC Event Handler Script Function is called whenever a MIDI CC event is received by the MIDI Input device.
The function has three parameters:
function onMIDIInCC(channel, cc, value) {
wjsLog ("Piece onMIDIInCC channel" + channel + ", " + cc + ", " + value)
}
The onMIDIInNote Event Handler Script Event Handler Script Function is called whenever a MIDI Note On or Off event is received by the MIDI Input device.
The function has four parameters:
function onMIDIInNote(channel, noteon, pitch, velocity) {
wjsLog ("Piece MIDI in note=" + noteon + ", " + channel + ", " + pitch + ", " + velocity)
}
The following table lists the various Objects and their associated parameters together with how those objects/parameters are available to Wotja Scripts, showing: the object name; the parameter group / view (where shown to a user); the displayed name (where shown to a user); the parameter name (as supplied to functions and which is always unique for a given object); and the range of legal values that you may supply.
Parameter Group / View | Displayed Name | Script Parameter Name | Notes |
---|---|---|---|
Voice - Basics | Name | "Voice" | Voice name |
Mute | "Mute" | Yes or No | |
Patch | "Patch" | Value in range 0 to 127 | |
Use Patch? | "Use Patch?" | Yes or No | |
MIDI Channel | "MIDI Channel" | Value in range 0, 16 | |
Voice Type | "Voice Type" | "Rhythmic", "Ambient", "Follows", "Repeat Bar", "Fixed Pattern", "Listening" | |
Pitch | "Pitch" | Value in range 0 to 127 | |
Pitch Range | "Pitch Range" | Value in range 11, 127 | |
Phrase Length | "Phrase Length" | Value in range 1, 256; also in Voice - Ambient | |
Phrase Length Range | "Phrase Length Range" | Value in range 0, 256; also in Voice - Ambient | |
Phrase Gaps | "Phrase Gaps" | Value in range 0, 256; also in Voice - Ambient | |
Phrase Gaps Range | "Phrase Gaps Range" | Value in range 0, 256; also in Voice - Ambient | |
Note Rest % | "Phrase Note Rest %" | Value in range 0, 100; also in Voice - Ambient | |
Voice - Ambient | Units | "Ambient Units" | "Seconds (thousandths of a)", "Beats (60ths of a)", "Full seconds" |
Duration | "Ambient Duration" | Value in range 0, 32000 | |
Duration Range | "Ambient Duration Range" | Value in range 0, 32000 | |
Gap Minimum | "Ambient Gap Min" | Value in range 0, 32000 | |
Gap Range | "Ambient Gap Range" | Value in range 0, 32000 | |
Voice - Arcticulation | Minimum | "Articulation Minimum" | Value in range 0, 100 |
Range | "Articulation Range" | Value in range 0, 100 | |
Change | "Articulation Change" | Value in range 0, 100 | |
Change Range | "Articulation Change Range" | Value in range 0, 100 | |
Voice - Following | Follow Voice | "Follow Named Voice" | Voice name |
Percent | "Follow Percent" | Value in range 0, 100 | |
Strategy | "Follow Strategy" | "Chordal Harmony", "Interval Within Scale Rule", "Semitone Shift" | |
Units | "Follow Delay Unit" | "Seconds (thousandths of a)", "Beats (60ths of a)", "Full seconds" | |
Delay | "Follow Delay" | Value in range 0, 32000 | |
Delay Range | "Follow Delay Range" | Value in range 0, 32000 | |
Shift/Interval | "Follow Shift/Interval" | Value in range -60, +60 | |
S/I Range | "Follow Shift/Interval Range" | Value in range -60, +60 | |
Voice - Repeat | Voice | "Repeat Specific Voice" | Voice name |
Percent | "Repeat Bars Percent" | Value in range 0, 100 | |
Bars | "Repeat For Bars" | Value in range 1, 100 | |
History Range | "Repeat Bar History Range" | Value in range 0, 100 | |
History | "Repeat Bar History" | Value in range 1, 100 | |
Bars Range | "Repeat For Bars Range" | Value in range 0, 100 | |
Voice - Patterns | Patterns | "Patterns" | Pattern String |
Use Percent | "Patterns Use Percent" | Value in range 0, 100 | |
Mutation Factor | "Mutation factor" | Value from 0 to 1000 (corresponding to 0 to 100 percent) | |
Bars Between | "Mutate No. Bars" | Value in range 0, 100 | |
Bars Range | "Mutate No. Bars Range" | Value in range 0, 100 | |
Mutate Rhythm? | "Mutation of Rhythm" | Yes or No | |
Meter | "Meter" | "1:4", "2:4", "3:4", "4:4", "5:4", "6:4", "7:4", "8:4", "1:8", "2:8", "3:8", "4:8", "5:8", "6:8", "7:8", "8:8", "9:8", "10:8", "11:8", "12:8" | |
Voice - Chords | Depth | "Chord Depth" | Value in range 1, 32 |
Pitch Offset | "Chord Pitch Offset" | Value in range -60, +60 | |
Delay | "Chord Delay" | Value in range 0, 32000 | |
Depth % | "Chord Depth Percent" | Value in range 0, 100 | |
Delay Unit | "Chord Delay Unit" | "Seconds (thousandths of a)", "Beats (60ths of a)", "Quantized Beats (60ths of a)" | |
Velocity Factor | "Chord Velocity Factor" | Value in range -100, +100 | |
Delay Range | "Chord Delay Range" | Value in range 0, 32000 | |
Depth Range | "Chord Depth Range" | Value in range 0, 32 | |
Strategy | "Chord Strategy" | "Chordal Harmony", "Interval Within Scale Rule", "Semitone Shift" | |
Shift/Interval | "Chord Shift/Interval" | Value in range -60, +60 | |
S/I Range | "Chord Shift/Interval Range" | Value in range -60, +60 | |
Voice - Rules | Harmony Rules | "Harmony Rules" | Rule name |
Next Note Rules | "Next Note Rules" | Rule name | |
Rhythm Rules | "Rhythm Rules" | Rule name | |
Scale Rules | "Scale Rules" | Rule name | |
Harmonize? | "Harmonize?" | Yes or No | |
Voice Root | "Voice Root" | "A", "A#", "Ab" etc. | |
Voice - Comments | Copyright | "Copyright" | Copyright text |
Notes | "Notes" | Notes text | |
Voice - Controllers | Damper/Hold (64) | "Damper/Hold (64)" | Value in range -1, 127 |
Harmonic Content (71) | "Harmonic Content (71)" | Value in range -1, 127 | |
Reverb (91) | "Reverb (91)" | Value in range -1, 127 | |
Chorus (93) | "Chorus (93)" | Value in range -1, 127 | |
Damper Release | "Damper Release" | Yes or No | |
Portamento (84) | "Portamento (65)" | Value in range -1, 127 | |
MIDI Channel Sharing | "MIDI Channel Reallocation" | Yes or No | |
Voice - User Controller 1 | MIDI CC | "User Controller 1 Midi Command" | Value in range 0 to 127 |
Mode | "User Controller 1 Mode" | "-1 - Off", "0 - Random Drift", "1 - LFO (Min-Max-Min)", "2 - LFO (Max-Min-Max)", "3 - Sawtooth (Min-Max)", "4 - Sawtooth (Max-Min)" | |
Minimum | "User Controller 1 Minimum" | Value in range 0, 127 | |
Range | "User Controller 1 Range" | Value in range 0, 127 | |
Change | "User Controller 1 Change" | Value in range 0, 127 | |
Change Range | "User Controller 1 Change Range" | Value in range 0, 127 | |
Update | "User Controller 1 Update" | Value in range 0, 10000 | |
Update Range | "User Controller 1 Update Range" | Value in range 0, 10000 | |
Update Units | "User Controller 1 Update Unit" | "Seconds (thousandths of a)", "Full seconds" | |
Beat Cycle Length | "User Controller 1 Beat Cycle Length" | Value in range 0, 32000 | |
Phase Shift% | "User Controller 1 Phase Shift" | Value in range 0, 100 | |
Voice - User Controller 2 | MIDI CC | "User Controller 2 Midi Command" | Value in range 0 to 127 |
Mode | "User Controller 2 Mode" | "-1 - Off", "0 - Random Drift", "1 - LFO (Min-Max-Min)", "2 - LFO (Max-Min-Max)", "3 - Sawtooth (Min-Max)", "4 - Sawtooth (Max-Min)" | |
Minimum | "User Controller 2 Minimum" | Value in range 0, 127 | |
Range | "User Controller 2 Range" | Value in range 0, 127 | |
Change | "User Controller 2 Change" | Value in range 0, 127 | |
Change Range | "User Controller 2 Change Range" | Value in range 0, 127 | |
Update | "User Controller 2 Update" | Value in range 0, 10000 | |
Update Range | "User Controller 2 Update Range" | Value in range 0, 10000 | |
Beat Cycle Length | "User Controller 2 Beat Cycle Length" | Value in range 0, 32000 | |
Update Units | "User Controller 2 Update Unit" | "Seconds (thousandths of a)", "Full seconds" | |
Phase Shift% | "User Controller 2 Phase Shift" | Value in range 0, 100 | |
Voice - Micro Note Delay | Delay Range | "Micro Note Delay Range" | Value in range 0, 1000 |
Delay Change | "Micro Note Delay Change" | Value in range 0, 1000 | |
Delay Offset | "Micro Note Delay Offset" | Value in range -1000, +1000 | |
Voice - Micro Pitch | Bend Sensitivity | "Pitch Bend Sensitivity" | Value in range 0, 24 |
Pitch Bend Offset | "Pitch Bend Offset" | Value in range -8192, +8191 | |
Pitch Range | "Micro Pitch Range" | Value in range 0, 8191 | |
Pitch Change | "Micro Pitch Change" | Value in range 0, 1000 | |
Pitch Update | "Micro Pitch Update" | Value in range 0, 10000 | |
Update Range | "Micro Pitch Update Range" | Value in range 0, 10000 | |
Voice - Micro Vol Env | Range | "Micro Volume Range" | Value in range 0, 127 |
Change | "Micro Volume Change" | Value in range 0, 127 | |
Update | "Micro Volume Update" | Value in range 0, 1000 | |
Update Range | "Micro Volume Update Range" | Value in range 0, 10000 | |
Voice - Note to MIDI CC Mapping | CC for Note On? | "MIDI CC instead of Note?" | Yes or No |
Note On CC | "MIDI CC Note On Value" | Value from 0 to 127 | |
CC for Velocity? | "MIDI CC for Note On Velocity?" | Yes or No | |
Velocity CC | "MIDI CC Note On Velocity" | Value from 0 to 127 | |
CC for Off? | "MIDI CC for Note Off?" | Yes or No | |
Note Off CC | "MIDI CC Note Off Value" | Value from 0 to 127 | |
Voice - User Envelope 1 (Volume) | MIDI CC | "User Envelope 1 MIDI CC" | Value from 0 to 127 |
Enabled? | "User Envelope 1 Enabled" | Yes or No | |
Envelope | "Volume" | Envelope | |
Voice - User Envelope 2 (Pan) | MIDI CC | "User Envelope 2 MIDI CC" | Value from 0 to 127 |
Enabled? | "User Envelope 2 Enabled" | Yes or No | |
Envelope | "Pan (10)" | Envelope | |
Voice - Envelope - Velocity | Velocity | "Velocity" | Envelope |
Voice - Envelope - Velocity Range | Velocity Range | "Velocity Range" | Envelope |
Voice - Envelope - Velocity Change | Velocity Change | "Velocity Change" | Envelope |
Voice - Envelope - Velocity Change Range | Velocity Change Range | "Velocity Change Range" | Envelope |
Voice - Text to Music | Text Pattern Enabled | "Text Pattern Enabled" | Yes or No |
Text Pattern Text | "Text Pattern Text" | TTM Text String | |
Text Pattern Phrase Length | "Text Pattern Phrase Length" | Value in range 1 to 16 | |
Text Pattern Phrase Range | "Text Pattern Phrase Range" | Value in range 0 to 16 | |
Text Pattern Gaps | "Text Pattern Gaps" | Value in range 0 to 16 | |
Text Pattern Gaps Range | "Text Pattern Gaps Range" | Value in range 0 to 16 | |
Text Pattern Interval | "Text Pattern Interval" | Value in range 0 to 36 | |
Text Pattern Interval Range | "Text Pattern Interval Range" | Value in range 0 to 36 | |
Text Pattern Improvise After Tune | "Text Pattern Improvise After Tune" | Yes or No | |
Text Pattern Variation | "Text Pattern Variation" | Value in range 0 to 100 | |
Text Pattern Repeats | "Text Pattern Repeats" | Value in range 0 to 16 | |
Text Pattern Repeats Range | "Text Pattern Repeats Range" | Value in range 0 to 16 | |
Text Pattern Tune Start At Index | "Text Pattern Tune Start At Index" | Value in range 0 to 100 No | |
Text Pattern Tune Length Override | "Text Pattern Tune Length Override" | Value in range 0 to 100 No | |
Text Pattern Display | "Text Pattern Display" | Yes or No |
Parameter Group / View | Displayed Name | Script Parameter Name | Notes |
---|---|---|---|
Scale Rule | Value | "Value" |
Parameter Group / View | Displayed Name | Script Parameter Name | Notes |
---|---|---|---|
Harmony Rule | Value | "Value" |
Parameter Group / View | Displayed Name | Script Parameter Name | Notes |
---|---|---|---|
Rhythm Rule | Value | "Value" |
Parameter Group / View | Displayed Name | Script Parameter Name | Notes |
---|---|---|---|
Next Note Rule | Value | "Value" |
Parameter Group / View | Displayed Name | Script Parameter Name | Notes |
---|---|---|---|
Generative Piece Rules | Scale Rules | "Scale Rules" | |
Harmony Rules | "Harmony Rules" | ||
Next Note Rules | "Next Note Rules" | ||
Cell Rules | Meter | "Meter" | "1:4", "2:4", "3:4", "4:4", "5:4", "6:4", "7:4", "8:4", "1:8", "2:8", "3:8", "4:8", "5:8", "6:8", "7:8", "8:8", "9:8", "10:8", "11:8", "12:8" |
Parameter Group / View | Displayed Name | Script Parameter Name | Notes |
---|---|---|---|
Mix | Mix Root | "Mix Root" | "A", "A#", "Ab" etc. |
Tempo | "Tempo" | Value in range 1, 400 |
The following table all Synth Presets available to iseFxNetworkPresetSet in the current version of Wotja. The list was created using Wotja Script and the iseFxNetworkAllPresetNamesGet function.
sounds/Bass/Bass fat swept.tg sounds/Bass/Bass filter sweep.tg sounds/Bass/Bass pluck soft.tg sounds/Bass/Bass plucked bright.tg sounds/Bass/Bass pulser.tg sounds/Beats/Beats ch10 eperc wt.tg sounds/Beats/Beats ch10 imdrums wt.tg sounds/Beats/Beats ch10 ogglegacy wt.tg sounds/Bell/Bell bright.tg sounds/Bell/Bell combo.tg sounds/Bell/Bell glass felt.tg sounds/Bell/Bell glass tri.tg sounds/Bell/Bell synth bright.tg sounds/Bell/Bell synth soft.tg sounds/Drone/Drone cosmic 1.tg sounds/Drone/Drone cosmic 2.tg sounds/Drone/Drone fizz 2.tg sounds/Drone/Drone fizz.tg sounds/Drone/Drone fuzz.tg sounds/Drone/Drone motor.tg sounds/Drone/Drone strings octave.tg sounds/Drone/Drone strings.tg sounds/Drone/Drone synth soft.tg sounds/Drone/Drone voxaa.tg sounds/Drone/Drone warm fizzer.tg sounds/E-piano/E-Piano 2.tg sounds/E-piano/E-Piano blend 2.tg sounds/E-piano/E-Piano blend.tg sounds/E-piano/E-Piano bowed.tg sounds/E-piano/E-Piano bright.tg sounds/E-piano/E-Piano shimmer.tg sounds/E-piano/E-Piano soft.tg sounds/E-piano/E-Piano space.tg sounds/E-piano/E-Piano.tg sounds/Lead/Lead bob.tg sounds/Lead/Lead dsynth soft warm.tg sounds/MO1-Lead/Brassy.tg sounds/MO1-Lead/Breathy chime.tg sounds/MO1-Lead/Bright FM keys 1.tg sounds/MO1-Lead/Chime bar 1.tg sounds/MO1-Lead/FM keys 1.tg sounds/MO1-Lead/FM keys 2.tg sounds/MO1-Lead/FM keys 3.tg sounds/MO1-Lead/FM keys 4.tg sounds/MO1-Lead/FM keys 5.tg sounds/MO1-Lead/FM keys 6.tg sounds/MO1-Lead/FM pluck.tg sounds/MO1-Lead/Felt mallet chime.tg sounds/MO1-Lead/Filter warble.tg sounds/MO1-Lead/Harmonic scan 1.tg sounds/MO1-Lead/Inverse harmonic scan.tg sounds/MO1-Lead/Mellow FM keys 1.tg sounds/MO1-Lead/Perc hi-lo.tg sounds/MO1-Lead/Pluck octaves.tg sounds/MO1-Lead/Rattle plate.tg sounds/MO1-Lead/Resonant filter sweep.tg sounds/MO1-Lead/Ringing sine.tg sounds/MO1-Lead/Slight vocal.tg sounds/MO1-Lead/Soft bright lead.tg sounds/MO1-Lead/Soft filter sweep.tg sounds/MO1-Lead/Soft hi-lo.tg sounds/MO1-Lead/Soft perc tine.tg sounds/MO1-Lead/Soft pluck bright tail.tg sounds/MO1-Lead/Staccato supersaws hard attack.tg sounds/MO1-Lead/Staccato supersaws.tg sounds/MO1-Lead/Supersaws hard attack.tg sounds/MO1-Lead/Supersaws.tg sounds/MO1-Lead/Tuned noise.tg sounds/MO1-Lead/WTable scan 1.tg sounds/MO1-Lead/WTable scan 2.tg sounds/MO1-Lead/WTable scan 3.tg sounds/MO1-Lead/WTable scan 4.tg sounds/MO1-Lead/WTable scan 5.tg sounds/MO1-Lead/WTable scan 6.tg sounds/Multi/Multi 3 op fm template.tg sounds/Multi/Multi piano strings.tg sounds/Multi/Multi wavetable crossfade template.tg sounds/Noise/Noise mains hum.tg sounds/Noise/Noise on the beach.tg sounds/Noise/Noise ring mod high bell.tg sounds/Noise/Noise tuned breezes.tg sounds/Pad/Pad bowed.tg sounds/Pad/Pad brass metal shimmer.tg sounds/Pad/Pad brass soft.tg sounds/Pad/Pad brassy.tg sounds/Pad/Pad coda mod.tg sounds/Pad/Pad epiano.tg sounds/Pad/Pad fizz grower.tg sounds/Pad/Pad fizz.tg sounds/Pad/Pad hummer.tg sounds/Pad/Pad outer space.tg sounds/Pad/Pad pipe shimmer.tg sounds/Pad/Pad pitched metal.tg sounds/Pad/Pad side trails vib.tg sounds/Pad/Pad soft chev 2.tg sounds/Pad/Pad soft easel.tg sounds/Pad/Pad soft ep 1.tg sounds/Pad/Pad soft ep 2.tg sounds/Pad/Pad soft for chording.tg sounds/Pad/Pad soft tremolo.tg sounds/Pad/Pad space park 1.tg sounds/Pad/Pad space park 2.tg sounds/Pad/Pad space park 3.tg sounds/Pad/Pad space scape.tg sounds/Pad/Pad space shimmer.tg sounds/Pad/Pad space wind.tg sounds/Pad/Pad synth 1.tg sounds/Pad/Pad synth 2.tg sounds/Pad/Pad unresolved.tg sounds/Pad/Pad warm chev 1.tg sounds/Pad/Pad warm soft.tg sounds/Perc/Perc beat sync noise.tg sounds/Piano/Piano blend bright.tg sounds/Piano/Piano blend upright.tg sounds/Piano/Piano brass.tg sounds/Piano/Piano damped bright.tg sounds/Piano/Piano damped long 1.tg sounds/Piano/Piano damped long 2.tg sounds/Piano/Piano damped.tg sounds/Piano/Piano upright long.tg sounds/Piano/Piano upright wide.tg sounds/Pluck/Pluck guitar bell bright.tg sounds/Pluck/Pluck guitar blend edge.tg sounds/Pluck/Pluck guitar blend ep.tg sounds/Pluck/Pluck guitar blend osc.tg sounds/Pluck/Pluck guitar blend soft.tg sounds/Pluck/Pluck guitar blend steel.tg sounds/Pluck/Pluck guitar bowed.tg sounds/Strings/Strings build.tg sounds/Strings/Strings distant.tg sounds/Strings/Strings slow.tg sounds/Strings/Strings tremolo.tg sounds/Synth/Synth beat sync filter blip.tg sounds/Synth/Synth dsynth warm 2.tg sounds/Synth/Synth fizz pulse.tg sounds/Synth/Synth fizz soft.tg sounds/Synth/Synth organ electric.tg sounds/Synth/Synth pwm.tg sounds/Synth/Synth saw phase offset.tg sounds/Synth/Synth slow vowel morph.tg sounds/Synth/Synth soft lead.tg sounds/Synth/Synth subtractive template 1.tg sounds/Synth/Synth subtractive template.tg sounds/Synth/Synth swept harmonics.tg sounds/Synth/Synth wavetable simple vibrato.tg sounds/Units/Unit dsynth.tg sounds/Units/Unit osc.tg sounds/Units/Unit particle.tg sounds/Units/Unit wavetable.tg
The following table all Effect Presets available to iseFxNetworkPresetSet in the current version of Wotja. The list was created using Wotja Script and the iseFxNetworkAllPresetNamesGet function.
fx/AllInOne/Combi chorus delay reverb 2.fxm fx/AllInOne/Combi chorus delay reverb.fxm fx/AllInOne/Combi chorus reverb.fxm fx/AllInOne/Combi compressor chorus delay eq.fxm fx/AllInOne/Combi compressor chorus delay reverb eq.fxm fx/AllInOne/Combi delay chorus reverb.fxm fx/AllInOne/Combi delay eq.fxm fx/AllInOne/Combi delay reverb eq.fxm fx/AllInOne/Combi eq chorus reverb.fxm fx/AllInOne/Combi filter delay 2.fxm fx/AllInOne/Combi filter delay reverb muted.fxm fx/AllInOne/Combi filter delay shift.fxm fx/AllInOne/Combi filter delay.fxm fx/AllInOne/Combi filter eq reverb.fxm fx/AllInOne/Combi filter shifter.fxm fx/AllInOne/Combi lfo filter chorus reverb.fxm fx/AllInOne/Combi lfo filter chorus.fxm fx/AllInOne/Combi mix eq compressor reverb.fxm fx/AllInOne/Combi reverb eq.fxm fx/AllInOne/Combi reverb lfo filter.fxm fx/Amp/- Amp default.fxm fx/Amp/Amp quad.fxm fx/Chorus/- Chorus default.fxm fx/Chorus/Chorus deep.fxm fx/Chorus/Chorus double.fxm fx/Chorus/Chorus fast flange.fxm fx/Chorus/Chorus feedback.fxm fx/Chorus/Chorus light.fxm fx/Chorus/Chorus medium.fxm fx/Chorus/Chorus strong.fxm fx/Compressor/- Compressor default.fxm fx/Compressor/Compressor basic.fxm fx/Compressor/Compressor low end boost.fxm fx/Compressor/Compressor mild.fxm fx/Compressor/Compressor smooth.fxm fx/Compressor/Compressor tight.fxm fx/Delay/- Delay default.fxm fx/Delay/Delay bounce.fxm fx/Delay/Delay double sync.fxm fx/Delay/Delay doubling.fxm fx/Delay/Delay echoer.fxm fx/Delay/Delay filtered mono.fxm fx/Delay/Delay filtered sync pan.fxm fx/Delay/Delay long.fxm fx/Delay/Delay resonator.fxm fx/Delay/Delay simple.fxm fx/Delay/Delay slapback.fxm fx/Delay/Delay tight slapback.fxm fx/Distortion/- Distortion default.fxm fx/Distortion/Distortion broken filter.fxm fx/Distortion/Distortion fuzz drive.fxm fx/Distortion/Distortion fuzz.fxm fx/Distortion/Distortion mild.fxm fx/EQ/- Equaliser default.fxm fx/EQ/Equaliser hi cut.fxm fx/EQ/Equaliser lo cut.fxm fx/EQ/Equaliser mid.fxm fx/Filter/- Filter default.fxm fx/Filter/FIlter 4Hz auto wah.fxm fx/Filter/Filter 2Hz autowah.fxm fx/Filter/Filter 4Hz autowah.fxm fx/Filter/Filter dirty.fxm fx/Filter/Filter hi cut.fxm fx/Filter/Filter high fast sweep.fxm fx/Filter/Filter parallel bandpass 2 bar sweep.fxm fx/Filter/Filter slow auto wah.fxm fx/Filter/Filter slow sweep hi q.fxm fx/Filter/Filter subtle sweep.fxm fx/Filter/Filter telephone.fxm fx/Overdrive/- Overdrive default.fxm fx/Overdrive/Overdrive extreme.fxm fx/Overdrive/Overdrive harmonics.fxm fx/Overdrive/Overdrive hot.fxm fx/Overdrive/Overdrive serious.fxm fx/Overdrive/Overdrive warm.fxm fx/Pan/Pan auto.fxm fx/Pan/Pan shimmer.fxm fx/Reverb/- Reverb default.fxm fx/Reverb/Reverb 5 second.fxm fx/Reverb/Reverb 9 second.fxm fx/Reverb/Reverb basement.fxm fx/Reverb/Reverb bright hall.fxm fx/Reverb/Reverb bright plate.fxm fx/Reverb/Reverb bright small room.fxm fx/Reverb/Reverb drum hallway.fxm fx/Reverb/Reverb drum studio.fxm fx/Reverb/Reverb light ambience.fxm fx/Reverb/Reverb medium room.fxm fx/Reverb/Reverb resonant metallic.fxm fx/Reverb/Reverb ringing 6 second.fxm fx/Reverb/Reverb slapback room.fxm fx/Reverb/Reverb smooth 10 second.fxm fx/Volume/Volume 10 second duck.fxm fx/Volume/Volume 4hz gate pan.fxm fx/Volume/Volume 4hz gate.fxm fx/Volume/Volume swell.fxm fx/Volume/Volume tremolo fast.fxm fx/Volume/Volume tremolo mono 2xbpm sync.fxm fx/Volume/Volume tremolo pan.fxm fx/Volume/Volume tremolo slow.fxm fx/Volume/Volume tremolo stereo 2xbpm sync.fxm
Wotja Script Utility functions all start with the wjs prefix
wjsLog ()
The function wjsLog may be used to display text in the Script Console; this is very useful for debugging your scripts!
Example:
function onImeStart() {
wjsLog("Hello World!")
}
wjsGetRandom ()
This function returns a random integer.
The function has no parameters.
Example:
var value = wjsGetRandom ()
wjsRandomGetFromTo (minimum, maximum)
This function returns a random integer in the range of the two supplied values.
The function has two parameters:
Example:
function onImeStart() {
// Get a random integer between 0 and 50 inclusive.
var value = wjsRandomGetFromTo (0, 50)
wjsLog("random value=", value)
}
The IME contains many powerful scripting features. The IME related functions all start with the ime prefix.
imeParameterSet (parameterName, newValue)
This function is used to set the object's parameter to the supplied value, for the object within whose trigger script you place this call.
The function has two parameters:
Example:
function onImeStart() {
// Set the Chord Depth to 4 (assuming we make this call from within a
// Voice's trigger script!)
var chordDepth = 4
imeParameterSet("Chord Depth", chordDepth)
}
imeParameterGet (parameterName)
This function returns the value of the named parameter, for the object within whose trigger script you place this call. Note that the value returned is always a string, which you can convert to a number using tonumber().
The function has one parameter:
Example:
function onImeStart() {
// Get the current Chord Depth (assuming we make this call from within a
// Voice's trigger script!)
var chordDepth = imeParameterGet("Chord Depth")
wjsLog ("Chord Depth=" + chordDepth)
}
imeVoiceMIDIChannelGet()
This function returns the MIDI channel (assuming the script is called from within a voice script!). The value returned is a value from 0 to 15 (MIDI channel is actually displayed in the IME Network screen as 1 to 16).
The function has no parameters.
Example:
function onImeStart() {
var channel = imeVoiceMIDIChannelGet ()
wjsLog ("Channel=" + channel)
}
imeRuleElementGet (ruleObjectType, ruleObjectIndex, ruleElementIndex)
This function returns the rule element value of the specified index, for the indexed rule object. The value returned is a value between 0 and 127.
The function has the following parameters:
Example 1:
function onImeStart() {
// Dump out the scale rule element values, for the first scale.
var scaleRuleIndex = 0
var itemIndex = 0
while (itemIndex < 12)
{
var value = imeRuleElementGet ("Scale Rule", scaleRuleIndex, itemIndex)
wjsLog ("value=" + value)
index = itemIndex + 1
}
}
Example 2:
function onImeStart() {
var scaleRuleCount = imeObjectCountGet("Scale Rule")
wjsLog ("Scale Rule objects=" + scaleRuleCount)
for (var scaleRuleIndex = 0; scaleRuleIndex < scaleRuleCount; scaleRuleIndex++) {
// Dump out the scale rule element values, for the scale!
var ruleName = imeObjectNameGet("Scale Rule", scaleRuleIndex)
wjsLog ("Scale=" + ruleName)
var itemIndex = 0
while (itemIndex < 12)
{
var value = imeRuleElementGet ("Scale Rule", scaleRuleIndex, itemIndex)
wjsLog ("itemIndex" + ", " + itemIndex + ", " + "value" + ", " + value)
itemIndex = itemIndex + 1
}
}
}
imeMIDISendCC (channel, cc, value [, delay])
This function emits the specified MIDI CC event.
The function has the following parameters:
Example:
function onImeBar(bar) {
// Voice trigger...
// Apply a pan sweep through the bar from left to right,
// to show-off the use of imeMIDISendCC.
var duration = imeBarDurationGet()
var midiChannel = imeVoiceMIDIChannelGet()
var delay = 0
var ccController = 10 // Pan controller!
var value = 0
while delay <= duration {
var value = (127 * delay) / duration
// Note that the "delay" is optional; we use this in this specific
// demo, to get a sweep effect from start to end of the bar.
imeMIDISendCC(midiChannel, ccController, value, delay)
delay = delay + 20
}
}
imeBarDurationGet ()
This function returns the duration of the piece bar, in IME pattern time units; where 240 represents four crotchets or one whole note or a bar of 4:4 time.
The function has no parameters.
Example:
function onImeStart() {
var duration = imeBarDurationGet()
wjsLog ("duration=" + duration)
}
imeObjectCountGet (objectType)
Returns the number of objects of the specified type, in the current Wotja Mix.
The function has the following parameters:
Example:
function onImeStart() {
var voiceCount = imeObjectCountGet("Voice")
wjsLog ("Voice objects=" + voiceCount)
}
imeObjectIndexGet (objectType, objectIndex)
Returns the index of the named object, which will be greater than or equal to 0 if the named object is found; the function will return -1 if not found.
The function has the following parameters:
Example:
function onImeStart() {
var majorScaleRuleIndex = imeObjectIndexGet("Scale Rule", "Major")
wjsLog ("majorScaleRuleIndex=" + majorScaleRuleIndex)
}
imeObjectNameGet (objectType, objectIndex)
Returns the name of the specified object.
The function has the following parameters:
Example:
function onImeStart() {
var voiceCount = imeObjectCountGet("Voice")
wjsLog ("Voice objects=" + voiceCount)
for (var index = 0; index < voiceCount; index++) {
wjsLog ("Voice name=" + imeObjectNameGet("Voice", index))
}
}
imeObjectParameterGet (objectType, objectIndex, parameterName)
Returns the value of the parameter, for the specified object index of the specified object type, in the playing piece.
The function has the following parameters:
Example:
function onImeStart() {
var valueWas = imeObjectParameterGet("Voice", 0, "Chord Depth")
imeObjectParameterSet("Voice", 0, "Chord Depth", 4)
var valueNow = imeObjectParameterGet("Voice", 0, "Chord Depth")
wjsLog("Chord Depth valueWas=" + valueWas + ", valueNow = " + valueNow)
}
imeObjectParameterSet (objectType, objectIndex, parameterName, newValue)
Sets the parameter to the the supplied value, for the specified object index of the specified object type, in the playing piece.
The function has the following parameters:
Example:
function onImeStart() {
var valueWas = imeObjectParameterGet("Voice", 0, "Chord Depth")
imeObjectParameterSet("Voice", 0, "Chord Depth", 4)
var valueNow = imeObjectParameterGet("Voice", 0, "Chord Depth")
wjsLog("Chord Depth valueWas=" + valueWas + ", valueNow = " + valueNow)
}
imePieceElapsedPercentGet ()
Returns the elapsed percentage of the playing piece, within the context of it's container cell. A cell with duration set to "Infinite" is actually around 8 hours before it restarts; so will tend to report 0 percent. A cell with duration of just a few bars, will progress quickly from 0 through to 100.
The function has no parameters.
Example:
function onImeBar() {
var value = imePieceElapsedPercentGet()
wjsLog ("imePieceElapsedPercentGet=" + value)
}
imeRuleElementSet (ruleObjectType, ruleObjectIndex, ruleElementIndex, newValue)
This function set the rule element value of the specified index, for the indexed rule object, to the specified value. The value must be between 0 and 127.
The function has the following parameters:
Example 1:
function onImeStart() {
// Set the scale rule element values, to odd settings (!), for the first scale.
var scaleRuleIndex = 0
var itemIndex = 0
while (itemIndex < 12) {
imeRuleElementSet ("Scale Rule", scaleRuleIndex, itemIndex, (itemIndex * 127) / 12)
itemIndex = itemIndex + 1
}
}
Example 2:
function onImeStart() {
var ruleCount = imeObjectCountGet("Scale Rule")
wjsLog ("Scale Rule objects=" + ruleCount)
for (var scaleRuleIndex = 0; scaleRuleIndex < ruleCount; scaleRuleIndex++) {
// Set the scale rule element values, for the scale, to stupid values!
var ruleName = imeObjectNameGet("Scale Rule", scaleRuleIndex)
wjsLog ("Scale=" + ruleName)
var itemIndex = 0
while (itemIndex < 12) {
var value = (itemIndex * 127) / 12
imeRuleElementSet ("Scale Rule", scaleRuleIndex, itemIndex, value)
itemIndex = itemIndex + 1
}
}
}
imeVoiceEnvelopePercentGet (voiceObjectIndex, parameterName, percent)
This function returns the percent value for the specified envelope at the given percent position. The value returned is a value between 0 and 127.
The function has the following parameters:
Example:
function onImeStart() {
var voiceCount = imeObjectCountGet("Voice")
wjsLog ("Voice objects=" + voiceCount)
for (var voiceIndex = 0; voiceIndex < voiceCount; voiceIndex++) {
// Ramp-up every voice volume envelope!
var voiceName = imeObjectNameGet("Voice", voiceIndex)
wjsLog ("Voice=" + voiceName)
var percent = 0
while (percent <= 100)
{
var valueWas = imeVoiceEnvelopePercentGet (voiceIndex, "Volume", percent)
wjsLog ("Volume at " + percent + ", " + "was=" + valueWas)
var setToValue = percent + 1
wjsLog ("set to new value =" + setToValue)
imeVoiceEnvelopePercentSet (voiceIndex, "Volume", percent, setToValue)
var valueNow = imeVoiceEnvelopePercentGet (voiceIndex, "Volume", percent)
wjsLog ("Volume at " + percent + ", " + "now=" + valueNow + "\n")
percent = percent + 1
}
}
}
imeVoiceEnvelopePercentSet (voiceObjectIndex, parameterName, percent, newValue)
This function sets the envelope value at the specified percent, for the indexed voice, to the specified value. The value must be between 0 and 127.
The function has the following parameters:
Example:
function onImeStart() {
var voiceCount = imeObjectCountGet("Voice")
wjsLog ("Voice objects=" + voiceCount)
for (var voiceIndex = 0; voiceIndex < voiceCount; voiceIndex++) {
// Ramp-up every voice volume envelope!
var voiceName = imeObjectNameGet("Voice", voiceIndex)
wjsLog ("Voice=" + voiceName)
var percent = 0
while (percent <= 100)
{
var valueWas = imeVoiceEnvelopePercentGet (voiceIndex, "Volume", percent)
wjsLog ("Volume at " + percent + ", " + "was=" + valueWas)
var setToValue = percent + 1
wjsLog ("set to new value =" + setToValue)
imeVoiceEnvelopePercentSet (voiceIndex, "Volume", percent, setToValue)
var valueNow = imeVoiceEnvelopePercentGet (voiceIndex, "Volume", percent)
wjsLog ("Volume at " + percent + ", " + "now=" + valueNow + "\n")
percent = percent + 1
}
}
}
imeCellTrackIndexGet()
This function returns the track index of the Mix Cell containing the current voice/piece. This is used with various ISE related functions.
The function has no parameters
Example:
function onImeStart() {
var cellTrackIndex = imeCellTrackIndexGet()
}
imeCellColumnIndexGet()
This function returns the column index of the Mix Cell containing the current voice/piece. This is used with various ISE related functions.
The function has no parameters
Example:
function onImeStart() {
var cellColumnIndex = imeCellColumnIndexGet()
}
ISE related functions all start with the ise prefix
iseGetFxNetworkIdForMix()
This function returns the id that can be used for manipulating the effects chain for the Global Mix FX.
The function has no parameters
Example:
function onImeStart() {
var fxNetworkIdForMix = iseGetFxNetworkIdForMix()
}
iseGetFxNetworkIdForCellGlobal(trackIndex, columnIndex)
This function returns the id that can be used for manipulating the effects chain for the Cell, identified by the supplied track and column indexes.
The function has the following parameters:
Example:
function onImeStart() {
var fxNetworkIdForCellAtTrack0Column1 = iseGetFxNetworkIdForCellGlobal(0, 1)
}
iseGetFxNetworkIdForCellSynthTrackColumnChannel(trackIndex, columnIndex, channel)
This function returns the id that can be used for manipulating the effects chain for the Cell, identified by the supplied track and column indexes.
The function has the following parameters:
Example:
function onImeStart() {
var synthFxNetworkIdForCellAtTrack0Column1MIDIChannel2 = iseGetFxNetworkIdForCellSynthTrackColumnChannel(0, 1, 2)
}
iseGetFxNetworkIdForCellEffectTrackColumnChannel()
This function returns the id that can be used for manipulating the effects chain for the Cell, identified by the supplied track and column indexes.
The function has the following parameters:
Example:
function onImeStart() {
var trackFxNetworkIdForCellAtTrack0Column1MIDIChannel2 = iseGetFxNetworkIdForCellEffectTrackColumnChannel(0, 1, 2)
}
iseFxNetworkAllPresetNamesGet(fxNetworkId)
This function returns an array of all FX presets that can be supplied to the FX network with the specified ID. The list returned using an FX Network ID generated by iseGetFxNetworkIdForCellSynthTrackColumnChannel is different to those using other FX network IDs (which all otherwise return the same array of values)
The function has the following parameters:
Example:
function onImeStart() {
var fxNetworkIdForMix = iseGetFxNetworkIdForMix()
var allEffectsPresets = iseFxNetworkAllPresetNamesGet(fxNetworkIdForMix)
// Display the preset names on the console
for (var effectPresetIndex = 0; effectPresetIndex < allEffectsPresets.length; effectPresetIndex++) {
wjsLog(allEffectsPresets.length[effectPresetIndex])
}
var synthFxNetworkId = iseGetFxNetworkIdForCellSynthTrackColumnChannel(0, 0, 0)
var allSynthPresets = iseFxNetworkAllPresetNamesGet(synthFxNetworkId)
// Display the preset names on the console
for (var synthFxIndex = 0; synthFxIndex < allSynthPresets.length; synthFxIndex++) {
wjsLog(allSynthPresets.length[synthFxIndex])
}
}
iseFxNetworkRandomPresetNamesGet(fxNetworkId)
This function returns an array of all FX presets that can be supplied to the FX network with the specified ID; filtered such that only the presets that you have enabled in your current randomization scheme are returned. The list returned using an FX Network ID generated by iseGetFxNetworkIdForCellSynthTrackColumnChannel is different to those using other FX network IDs (which all otherwise return the same array of values)
The function has the following parameters:
Example:
function onImeStart() {
var fxNetworkIdForMix = iseGetFxNetworkIdForMix()
var allEffectsPresets = iseFxNetworkRandomPresetNamesGet(fxNetworkIdForMix)
// Display the preset names on the console
for (var effectPresetIndex = 0; effectPresetIndex < allEffectsPresets.length; effectPresetIndex++) {
wjsLog(allEffectsPresets.length[effectPresetIndex])
}
var synthFxNetworkId = iseGetFxNetworkIdForCellSynthTrackColumnChannel(0, 0, 0)
var allSynthPresets = iseFxNetworkRandomPresetNamesGet(synthFxNetworkId)
// Display the preset names on the console
for (var synthFxIndex = 0; synthFxIndex < allSynthPresets.length; synthFxIndex++) {
wjsLog(allSynthPresets.length[synthFxIndex])
}
}
iseFxNetworkPresetSet(fxNetworkId, fxPreset)
This function applies the specified FX Preset to the specified FX Network
The function has the following parameters:
Example:
function onImeStart() {
var fxNetworkIdForMix = iseGetFxNetworkIdForMix()
iseFxNetworkPresetSet(fxNetworkIdForMix, "fx/Filter/Filter 4Hz autowah.fxm")
}
imeCellTrackIndexGet()
This function returns the cell index for the current mix.
The function has the following parameters:
Example:
function onImeStart() {
var fxNetworkIdForMix = iseGetFxNetworkIdForMix()
iseFxNetworkPresetSet(fxNetworkIdForMix, "fx/Filter/Filter 4Hz autowah.fxm")
}
ITE related functions all start with the ite prefix
iteRandomWordsGet (numberOfWords)
This function returns a string containing a number of random words.
The function has the following parameters:
Example:
function onImeStart() {
// Make a string with 3 random words
var ttmText = iteRandomWordsGet(3)
// Set the TTM text using our random string
imeParameterSet("Text Pattern Text", ttmText)
}
iteShuffleWords (textToShuffle)
This function returns a string containing a shuffled version of the suppled text. The words preserved from the supplied text, but the order of those words is changed.
The function has the following parameters:
Example:
function onImeStart() {
// Make a string that is a random shuffle of words
var textToShuffle = "Shuffle these four words"
var ttmText = iteShuffleWords(textToShuffle)
// Set the TTM text using our shuffled string
imeParameterSet("Text Pattern Text", ttmText)
}
iteShuffleCharacters (textToShuffle)
This function returns a string containing a shuffled version of the suppled text. All the characters are shuffled; words are broken-up.
The function has the following parameters:
Example:
function onImeStart() {
// Make a string that is a random shuffle of characters
var textToShuffle = "Shuffle these characters"
var ttmText = iteShuffleCharacters(textToShuffle)
// Set the TTM text using our shuffled string
imeParameterSet("Text Pattern Text", ttmText)
}
A great way to start thinking about Event Handler Script Functions, is to look at various real examples of how to do various interesting things with Event Handler Script Functions!
This is a script that you could use as a piece-level Bar trigger script.
function onImeStart() {
var date = new Date()
var hour = date.getHours()
if ((hour > 20) || (hour <8)) {
imeParameterSet("Scale Rules", "early morning scale")
} else {
imeParameterSet("Scale Rules", "middle of day scale")
}
}
This is a voice-level Bar trigger script.
function onImeStart() {
// Get a random integer between 1 and 3 inclusive.
var value = wjsRandomGetFromTo (1, 3)
wjsLog ("value=" + value)
var patternString = ""
if (value == 1) {
patternString = "<100 B 240 1>"
} else if (value == 2) {
patternString = "<100 B 120 1 120 2>"
} else {
patternString = "<100 B 60 1 60 2 60 3 60 4>"
}
imeParameterSet("Patterns", patternString)
}
This is a script that you could use as a piece-level Bar trigger script.
function onImeBar(bar) {
// Voice trigger...
// Apply a pan sweep through the bar from left to right,
// to show-off the use of imeMIDISendCC.
wjsLog ("onImeBar(" + index + ") - Voice")
var barDuration = imeBarDurationGet()
wjsLog ("barDuration=" + barDuration)
var midiChannel = imeVoiceMIDIChannelGet()
var delay = 0
var ccController = 10 // Pan controller!
var value = 0
while (delay <= barDuration) {
var value = (127 * delay) / barDuration
// Note that the "delay" is optional; we're using the in this specific
// demo, to get a sweep effect from start to end of the bar.
imeMIDISendCC(midiChannel, ccController, value, delay)
delay = delay + 20
}
}
function onImeBar(bar) {
// Piece trigger...
// Change bar / tempo every 2 bars...
wjsLog ("onImeBar(" + bar + ") - Piece")
if ( ((bar + 1) % 2) == 0) {
wjsLog ("bar=" + bar)
var rootWas = imeParameterGet("Mix Root")
wjsLog ("Piece/Mix Root was=" + rootWas)
// Every 2 bars, change the root at random,
// from all those available!
var roots = ["A", "A#", "B", "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#"]
var rootIndex = wjsRandomGetFromTo(0, roots.length-1)
var newRoot = roots[rootIndex]
wjsLog ("New root=" + newRoot)
imeParameterSet("Mix Root", newRoot)
// Set tempo as well; to a value related to the selected root!
var tempoWas = imeParameterGet("Tempo")
wjsLog ("Piece/Mix tempo was=" + tempoWas)
var newTempo = 100 + rootIndex * 5
wjsLog ("New tempo=" + newTempo)
imeParameterSet("Tempo", newTempo)
}
}
// Choose a random root
function chooseRandomRoot() {
var roots = ["A", "A#", "B", "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#"]
var rootIndex = wjsRandomGetFromTo(0, roots.length-1)
var newRoot = roots[rootIndex]
return newRoot
}
// Check if the specified Scale Rule name exists in the mix
function getDoesScaleRuleExistWithThisName(lookForRuleName) {
var scaleRuleCount = imeObjectCountGet("Scale Rule")
//wjsLog ("Scale Rules objects=" + scaleRuleCount)
for (var index = 0; index < scaleRuleCount; index++) {
var scaleRuleName = imeObjectNameGet("Scale Rule", index)
// wjsLog ("scaleRuleName=" + scaleRuleName)
if (lookForRuleName == scaleRuleName) {
// Found the rule, so return true.
return true
}
}
// To get here, the rule wasn't found, so return false.
return false
}
// Event Triggers
function onImeBar(bar) {
// Piece trigger...
// Change bar / scale rule every 2 bars...
// Note that this requires you to have at least two scale rules;
// one called "Major" and one called "Minor"
wjsLog ("onImeBar(" + bar + ") - Piece")
// Every 2 bars, change the root at random, from all those available!
if ( ((bar + 1) % 2) == 0) {
wjsLog ("bar=" + bar)
var rootWas = imeParameterGet("Mix Root")
wjsLog ("Piece/Mix Root was=" + rootWas)
var newRoot = chooseRandomRoot()
imeParameterSet("Mix Root", newRoot)
wjsLog ("Piece/Mix Root now=" + newRoot)
// Set scale as well; to a value related to the selected root.
// Choose one of two Scale Rule names at random.
var useRuleName = ""
if (wjsRandomGetFromTo(0, 100) <= 50) {
useRuleName = "Major"
} else {
useRuleName = "Minor"
}
if (getDoesScaleRuleExistWithThisName(useRuleName)) {
wjsLog ("Piece/Mix Scale Rule set to=" + useRuleName)
// Apply rule to all voices!
var voiceCount = imeObjectCountGet("Voice")
// wjsLog ("Voice objects=" + voiceCount)
for (var voiceIndex = 0; voiceIndex < voiceCount; voiceIndex++) {
// wjsLog ("Voice name=" + imeObjectNameGet("Voice", voiceIndex))
imeObjectParameterSet("Voice", voiceIndex, "Scale Rules", useRuleName)
}
} else {
wjsLog("Warning - rule name not found=" + useRuleName)
}
}
}
function onImeStart() {
wjsLog ("Piece!")
// Wotja script to get hour of day as 24-hour clock value
// ... and adjust tempo accordingly!
var date = new Date()
var hour = date.getHours()
if ((hour > 20) || (hour <8)) {
wjsLog ("late night / early morning!")
var randomValue = wjsRandomGetFromTo(0,50)
imeParameterSet("Tempo", 50 + randomValue)
} else {
wjsLog ("middle of day!")
var randomValue = wjsRandomGetFromTo(0,50)
imeParameterSet("Tempo", 100 + randomValue)
}
}
function onImeStart() {
wjsLog ("Voice!")
var chordDepth = imeParameterGet("Chord Depth")
// Convert any string value to integer, then add one.
chordDepth = parseInt(chordDepth) + 1
// Loop the value around if it gets larger than we want.
if (chordDepth > 8) {
chordDepth = 1
}
imeParameterSet("Chord Depth", chordDepth)
}
function onImeBar(bar) {
wjsLog ("onImeBar, bar=" + bar)
var chordDepth = imeParameterGet("Chord Depth")
// Convert any string value to integer, then add one.
chordDepth = parseInt(chordDepth) + 1
// Loop the value around if it gets larger than we want.
if (chordDepth > 8) {
chordDepth = 1
}
imeParameterSet("Chord Depth", chordDepth)
}
In this example, imagine that you have a mutating drum Voice that you want to have muted at the start of the piece and come in with a bang at the start of bar 20. And you don't want the mutations to start until bar 21...
How would that work in the world of script?
Here is the Voice Start trigger:
function onImeStart() {
// When we start, disable mutation for this Voice!
// And set mute, too!
imeParameterSet("Mute", "Yes")
imeParameterSet("Mutation Factor", 0)
}
Here is the Voice Bar trigger:
function onImeBar(bar) {
if (bar == 20) {
// At bar 20, unmute the voice!
imeParameterSet("Mute", "No")
}
if (bar == 21) {
// At bar 21, adjust the mutation factor!
imeParameterSet("Mutation Factor", 20)
}
}
The power of using scripts like this, is that:
var GLastNote = null
function onImeVoiceComposed(voiceIndex, noteon, channel, pitch, velocity) {
// Keep track of last composed note using the global (for this voice)
// called GLastNote ...
// Note that the "pitch" parameter should be ignored when noteon is false.
midiChannel = imeVoiceMIDIChannelGet()
if (noteon) {
if (GLastNote != null) {
imeMIDISendCC(midiChannel, 11, GLastNote, 10)
}
GLastNote = pitch
imeMIDISendCC(midiChannel, 11, pitch, 0)
} else {
if (GLastNote != null) {
imeMIDISendCC(midiChannel, 11, GLastNote, 10)
GLastNote = null
}
}
}
function makeRandomText() {
// Make some random TTM text.
// We show 3 different techniques!
// Choose one of these to use at random.
var technique = wjsRandomGetFromTo(0, 2)
var ttmText = ""
switch (technique) {
case 0:
// Make a string with 3 random words
ttmText = iteRandomWordsGet(3)
break
case 1:
// Make a string that is a random shuffle of words
ttmText = "Shuffle these four words"
ttmText = iteShuffleWords(ttmText)
break
default:
// Make a string that is a random shuffle of characters
ttmText = "Shuffle these characters"
ttmText = iteShuffleCharacters(ttmText)
break
}
wjsLog("random ttmText=", ttmText)
return ttmText
}
function onImeStart() {
// Generate some random TTM text!
var ttmText = makeRandomText()
// Now that we have our string, set it!
imeParameterSet("Text Pattern Text", ttmText)
}
function onImeStart() {
// Set the TTM property "Text Pattern Repeats" to 2
imeParameterSet("Text Pattern Repeats", 2)
}
// Complex scripting example:
// - At piece start, apply random TTM Text.
// - After 4 bars, or at piece stop - restore the original TTM Text.
// The original TTM text is stored in this "global" variable
var GOriginalTTMText = ""
// The value we last set in onImeStart
var GLastSetTTMText = ""
function setRandomTTMText() {
// Take a copy of the original TTM text
GOriginalTTMText = imeParameterGet("Text Pattern Text")
wjsLog("GOriginalTTMText=" + GOriginalTTMText)
// Make a string with 3 random words
var ttmText = iteRandomWordsGet(3)
wjsLog("ttmText=" + ttmText)
GLastSetTTMText = ttmText
// Now that we have our string, set it!
imeParameterSet("Text Pattern Text", ttmText)
}
function restoreOriginalTTMText() {
var ttmNow = imeParameterGet("Text Pattern Text")
wjsLog("restoreOriginalTTMText, ttmNow=" + ttmNow)
if (ttmNow != GLastSetTTMText) {
wjsLog("The user value has changed since last random set - keep the current value")
} else {
wjsLog("Restoring TTM Text to=" + GOriginalTTMText)
imeParameterSet("Text Pattern Text", GOriginalTTMText)
}
}
//
// Trigger script functions
//
function onImeStart() {
wjsLog("onImeStart")
setRandomTTMText()
}
function onImeBar(bar) {
// On the 4th bar, restore the TTM text... UNLESS the user
// has already changed the value through the UI.
wjsLog("onImeBar, bar=" + bar)
if (bar == 4) {
wjsLog("onImeBar, bar 4!")
restoreOriginalTTMText()
}
}
function onImeStop() {
wjsLog("onImeStop")
// At the end, restore the TTM text... UNLESS the user
// has already changed the value through the UI.
restoreOriginalTTMText()
}
function onImeStart() {
// Query what Synth and Effect presets are available, and list them in the Script Console
var trackIndex = 0
var columnIndex = 0
var channel = 1
var fxNetworkIdSynth = iseGetFxNetworkIdForCellSynthTrackColumnChannel(trackIndex, columnIndex, channel)
var fxNetworkIdTrack = iseGetFxNetworkIdForCellEffectTrackColumnChannel(trackIndex, columnIndex, channel)
var synthFxPresets = iseFxNetworkAllPresetNamesGet(fxNetworkIdSynth)
wjsLog("All synthFxPresets.length=" + synthFxPresets.length)
for (var synthFxIndex = 0; synthFxIndex < synthFxPresets.length; synthFxIndex++) {
wjsLog(synthFxPresets[synthFxIndex])
}
var trackFxPresets = iseFxNetworkAllPresetNamesGet(fxNetworkIdTrack)
wjsLog("All trackFxPresets.length=" + trackFxPresets.length)
for (var trackFxIndex = 0; trackFxIndex < trackFxPresets.length; trackFxIndex++) {
wjsLog(trackFxPresets[trackFxIndex])
}
}
function onImeStart() {
// Generate a set of FX Network IDs, that are used for querying and setting different FX presets.
var fxNetworkIdMix = iseGetFxNetworkIdForMix()
var fxNetworkIdMixTrack0 = iseGetFxNetworkIdForMixTrack(0)
var fxNetworkIdCellGlobalTrack0Column0 = iseGetFxNetworkIdForCellGlobal(0,0)
var fxNetworkIdCellSynthTrack0Column0Channel1 = iseGetFxNetworkIdForCellSynthTrackColumnChannel(0,0,1)
var fxNetworkIdCellEffectTrack0Column0Channel1 = iseGetFxNetworkIdForCellEffectTrackColumnChannel(0,0,1)
// Query what Synth and Effect presets are available, and list them in the Script Console
var trackFxPresets = iseFxNetworkRandomPresetNamesGet(fxNetworkIdMixTrack0)
wjsLog("trackFxPresets.length=" + trackFxPresets.length)
for (var trackFxIndex = 0; trackFxIndex < trackFxPresets.length; trackFxIndex++) {
wjsLog("trackFxPreset=" + trackFxPresets[trackFxIndex])
}
var synthFxPresets = iseFxNetworkRandomPresetNamesGet(fxNetworkIdCellSynthTrack0Column0Channel1)
wjsLog("synthFxPresets.length=" + synthFxPresets.length)
for (var synthFxIndex = 0; synthFxIndex < synthFxPresets.length; synthFxIndex++) {
wjsLog("synthFxPreset=" + synthFxPresets[synthFxIndex])
}
if (synthFxPresets.length > 0) {
// Set a random synth patch (from those available) for track 0, column 0, channel 1
// Now... set patch random for cell 1!
var synthPresetForTrack0Column0Channel1 = synthFxPresets[wjsRandomGetFromTo(0,synthFxPresets.length-1)]
wjsLog("Use synthPresetForTrack0Column0Channel1=" + synthPresetForTrack0Column0Channel1)
iseFxNetworkPresetSet(fxNetworkIdCellSynthTrack0Column0Channel1, synthPresetForTrack0Column0Channel1)
}
if (trackFxPresets.length > 0) {
// Set a random FX patch (from those available) for the global Mix FX
var fxForMix = trackFxPresets[wjsRandomGetFromTo(0,trackFxPresets.length-1)]
wjsLog("Use fxForMix=" + fxForMix)
iseFxNetworkPresetSet(fxNetworkIdMix, fxForMix)
}
}
function onImeStart() {
// Generate the FX Network ID ... for the Global Mix FX
var fxNetworkIdMix = iseGetFxNetworkIdForMix()
// Query what Effect presets are available... for the Global Mix FX
var trackFxPresets = iseFxNetworkRandomPresetNamesGet(fxNetworkIdMix)
// Set a random FX patch (from those available) for the global Mix FX
// Check - has the user got any suitable FX enabled?
if (trackFxPresets.length > 1) {
// Yes, we have at least one suitable FX preset available
// Choose one at random...
var randomIndex = wjsRandomGetFromTo(0,trackFxPresets.length-1)
var fxForMix = trackFxPresets[randomIndex]
wjsLog("Use fxForMix=" + fxForMix)
// Apply the randomly selected preset
iseFxNetworkPresetSet(fxNetworkIdMix, fxForMix)
}
}
function onImeStart() {
// Voice trigger script - apply a random Synth patch at start
// Generate the FX Network ID ... for the Voice's cell and Voice's MIDI channel
var trackIndex = imeCellTrackIndexGet()
var columnIndex = imeCellColumnIndexGet()
var channel = imeVoiceMIDIChannelGet()
wjsLog("Voice trackIndex=" + trackIndex + ", columnIndex=" + columnIndex + ", channel=" + channel)
var fxNetworkIdSynth = iseGetFxNetworkIdForCellSynthTrackColumnChannel(trackIndex, columnIndex, channel)
var fxNetworkIdTrack = iseGetFxNetworkIdForCellEffectTrackColumnChannel(trackIndex, columnIndex, channel)
// Query what Synth and Effect presets are available, and list them in the Script Console
var synthFxPresets = iseFxNetworkRandomPresetNamesGet(fxNetworkIdSynth)
wjsLog("synthFxPresets.length=" + synthFxPresets.length)
for (var synthFxIndex = 0; synthFxIndex < synthFxPresets.length; synthFxIndex++) {
wjsLog("synthFxPreset=" + synthFxPresets[synthFxIndex])
}
var trackFxPresets = iseFxNetworkRandomPresetNamesGet(fxNetworkIdTrack)
wjsLog("trackFxPresets.length=" + trackFxPresets.length)
for (var trackFxIndex = 0; trackFxIndex < trackFxPresets.length; trackFxIndex++) {
wjsLog("trackFxPreset=" + trackFxPresets[trackFxIndex])
}
if (synthFxPresets.length > 0) {
// Set a random synth patch (from those available) for track 0, column 0, channel 1
// Now... set patch random for cell 1!
var synthPreset = synthFxPresets[wjsRandomGetFromTo(0,synthFxPresets.length-1)]
wjsLog("Use synthPreset=" + synthPreset)
iseFxNetworkPresetSet(fxNetworkIdSynth, synthPreset)
}
if (trackFxPresets.length > 0) {
// Set a random FX patch (from those available) for the global Mix FX
var trackPreset = trackFxPresets[wjsRandomGetFromTo(0,trackFxPresets.length-1)]
wjsLog("Use fxForMix=" + trackPreset)
iseFxNetworkPresetSet(fxNetworkIdTrack, trackPreset)
}
}
A hyperinstrument can be defined as being an instrument that can have extraordinary, semi-automated response to relatively simple real-time inputs.
Wotja is a hyperinstrument in many ways. For example from simple interaction in real-time through mouse and keyboard, you can have it generate extraordinary, ever-changing music that responds to your inputs. Wotja also directly responds to any real-time MIDI note data fed into it, for example from a MIDI keyboard or other MIDI controller; where you feed MIDI data into Wotja, you will find that Wotja can automatically harmonise its voices with all incoming MIDI note data. You can also configure Wotja to respond in many advanced ways to both MIDI note events and MIDI control events (otherwise known as "MIDI CCs").
Wotja can function as a hyperinstrument for 2 main reasons: The IME can real-time harmonise with incoming MIDI note events and control events (otherwise known as "MIDI CCs"), and Wotja's generative engine is an instrument that creates more than the sum of your direct inputs with keyboard, mouse, and MIDI. In other words, Wotja's generative engine, MIDI control, scripting and direct MIDI input harmonisation all work together to make itself greater than the sum of its parts; a customisable generative hyperinstrument!
See the Hyperinstrument - Quick Start if you want to get started quickly.
You can respond to any incoming MIDI CC however you want; for example, to change the current scale or adjust a harmony rule in real-time in response to incoming MIDI CC events.
You can also respond to any incoming MIDI Note on/off event however you want; for example, you could use some notes (such as accidentals in a scale) to change parameter values. In other words, you can use certain specific notes to trigger various complex responses by Wotja, for example; or to enable/disable the chording parameters only for certain notes (immediately that a note is triggered!); or to change scale; or pretty much whatever you can imagine.
Here is an example of a Voice MIDI In Note trigger script that you could use in your own piece.
function onMIDIInNote(channel, noteon, pitch, velocity) {
if (channel == imeVoiceMIDIChannelGet()) {
wjsLog("onMIDIInNote for our channel!")
}
}
To have a Voice "listen" to incoming MIDI data, you need to follow the instructions below.
Set the voice you want to listen to MIDI input, such that:
function onMIDIInNote(channel, noteon, pitch, velocity) {
if (channel == imeVoiceMIDIChannelGet()) {
wjsLog ("onMIDIInNote for our channel!")
}
}
You might want to set your Listening voice to auto-chord with depth of 2 or greater.
If you want an different Voice to also make sounds in response to your incoming MIDI note event, set it to FOLLOW the Listening Voice.