Thursday, August 2, 2018

MIDI Part One: MIDI Out

It's easy to forget that the USB jack on the back of an Ornament and Crime can be used for things other than updating firmware. Teensy 3.2 has a capable, if poorly-documented, MIDI library. With the right software, O_C can be a modular system's link to the outside world.

I'm going to walk through sending MIDI messages in this post. In the next post, I'm going to introduce Captain MIDI, a full-scale modular MIDI interface in the classic Ornament and Crime style.

Enabling MIDI


MIDI support is enabled in Arduino IDE as one of the compile options. From the Tools menu, go down to "USB Type" and choose "MIDI" instead of the usual "No USB."

Note #1: MIDI support adds about 3% to the size of the compiled binary, so if you're working with a normal O_C codebase, MIDI support might take you over the limit.

Note #2: I haven't tested the default O_C apps with MIDI support enabled. I think they'll continue to work as normal, but I haven't tried it.

Note #3: Arduino IDE remembers your last settings. This is usually a good thing, but it means that you'll need to keep track of whether you want MIDI support enabled or not if you have multiple codebases.

Note #4: When I compile with MIDI, I don't have to push the Program button on the Teensy; programming starts automatically as soon as the build is done. I don't know why it works this way, but I suspect that it's normal USB behavior that is suppressed when compilation is done with "No USB."

The Teensy USB MIDI Library


See the Teensyduino USB MIDI documentation here:

https://www.pjrc.com/teensy/td_midi.html

The information on that page can be characterized as somewhat accurate. Hopefully, I can save you from some of the frustration that I experienced when I counted on it being right. Still, it's a decent starting point, and it's worth knowing.

If you go through the library code that's part of Teensyduino, there's more than one MIDI library, so I suspect that the documentation just wasn't updated. At very least, it's not specific to the Teensy version that we care about, 3.2.

But the documentation's gaps won't vex us too much for Midi out. It'll become more relevant when we look at MIDI in.

Basic MIDI Out


I'm starting with MIDI out because it's a bit easier than MIDI in. Don't worry, MIDI in is still pretty easy. But with MIDI out, you're just using the documented methods to send messages.

Every MIDI operation (out and in) uses the global object usbMIDI. For example, to send a Note On message, you do

usbMIDI.sendNoteOn(midi_note, velocity, channel);

midi_note is an integer from 0-127, velocity is an integer from 0-127, and channel is an integer from 1 to 16. Take note that MIDI channels in this library are 1-indexed.

The MIDI library puts each message in a buffer, and holds onto it until 16 messages have been buffered, or until 1ms (or so) has elapsed, whichever comes first. If you want to send buffered messages earlier than that, you can call

usbMIDI.send_now();

Note Off is similar to Note On, including velocity:

usbMIDI.sendNoteOff(midi_note, 0, channel);

MIDI control change looks like this:

usbMIDI.sendControlChange(controller_number, value, channel);

Note that value has a seven-bit range from 0-127, per the MIDI specification.

usbMIDI.sendAfterTouch(value, channel);

This is channel aftertouch, and the value here is also from 0-127.

And pitch bend:

usbMIDI.sendPitchBend(bend, channel);

The bend range here is from 0-16383. Values from 0 to 8191 are negative bend, 8192 is 0 bend, and values from 8193 to 16383 are positive. For logging purposes, I'd just display (bend - 8192).

Other MIDI Out


I've been working with system exclusive messages, and I'll probably deal with that separately if anyone is interested. I haven't really figured out clock yet. The documentation says this:

usbMIDI.sendRealTime(usbMIDI.Clock);

but there is no usbMIDI.Clock, at least for Teensy 3.2, and there doesn't seem to be specific support for clock in the library code. So this is sort of on my "pending" list. The library lets us construct MIDI messages a byte at a time, and that might be necessary if we want clock.

4 comments:

  1. The O_C can act only as a MIDI device (not host) right? Been looking for a way to get/make a MIDI keyboard controlled quantizer, like the Instruo Performance Quantizer.

    ReplyDelete
    Replies
    1. That's correct, it can't be a host, at least within the confines of the Teensydunino USB MIDI library.

      Delete
  2. This comment has been removed by the author.

    ReplyDelete
  3. could be real cool to use the midi in later with some kind of controller interface like lemur for ipad, and do a separate lemur control panel for each applet for finer control, via the touch interface of the ipad...sequencers, ADSR...with additional slow moving modulation of each value from the lemur template!


    ReplyDelete

Pitch Calculation and Output

"If pitches were horses, we'd all be eatin' steak." --Jayne Cobb And where have I been for almost two months? I was busy...