By popular demand, two simple pieces of code have been added Field to support the writing and reading of MIDI files. MIDI’s complete and utter adequacy as a protocol combined with its first mover advantage (it was standardized in the early 80s) has meant that, despite its obvious problems, it is the interchange format for note-level descriptions of music that is read and written everywhere where note-level descriptions of music might be useful.
How to write some notes to a MIDI file? Here’s the code:
That’s really all you need to know. The same information in a different form:
saver.note(time, pitch, velocity, duration)
— adds a note to a SaveMidi
object. The note starts at time
(in seconds), is of pitch pitch
(from 0-127), velocity (from 0.0 to 1.0) and lasts duration
seconds long. Think of velocity as a keyboard-centric way of saying ‘loudness’. Pitch probably requires a little explanation. pitch=69
is, by convention, the pitch A
that traditionally sounds at 440Hz. pitch=68
is then the A♭ immediately below that, pitch=70
is the B
immediately above. That’s all the music theory I’m going to give here. There’s also a saver.note(time, pitch, velocity, duration, channel)
where channel can go from 0-15 (inclusive) if you know what channels are in MIDI files.
However, the reality is that it’s up to the program that interprets this MIDI file as to what the notes (and velocities) mean (just as it’s up to the synthesizer you connect your keyboard to as to what sounds come out when you press the keys). If we just drag this .mid file into GarageBand we’ll get those notes on a “Steinway Grand”:
Take a moment to convince yourself that that shape (with pitch running from low to high / bottom to top, and time running left to right) is what you’d expect from the code above.
Two things to note:
Code for sending notes out of Field into any app that’s listening for MIDI works in very similar ways. First make sure you have turned on “IAC” midi (this stands for Inter-Application communication) in Audio/Midi setup. This app can be found in /Applications/Utilities. Window->Show Midi Studio shows:
Double click on the IAC Driver and check “device is online” before starting Field.
Then:
… sends a note. output.note(pitch, velocity, duration_in_seconds, channel)
— with velocity 0-1, pitch 0-127 and channel 0-15. Note that GarageBand ignores ‘channel’ and only (seems?) to be willing to play midi if the first track is selected. Consider exploring Logic Pro…
Loading MIDI files is just as easy. Just because we can, let’s draw that GarageBand screen in Field:
Yields:
Being able to iterate over the whole MIDI file gives you access to everything. But it’s not always what you want, if you want to make an animation that responds to what’s happening in a moment of time. Three things help:
loaded.notesAtTime(4.5)
returns all (if any) notes that are sounding at time 4.5seconds.loaded.notesBetweenTimes(4.5, 4.6)
returns all (if any) notes that are sounding at any point between time 4.5 and 4.6 secondsloaded.read(4.5)
returns all (if any) notes that are sounding between the last time you called loaded.read( ... )
and 4.5 seconds. This useful for incrementally reading through a MIDI file (perhaps, say, based on _t()
) and making sure you don’t miss any notes. It only works, though, when reading forwards in time (you won’t get anything if you skip backwards).