Magic Flute

I've built a "Magic Flute" for my Living Art Finite State Machine project.
The Magic Flute is a simple wind-style MIDI controller interface which can play all of the notes in a C-major scale. I'm a keyboard player by training, but I've always wanted to try playing a wind instrument -- particularly the clarinet.
The major purpose of this assignment, however, was to create a Finite State Machine:

As we discussed in class, the Finite State Machine is characterized by inputs, outputs, and a memory of previous states. In the case of the Magic Flute controller, the inputs are the keys. The outputs are a slight clicking sound as the keys contact the body of the instrument, but more importantly the MIDI messages the controller sends. The memory is in the code that runs on the ATMEGA chip on the Arduino board. The code remembers which buttons were pressed and sends MIDI messages according to the Finite State Machine.
You may notice that there is no mention of wind pressure in the Finite State Machine. I spent the better part of last weekend trying to get a sound level circuit to work. The circuit I used worked fine for amplifying audio, but was very unreliable when I tried to use Arduino to measure the amplitude of sound coming into it.
I came up with some other possibilities for measuring the wind speed inside the controller:
- Using a tiny encoder wheel with a opto interrupter to measure the speed
- Looking for a vibration sensor that outputs a good signal
- Hot-wire anemometer
There are some other extensions I would like to make to the controller's firmware if I have time to build it again:
- A button-triggered mini sequencer function so I can record and playback a short motif. This could be really cool for live performance. I could sample a short loop as accompaniment and then play a live melody on top of it. - A transposition function so I can play notes outside of the C-major scale
- Key combinations to allow me to play semitones which are fundamental to playing other scales
- A volume knob
/*
Magic Flute v1.0
2007-01-30
Michael Chladil
- 8-button MIDI controller using the Arduino's digital inputs
- Sends MIDI note-on and note-off commands for the C-major scale
*/
#define DEBUG 1
#define FIRST_SWITCH 2
#define LAST_SWITCH 9
#define SERIAL_MODE BYTE
/* HEX | BINARY | ASCII | DECIMAL
Useful for changing debugging schemes. If I want to look at the serial data without a
MIDI connection, I can change SERIAL_MODE to something else
*/
int switchStates[8];
int lastSwitchStates[8];
char notes[8] = {62, 64, 66, 67, 69, 71, 73, 74};
int i;
void setup ()
{
for (i = FIRST_SWITCH; i <= LAST_SWITCH; i++)
pinMode (i, INPUT);
Serial.begin (31250);
}
void loop ()
{
for (i = FIRST_SWITCH; i <= LAST_SWITCH; i++)
{
switchStates[i - FIRST_SWITCH] = digitalRead (i);
if (lastSwitchStates[i - FIRST_SWITCH] != switchStates[i - FIRST_SWITCH])
{
if (switchStates[i - FIRST_SWITCH] == 1) // PRESS -- switch has transitioned from low to high
noteOn (0x90, notes[i - FIRST_SWITCH], 100);
else // RELEASE -- switch has tranistioned from high to low
noteOn (0x90, notes[i - FIRST_SWITCH], 0);
lastSwitchStates[i - FIRST_SWITCH] = switchStates[i - FIRST_SWITCH];
}
}
}
// plays a MIDI note. Doesn't check to see that
// cmd is greater than 127, or that data values are less than 127
void noteOn(char cmd, char data1, char data2) {
Serial.print(cmd, SERIAL_MODE);
Serial.print(data1, SERIAL_MODE);
Serial.print(data2, SERIAL_MODE);
}


















