You are here

Logic: Writing MIDI Scripts

Apple Logic Pro Tips & Techniques By Stephen Bennett
Published July 2021

Logic’s Scripter plug‑in opens the doors to powerful custom MIDI manipulation.

One of the features unique to Logic in the early days of MIDI sequencers was the flexibility of its object‑orientated MIDI programming environment. While many of the sexy developments over the years have focused on audio processing and virtual effect and instrument plug‑ins, the MIDI side has sat quietly under the hood making everything work together. With the introduction of the Scripter MIDI plug‑in, Apple once again opened up real‑time MIDI programming in Logic Pro X, allowing users to create bespoke MIDI processing tools.

Screen 1: The Scripter tutorials menu.Screen 1: The Scripter tutorials menu.Scripter uses the JavaScript programming language as its engine. In many ways, coding is easier to learn than human language — there are no irregular verbs, or words that are spelt the same but have widely different meanings. Additionally, the coding crowd are a friendly bunch and the reuse of snippets of code is common amongst programmers, so ‘newbies’ don’t have to reinvent the MIDI wheel to create new Scripter plug‑ins.

Handily, Apple have provided a range of Scripter tutorials that we can explore and utilise as a base for experimentation (see Screen 1). You can’t break anything here — just make sure you save copies of the tutorial files before you edit. Firstly, let’s load up Scripter on a MIDI track, from the MIDI FX pull‑down menu. You’ll see that the plug‑in has a standard preset menu and here, alongside the tutorials, there are many more MIDI plug‑ins that have been created using Scripter (something I didn’t realise before I started to create my own Scripts!).

Scripts In The Night

On loading a preset, two windows will open: the plug‑in itself and a script editor window. The latter is split into two parts; the top is where code is inserted, the lower a ‘Monitor’ section (the Console), where any output or errors generated appear. The default code that is created here is a pass‑through with MIDI monitor (Screen 2).

Screen 2: The Scripter default windows and code.Screen 2: The Scripter default windows and code.

It’s important to understand right away that MIDI data are called Events in Scripter. If you play some notes and wiggle some controllers, you’ll see the data passing through Scripter presented in the Console. You should also hear output from any virtual instrument you have inserted on the same track. This simple plug‑in consists of two lines of code and is part of a function — constrained by {wiggly brackets} — that can be called from larger JavaScript projects. A function is a kind of self‑contained utility that can perform some kind of action. The HandleMIDI() function is very important in Scripter as it’s the one that allows you to process MIDI data passing through it.

The event.trace(); line sends data to the Console, while the event.send(); line passes MIDI through the plug‑in — the closed brackets mean that all data is sent. If you delete the event.send(); line and click on Run Script you’ll now see (and hear!) that no data is passed through Scripter. All JavaScript functions have a similar structure. Note that spelling and the use of letter cases and other characters are vitally important for the code to run correctly — most errors are caused by not following this rule!

Note that spelling and the use of letter cases and other characters are vitally important for the code to run correctly — most errors are caused by not following this rule!

While it’s always fun to see MIDI data, it’s even better to process it! Apple have handily provided many Scripter examples that we can explore and reuse as jumping‑off points for our own plug‑ins. If you click on the Factory default pull‑down menu and scroll to the bottom of the list, you’ll see a Tutorial submenu. This contains examples of basic functionality and code we can repurpose. Let’s have a look at the Transpose and Delay Script (Screen 3). Select it and click on Open in Script Editor. Try playing some notes to hear the effect the MIDI processing has on your input.

Screen 3: The Transpose and Delay Script.Screen 3: The Transpose and Delay Script.

Colour Coding

You’ll notice that there is some information (‘remarks’) about the plug‑in in green behind the double // parallel lines. These lines say to Scripter “these are comments only!” and are a really useful feature, not only for reminding your future self what the heck you were trying to do with the plug‑in, but also to temporarily disable code when debugging. The other thing to notice is that many of the JavaScript commands are in relatively understandable English and that some bits are in different colours. The Scripter editor will assist you in typing commands and you can usually tell that you’ve done something wrong when your text doesn’t change to the expected colours. Try typing in event.send into a Scripter window and see how the text changes colour.

This is how the Transpose and Delay script works. Note that the code is ‘enclosed’ in the HandleMIDI(event) function:

  • event.send(); makes sure the event is sent through Scripter.
  • if (event instance of Note) checks to see if the MIDI event is actually a note and not a controller, SysEx or other data. It’s common in programming to check If a condition applies and then do something or, if it does not, do something else!
  • event.pitch += 12; transposes the note up 12 semitones (one octave). See Screen 4.
  • event.sendAfterMilliseconds (100); sends this transposed data to the instrument after a delay of 100ms.

Screen 4: The code inside the squiggly brackets is a subroutine.Screen 4: The code inside the squiggly brackets is a subroutine.

Try playing around with the delay time and transposition values and audition the results. Also, notice the curly brackets in the code. These define routines and subroutines. There must be an equal number of left‑ and right‑facing brackets for the code to work — the Console will tell you when there’s not!

Screen 5: Adding some code to an existing script.Screen 5: Adding some code to an existing script.To show how these work, open up two instances of Scripter and load the Transpose and Delay Script in one and the Trace Events Script in another. Copy the event.trace(); code to the former script and click on Run Script. Now when you input MIDI data you should see the input notes displayed along with hearing the delay and transpose processing. If you stick event.trace(); in the ‘if’ subroutine, you can get Scripter to only print the inputted MIDI notes (Screen 5). Entering controller data (modulation, sustain) should have no visible effect.

Scripter is a fully functional MIDI processing environment within Logic Pro that takes the program’s abilities in this area to new levels...

Getting Graphical

If you check out some of the Scripter plug‑ins, you’ll see many of these have faders and other simple objects, such as sliders and pull‑down menus. The slider object itself is created using the var (‘variable’) Plug‑inParameters line in Screen 6. You can see there are parameters attached to this, such as the name, “Slider” (in quotes as it’s a text string), whether it’s linear or logarithmic, minimum and maximum values, the default value, how many steps you’ll need and a name for the units displayed. This whole slider is, in effect, a variable and is created outside the function HandleMIDI(event) subroutine as we want to use it for the whole Script. The variable ActualSliderValue stores the value of the position of the slider itself, so that one lies inside the subroutine. Trace(ActualSliderValue); prints the slider value to the Console. If you change the slider and enter a MIDI note, you’ll see the value appear in the Console. And Trace(); is a really useful tool for checking what’s going on in your code.

Screen 6: A slider object and the code required to create it.Screen 6: A slider object and the code required to create it.

There are quite a few other simple GUI objects you can add to your Script, such as menus, radio buttons and tick boxes. Screen 7 shows how these can be created as a variable array — pay particular attention to brackets and commas that help define this array. An array is just like a set of cells in a spreadsheet, so here we are effectively storing these values for the GUI objects so we can access them anywhere in our script.

Screen 7: More GUI objects and the code required to create them.Screen 7: More GUI objects and the code required to create them.

If, Then, Else…

Now let’s combine code from different scripts to create a new MIDI processing tool. Open the default Scripter plug‑in, add the code from Screen 6 and save it as ‘My First Transposer’. Next, open the Transpose and Delay script in a new Scripter plug‑in and copy this code into the My First Transposer script window:

// if it’s a note

if (event instanceof Note) {

event.pitch += 12;

}

Next, change the last line to event.pitch +=ActualSliderValue; (replacing 12 with the variable that contains the slider value). Assuming your code looks like that in Screen 8, adjusting the slider will change the MIDI note played by your keyboard by a value defined by the position of the slider.

Screen 8: Creating bespoke code.Screen 8: Creating bespoke code.

{The Bottom line}

Scripter is a fully functional MIDI processing environment within Logic Pro that takes the program’s abilities in this area to new levels, albeit without any fancy graphical interface. Further help and information on Scripter is available in the Logic Pro Manual and routines are available at GitHub (https://kabirnagral.github.io/LPXscripts/). Places like Reddit and other forums on the net are also great sources of help and assistance in creating scripts for Logic Pro X.

This short workshop can’t turn you into a JavaScript expert overnight, but by analysing and manipulating the supplied tutorials and examples, it should be enough to start you on the journey. It’s probably also worth having a go at some online JavaScript tutorials, such as those at W3 schools (www.w3schools.com/js/) as this will help you understand some of the basic grammar that Scripter uses. I usually get involved in coding when I can’t find other ways to solve a MIDI‑based problem using available tools — if you find yourself in this situation, just open Scripter and experiment. You’ll soon find that a logical mind, a bit of patience and the help from a huge online community of JavaScript coders is all you’ll need to create your own bespoke MIDI processing tools.

Buy Related Tutorial Videos