I’ve always been fascinated by live-coded music. Frameworks like Chuck, Supercollider, Overtone, Extempore, and Sonic PI, along with popular performers and musicians like Sam Aaron and Andrew Sorensen have never ceased to amaze and inspire me.
That said, whenever I’ve tried to use one of those tools or frameworks to create my own music, I’ve always quickly given up. Maybe it’s because I’m just lazy and learning new things is hard, but I’ve always told myself that it’s because the tools I was using just didn’t fit with how I felt programming music should be. Syntactically, ergonomically, and conceptually, the tools just didn’t jive.
And then I stumbled across J.
J and the entire family of APL languages have a beautiful terseness and closeness to the data being operated on. They’re also fundamentally designed to operate on arrays, a data structure ripe for musical interpretation. I’ve convinced myself that if I can learn J, I’ll be able to build the live coding environment of my dreams!
That’s a big goal, but I’m taking baby steps to get there. Today, I’ll show you how I managed to make noise with J.
Making Noise Without J
My plan for making noise with J doesn’t actually involve my J software producing any noise directly. Instead, it’ll act as a controller that instructs other software on my machine to make noise on its behalf.
The software making the noise will be SimpleSynth, which is a small, easy to use MIDI synthesizer. If you’re following along, feel free to use any other MIDI synth you’d like, or a full audio workstation like Ableton or even GarageBand.
When we fire up SimpleSynth, it’ll ask which MIDI source it should use. MIDI is a protocol that lets us pass around musical information, like when and how loud certain notes should be played, between different devices. SimpleSynth is asking which stream of notes it should listen to and play.
Setting up our J virtual device in MIDI Studio.
I used MacOS’ built-in MIDI Studio to create a virtual MIDI channel called “J”, with a MIDI port called “Bus 1.” After making sure the virtual device was online, I selected it in SimpleSynth.
Selecting our J virtual device in SimpleSynth.
The last piece of the puzzle is finding some way of programmatically sending MIDI messages through my “J Bus 1” to be played by SimpleSynth. Geert Bevin’s SendMIDI command line tool did just the trick.
Once installed, we can use SendMIDI to send MIDI notes to SimpleSynth from our command line:
sendmidi dev "J Bus 1" on 60 100
60, with a velocity of
100 effectively plays a middle C at full volume.
Now we’re making music!
Talking to SendMIDI with J
The next challenge lies in getting J to execute
After much searching and head scratching, I learned that J exposes a wide range of miscellaneous functionality under the “foreigns” (
!:) verb. Calling
2!:1 y lets you spawn a new process, running whatever command you pass in through
Let’s try invoking our spawn verb with our
2!:1 'sendmidi dev "J Bus 1" on 60 100' |interface error | 2!:1'sendmidi dev "J Bus 1" on 60 100'
After even more searching and head scratching, I realized that I needed to use the fully-qualified
sendmidi path when making the call:
2!:1 '/usr/local/bin/sendmidi dev "J Bus 1" on 60 100'
I hear sound! Success!
Making Music with J
While this is great, it’s not much better just running our
sendmidi command directly from the command line. What would make things even better is if we could build ourselves a
play verb that plays any notes passed to it.
For example, if I were to run:
play 60 64 67
I’d expect J to construct and execute our
sendmidi command, which should play a C major chord:
sendmidi dev "J Bus 1" on 60 100 on 64 100 on 67 100
After a few brain-expanding weekends of playing around in J, I came up with this version of the
on =: ('on ',5|.' 100 ',":)"0 play =: [:2!:1'/usr/local/bin/sendmidi dev "J Bus 1" ',[:,/on
on verb turns an integer note into an “on string” of the format,
'on <note> 100 ', and the
play verb spawns the result of appending
'/usr/local/bin/sendmidi ...' to append mapped over
on applied to
Put simply, it constructs our
sendmidi command and executes it.
We can play a C major chord:
play 60 64 67
Or any other chord we want:
play 60 63 54 70 73
Please keep in mind that I’m very new to J, and even newer to tacit programming. If you see anything that can be improved, clarified, or corrected, please let me know.
I still feel very clunky and slow when it comes to using J. Building this two line program took hours of my time. That said, I feel like there is potential here. As I grow more used to the tacit paradigm and play with other ways of interacting to DAWs and other audio producers, I feel like J might turn into my ideal music creation environment.
Time will tell.