Transpose Script
-
In this tutorial we are going to write a script that transposes the incoming notes by a amount that can be specified with a slider.
While the script itself is not very useful - there is even an existing module with the same functionality, this task is still going to be a nice example for customized MIDI processing.
Step 1: Create the required modules
So the first thing you need is a Sound Generator with a ScriptProcessor. This is achieved with the following steps:
- Click on the
+
Symbol of the Master Container and add a Sound Generator. You can use any type (the scripting will be the same), but I recommend a Sine Wave Generator for simplicity. - Open the MIDI Processor Chain of the Sine Generator by clicking on the
MIDI
button below the Sine Generator header. - Add a Script Processor by clicking on the
+
symbol of the MIDI chain and select Script Processor
Step 2: Create the scripting interface
There is a WYSIWYG editor for advanced interface design, but for this simple task - one knob that controls the transpose amount, we can use the manual method of creating interfaces.
The script processor contains has six callback types and their code can be shown by clicking on the button bar below the Script Processor header.
The interface code is written in the
onInit()
-callback. Open up the onInit editor and paste this code in it:const var transposeKnob = Content.addKnob("Transpose", 0, 0); transposeKnob.setRange(-24, 24, 1);
This creates a knob at the position
(0,0)
and sets the name to "Transpose". The second line sets the range to -24 to 24 and the step size to 1 (because we only need integer numbers for the transposer).If you press <kbd>Compile</kbd>, you can see the new control on the area above the code editor - this is the content area that can be populated with controls and widgets:
Step 3: Implement the functionality
Until now the knob does not do anything so the next thing to do is to implement the actual transposing.
We need to transpose both note on and note off events by the amount specified by the knob. So we need this code in both callbacks:
Message.setNoteNumber(Message.getNoteNumber() + transposeKnob.getValue());
This line of code uses two API calls,
Message.getNoteNumber()
andMessage.setNoteNumber()
to change the incoming midi message.If you play some notes and move the slider you see that the script is working.
Step 4: Debugging
Even with this simple script we are running into one problem: If we press a note and move the slider while the note is playing, the corresponding note-off event will get another note number than the note on and this results in one of the most annoying things when scripting: stuck notes.
If you have stuck notes, simply turn off the sound generator with the power button and turn it back on. It will send a "All notes off" event and the stuck notes disappear.
There are many ways to fix this problem with different levels of complexity, but let's choose the most simple one: if you move the slider, all notes will be killed.
So we need to add some code to the callback that gets executed when the slider is moved. Open the
onControl
code editor and insert the following lines:if(number == transposeKnob) { Engine.allNotesOff(); }
This will send a global noteOff event to all sound generators - because all API calls from the
Engine
object work on a global level.Now if we move the knob, the playing voices will be killed and no stuck notes anymore.
- Click on the