| BrainStem and MIDI Example Last Modified: 2006-11-07 | | |
| Acroname Robotics | PDF webpage version | ||
| Introduction This example discusses the MIDI (Musical Instrument Digital Interface) protocol and shows how a BrainStem GP 1.0 module can communicate with a MIDI device. Some example programs show how to send MIDI commands to a synthesizer in order to generate sounds. Such a feature could be used in interactive artwork or media.
Theory The MIDI protocol provides a standard command set for a large variety of devices. Typically it is used with electronic musical instruments in order to control what notes they should play. A MIDI command is typically two or three bytes sent serially at a baud rate of 31250. A BrainStem module that supports the MIDI baud rate can play an enormous variety of sounds by sending commands through its serial port to a MIDI synthesizer. Tom Igoe at NYU provides an excellent introduction to MIDI commands and interfacing issues on his MIDI Communication web page. All the MIDI commands mentioned in this example are documented there. His page also has diagrams for the simple circuitry needed to connect a microcontroller to a MIDI device. For these examples, we constructed a circuit with a 74HC04 hex inverter as shown in the first "MIDI OUT from Microcontroller" diagram. Create a BrainStem Network for Additional Serial Ports Since a Stem has one serial port, it can be awkward to switch between programming the Stem and controlling another serial device. The non-standard MIDI baud rate also makes things cumbersome. It may require lots of switching back and forth between the MIDI device and Host computer and repeatedly changing the baud rate of the Stem module. Using a network of two Stems is an easy solution to these problems. The two Stems can be connected via the I2C bus. One can be configured for the MIDI baud rate. The other can be configured for a standard baud rate, such as 9600, and connected to a host computer. This makes it easy to download code to the Stem configured for MIDI communication. In the network, one Stem will be the "MIDI Stem" and the other will be the "Host Stem". The MIDI Stem must be connected to the host computer and configured separately before being connected in the network. The following commands entered in the Console application will configure the MIDI Stem: 2 18 4 7
2 18 0 6
6 19
The first cmdVAL_SET command tells the Stem to use the MIDI baud rate. The second changes the Stem's address to 6. This change is immediate so any additional commands must start with the new address. The final cmdVAL_SAV command writes the new settings to the EEPROM. At the next power-up or reset, the Stem will initialize with the MIDI baud rate. After sending these commands, the MIDI Stem must be connected with an I2C cable to the Host Stem. The Host Stem won't need any configuration commands. Its default settings will permit communication with both the host computer and MIDI Stem. With the network configured, all that remains is to connect the Host Stem's serial port to a computer and connect the MIDI Stem's serial port to a MIDI device. Then it's time to try some programs. A Korg NX5R synthesizer works great with the example programs listed below. Source Code - MIDI TEA Library A small TEA library provides routines for sending commands of 2 or 3 bytes from a TEA program. It also has some defined values for common MIDI commands. This TEA library is used by both example programs. /* filename: aMIDI.tea */
#ifndef _aMIDI_T_
#define _aMIDI_T_
#include <aIOPorts.tea>
#define NOTE_OFF (char)0x80
#define NOTE_ON (char)0x90
#define KEY_P (char)0xA0
#define CTRL_CHG (char)0xB0
#define PROG_CHG (char)0xC0
#define CHAN_P (char)0xD0
#define BEND (char)0xE0
void send3(char a, char b, char c)
{
asm
{
pushsb 5
pushsb 5
pushsb 5
pushlb 3
popbm aPortSerialNTX
}
}
void send2(char a, char b)
{
asm
{
pushsb 4
pushsb 4
pushlb 2
popbm aPortSerialNTX
}
}
#endif
Source Code - TEA Program to Repeat a Note The first example program plays a note over and over again. To spice things up a little, it does a pitch bend of each note. The program takes three arguments: a 1-based channel index, a 1-based instrument index, and a rate parameter. The rate is in units of 100ms and determines how long to pause after a note is done. /* filename: midi1.tea */
#include <aCore.tea>
#include "aMIDI.tea"
void main(char chan, char instr, char rate)
{
char k;
char channel;
// convert 1-based channel index to 0-based index
// (to match channel display on the Korg NX5R)
channel = chan - 1;
// turn notes off for channel
// then select instrument
send2(CTRL_CHG + channel, 0x7B);
send2(PROG_CHG + channel, instr - 1);
while (1)
{
// play note
send3(NOTE_ON + channel, 64, 64);
// bend and unbend note
for (k = 0; k != 100; k++)
{
send3(BEND + channel, 0, k);
aCore_Sleep(10);
}
for (k = 100; k != 0; k--)
{
send3(BEND + channel, 0, k);
aCore_Sleep(10);
}
// turn note off
send3(NOTE_ON + channel, 64, 0);
// delay based on input
aCore_Sleep(rate * 1000);
}
}
To run the first example program, enter the following Console commands: steep "midi1"
load "midi1" 6 0
launch 6 0 1 1 5
The steep command compiles the file. The load command loads it into program slot 0 of module 6. The launch command runs program 0 on module 6 with input parameters 1, 1, and 5. This makes channel 1 play a bending note with instrument sound 1 (a piano) and a 0.5 second pause between notes. Now for some fun... The synthesizer can play many notes at once and the Stem can run up to 4 programs at once. Enter the following command to start another TEA program that continuously plays notes: launch 6 0 2 11 7
This makes channel 2 play a bending note with instrument sound 11 (a music box) and a 0.7 second pause between notes. The Stem can handle two more programs: launch 6 0 3 17 11
launch 6 0 4 48 13
That produces repeating organ (17) notes and timpani (48) notes on channels 3 and 4. With all these notes repeating at odd intervals, it can start driving a person nuts. A cmdRESET command sent to Stem 6 will stop everything: 6 24
Source Code - TEA Program Sound Bending with a Sensor The next example is a "light drum". It uses sensor feedback to determine when to play a note, what pitch the note will have, and how loud it will be played. A GP2D12 range finder connected to analog input 1 controls pitch and a GP2D120 range finder connected to analog input 0 controls loudness and when to play a note. A hand moving up and down over the GP2D12 will adjust the pitch of the light drum. A hand moving close enough to the GP2D120 will play the note. Taking the difference between consecutive measurements from the GP2D120 provides some indication of how fast the hand is moving. A slow or soft swat at the GP2D120 will play a soft note. A fast or hard swat at the GP2D120 will play a loud note. A GP2D120 has an update rate of about 40ms so this is how fast samples are taken to determine hand velocity. /* filename: midi2.tea */
#include <aCore.tea>
#include <aA2D.tea>
#include "aMIDI.tea"
void main(char chan, char instr)
{
int r;
int r0;
int v;
int p = 64;
char channel;
// convert 1-based channel index to 0-based index
// (to match channel display on the Korg NX5R)
channel = chan - 1;
// turn notes off for channel
// then select instrument
send2(CTRL_CHG + channel, 0x7B);
send2(PROG_CHG + channel, instr - 1);
r0 = aA2D_ReadInt(0);
while (1)
{
// velocity is difference between this reading and last
r = aA2D_ReadInt(0);
v = r - r0;
// when close enough, this is a "strike"
if (r > 240) {
// velocity will be note pressure
v = v / 2;
if (v > 127) v = 127;
// turn off previous note
// then play new note with new pitch
send3(NOTE_ON + channel, (char)p, 0);
p = 32 + aA2D_ReadInt(1) / 16;
send3(NOTE_ON + channel, (char)p, (char)v);
// then wait for "release"
while (1) {
r = aA2D_ReadInt(0);
if (r < 230) break;
}
} else {
// if no strike, then update previous reading
// a Sharp sensor can't update any quicker than this
aCore_Sleep(400);
r0 = r;
}
}
}
To run the light drum program, enter the following Console commands: steep "midi2"
load "midi2" 6 1
launch 6 1 1 119
That makes channel 1 play a synth drum (119) note when an object moves in front of the GP2D120. Once an object has moved close enough to trigger a note, the program waits until the object moves away again. The threshold for "releasing" the note is significantly different from the threshold for triggering the note. This filters out tiny motions that might otherwise trigger lots of notes. Credits Many thanks go to Jen Lewin for loaning the Korg NX5R synthesizer. Her Laser Harps are the obvious inspiration for the Light Drum. Revision History:
| |||||||
Related Links: | ||||||||
| voice: 720-564-0373, email: sales@acroname.com, address: 4822 Sterling Dr., Boulder CO, 80301-2350, privacy © Copyright 1994-2010 Acroname, Inc., Boulder, Colorado. All rights reserved. |