In the past week I’ve found myself in multiple conversations about working with MIDI in TouchDesigner. Specifically, how you might pass a MIDI signal from one application to another on the same computer. So far, all of the conversations I’ve been involved in have been related to working with Windows – which means that this particular post is focused on that operating system, though the same idea should transfer to macOS if that’s your current platform.
So what’s the problem exactly?
All of my conversations about this topic have been centered around sending messages from TouchDesigner to WATCHOUT. For those unfamiliar, WATCHOUT is a media server application that’s used in Theatrical and live events contexts for controlling or sequencing media playback. It’s in the same family of tools as Disguise, GreenHippo, and Pandora’s Box. You may well be asking – “why not just use OSC?” That’s a great question, some versions of WATCHOUT don’t support OSC, though they do support MIDI. While this is the specific challenge, the more general idea that we can push against here is:
How can I locally (on the same machine) test a MIDI signal flow without adding extra hardware?
To get there we need to add in a virtual device to allow us to loopback. At it’s simplest, a loopback is just a way of capturing a signal that you’d other wise be sending somewhere else. Imagine using a cable from the headphone port on your laptop, and connecting it to the microphone in on your laptop (don’t actually do that, just imagine it). Why? Well, using actual interfaces often have different requirements, or set-up than just faking it – you’ll also likely find that operating systems don’t have an implicit knowledge of a particular signal or transfer format. Just because your computer is making noises doesn’t automatically mean that it can capture that noise locally.
How do we make this work then?
Enter the Virtual Device. A Virtual Device provides drivers that act as though it’s sending your signal to a dedicated piece of hardware, but instead allows you to rout it back to your machine. There are lots of examples of this in the audio world, and it just so happens that there’s a Virtual MIDI device we can install to pass around MIDI signals as well.
Doing a bit of googling I found LoobBe1. It has a free evaluation license, which is what we’ll use below. If you decide that this needs to be part of your commercial workflow, I’d encourage you purchase a license. It’s less than $15 US, and supporting folks that make useful tools is something we should all do more. As a disclaimer, I don’t have any affiliation or connection to LoopBe1 – I just found them after doing some internet searching.
We’re going to set-up a simple loopback test for a MIDI signal from TouchDesigner, and see if we can read that signal back. I don’t have a copy of WATCHOUT to work with, but if we can trouble shoot within TouchDesigner, we should at least know that it’s working.
Getting a MIDI Loopback Working
Windows 10 v1809
TouchDesigner 099 2019.15230
To get started you’ll need to download and install LoobBe1. I like to limit what starts up automatically on my computer, so I’d recommend also turning off the automatic start-up of this application once you have it installed.
From there we can start up TouchDesigner and begin our configuration process. We’re going to start by opening the MIDI Mapper dialogue. You can open that with
alt + d or you can find it from the Dialogues drop down:
You should now see the MIDI Mapper:
We’re going to test our output right in TouchDesigner. To do that let’s click on the
Create New Mapping button in the middle left of the dialogue window. That will add a row to our Device Mapping where we can specify that both our In and Out Device will be
LoopBe Internal MIDI.
Before we can move forward here it’s important to recognize that the naming of MIDI channels matters. MIDI (Music Instrument Digital Interface) has a detailed specification that ensures continuity across devices and manufactures, so it shouldn’t be a surprise that there’s lots of detail here. You can read the whole spec by here, or get a summary from Wikipedia. What we really care about today is that we need to format our TouchDesigner channel names in a way that’s compatible with Derivative’s implementation. To figure all of that out, we need to head over to the wiki for a quick read. Let’s take a look at the MIDI Out CHOP page. Here we see that:
Naming the CHOP channels: Channels are mapped to events by their name. Events like notes, controllers and velocities must be followed by the note/controller number (n65, c7). If the number is left off a note event, the note number is the value of the channel. Other events, which are sent to the entire channel, do not need a trailing number (pc, pw). The channel prefix can be used to identify the MIDI channel the event should be sent on (i.e. “ch1n45” assigns that TouchDesigner channel to note 45 messages on MIDI channel 1). Channels can always be renamed with a Rename CHOP before entering the MIDI Out CHOP.Derivative’s MIDI Out CHOP Wiki Page
The MIDI Out CHOP sends MIDI velocity as well. The values of the channels entering the MIDI Out CHOPs are sent as the velocity of the note. If Normalize is “None”, the channel needs to be 0 to 127. If Normalize is “0 to 1”, channel values between 0 and 1 are scaled to be MIDI 0 to 127.
The “Cook Every Frame” option cooks the CHOP every frame, even if the CHOP isn’t being displayed. All Volume Off and All Volume On flags are new and emit events for Controller 7 of all 16 channels. MIDI output go in a separate thread to allow output that slows TouchDesigner less. It now works in Time Slice mode for note events and controller events. (Not for Program Change or Sysex messages yet) Note channels only trigger anew Note On when the input channel goes from 0 or less to a value greater than zero. Similar for Note Off events.The channel name determines how it is interpreted.
What does that even mean?! Well, let’s set up a few pieces in a network to see if we can make sense of this.
I’m going to add a
Noise CHOP to my network, and turn on the time-slice parameter so we have some constantly changing values. I’m going to change the Channel name parameter to be
ch1c1. This would be Channel 1, Control 1.
By default our
Noise CHOP will have values between -1 and 1. Based on what’s in the wiki, we’ll either need to normalize our values (change them to be in a range of 0-1) or we’ll need to change our values to be in a range of 0-127. We can do either of these with a
Math CHOP so let’s add one of those in line and change our range parameters:
Now we can finish this off by adding a
MIDI Out CHOP to our network:
So how do we make sure this is working?
Well, let’s first check with Touch. Since we added our LoopBe Internal MIDI as our input device, we should now be able to drop in a
MIDI In CHOP to see our midi values:
Great – so we can see our values… only they’re expressed as whole numbers rather than as a floating point value. Why? MIDI works with 127 steps, so our MIDI Out CHOP is converting our 0-1 set of values into a range of 0-127. What this means is that you, dear developer-artist, have to make a choice. This approach works perfectly fine, but it may mean that at some point you’ll be doing some mental gymnastics in understanding how values in Touch correspond to values in your other application. If that’s too much to think about all the time, then you may want to change the math CHOP to be in a range of 0-127, with the values rounded either up or down (depending on your preference). This kind of change would let you see exactly what value you’re expected to be transmitted from Touch. If you’re working on a high profile AV installation, this kind of specificity might be worth having – if only so you can say with complete confidence that you’re transmitting a value of x on channelxyz.
Okay, so it works in Touch… but can we be sure? Of course. I’m going to use Isadora by Troikatronix to help us validate that we’re sending this correctly. I’m not going to go into too many of the details for how we set-this up in Izzy, just enough so we can validate what we’re seeing here.
To start I’m going to open up Isadora, go to the Communications drop down, and select MIDI Setup:
Like Touch, I’m going to set the Input Port to be LoopBe Internal MIDI:
To see if we’re actually transmitting values, let’s open up the Izzy Status monitor:
Sure enough, we should see a blinking Green light on Channel 1 and the value associated with it:
TADA! You’re passing data around locally from one application to another using MIDI.
Okay, so what exactly did we do? Well, we added a virtual MIDI interface that let us send MIDI encoded data between applications on a single computer. We then verified that this works by first looking at the data transmission in Touch, then further validated that this works working by looking outside of Touch with another application.
Why on earth do any of this? Well, that’s really a question for you. If MIDI is a core part of your work flow, and passing data between applications on the same computer has an important role for you, then the answers might seem obvious. For those still scratching their heads, imagine that you have raw sensor data that’s not MIDI friendly, but you’d like to get it into an application that does speak MIDI. This kind of workflow is great for that. Working with a Kinect but want to turn that data into MIDI, easy. What about a Leap – sure. Can I do my mouse – you betcha.
It might not be what you need today, but maybe it’ll inspire you to think about some mischief you could get yourself into.