Sunday, January 27, 2013

Expression, Part 2 (MIDI Aftertouch)


In my previous post I showed how to map the breath pressure measured at the time a note commences to MIDI note on velocity. This allows a wind controller to play synth patches that mimic percussive or plucked instruments in a fairly natural way - the harder you blow, the harder the attack sounds (assuming that the synthesizer patch is responsive to note on velocity).

Another expression parameter present in the MIDI spec is aftertouch, sometimes referred to as pressure. After pressing a key down, a player can "lean on" the note and the keyboard will send additional MIDI messages that tell a synthesizer how hard the key is being pressed. Synth patches that respond to aftertouch will often alter a filter frequency as the pressure on the key increases (usually brightening the sound), or apply more vibrato to the note, but that's just one of many possible things that can be altered in real time.

There are actually two types of aftertouch - monophonic aftertouch, sometimes called channel pressure, and polyphonic aftertouch. With monophonic aftertouch, the keyboard only sends one value for aftertouch, no matter how many keys are being held down. With polyphonic aftertouch, the keyboard sends one aftertouch value for each key being pressed. Since a wind instrument is inherently a monophonic (one note at a time) instrument, we'll only worry about monophonic aftertouch in this post.

This sketch builds on the sketch in the MIDI note on velocity sketch (and uses the same circuit built in this post), and brings back a couple of the concepts from the breath controller post. Notice how we keep track of the last time we sent an aftertouch value, and only send a new value if a specific amount of time has passed, to avoid sending unnecessary MIDI data.

I've highlighted in yellow the additions the sketch from the previous post (so anything not in yellow is unchanged). There really isn't a lot of new code, mostly because we only need to worry about sending aftertouch values when we know a note is on.


#define MIDI_CHANNEL 1
// The threshold level for sending a note on event. If the
// sensor is producing a level above this, we should be sounding
// a note.
#define NOTE_ON_THRESHOLD 80
// The maximum raw pressure value you can generate by
// blowing into the tube.
#define MAX_PRESSURE 500

// The three states of our state machine
// No note is sounding
#define NOTE_OFF 1
// We've observed a transition from below to above the
// threshold value. We wait a while to see how fast the
// breath velocity is increasing
#define RISE_WAIT 2
// A note is sounding
#define NOTE_ON 3
// Send aftertouch data no more than every AT_INTERVAL
// milliseconds
#define AT_INTERVAL 70 
// We wait for 10 milliseconds of continuous breath
// pressure above NOTE+ON_THRESHOLD before we turn on
// the note, to de-glitch
#define RISE_TIME 10 
// The five notes, from which we choose one at random
unsigned int notes[5] = {60, 62, 65, 67, 69};

// We keep track of which note is sounding, so we know
// which note to turn off when breath stops.
int noteSounding;
// The value read from the sensor
int sensorValue;
// The state of our state machine
int state;
// The time that we noticed the breath off -> on transition
unsigned long breath_on_time = 0L;
// The breath value at the time we observed the transition
int initial_breath_value;
// The aftertouch value we will send
int atVal;
// The last time we sent an aftertouch value
unsigned long atSendTime = 0L;


void setup() {
  state = NOTE_OFF;  // initialize state machine
}

int get_note() {
  return notes[random(0,4)];
}

int get_velocity(int initial, int final, unsigned long time_delta) {
  return map(final, NOTE_ON_THRESHOLD, MAX_PRESSURE, 0, 127);
}

void loop() {
  // read the input on analog pin 0
  sensorValue = analogRead(A0);
  if (state == NOTE_OFF) {
    if (sensorValue > NOTE_ON_THRESHOLD) {
      // Value has risen above threshold. Move to the RISE_TIME
      // state. Record time and initial breath value.
      breath_on_time = millis();
      initial_breath_value = sensorValue;
      state = RISE_WAIT;  // Go to next state
    }
  } else if (state == RISE_WAIT) {
    if (sensorValue > NOTE_ON_THRESHOLD) {
      // Has enough time passed for us to collect our second
      // sample?
      if (millis() - breath_on_time > RISE_TIME) {
        // Yes, so calculate MIDI note and velocity, then send a note on event
        noteSounding = get_note();
        int velocity = get_velocity(initial_breath_value, sensorValue, RISE_TIME);
        usbMIDI.sendNoteOn(noteSounding, velocity, MIDI_CHANNEL);
        state = NOTE_ON;
      }
    } else {
      // Value fell below threshold before RISE_TIME passed. Return to
      // NOTE_OFF state (e.g. we're ignoring a short blip of breath)
      state = NOTE_OFF;
    }
  } else if (state == NOTE_ON) {
    if (sensorValue < NOTE_ON_THRESHOLD) {
      // Value has fallen below threshold - turn the note off
      usbMIDI.sendNoteOff(noteSounding, 100, MIDI_CHANNEL);  
      state = NOTE_OFF;
    } else {
      // Is it time to send more aftertouch data?
      if (millis() - atSendTime > AT_INTERVAL) {
        // Map the sensor value to the aftertouch range 0-127
        atVal = map(sensorValue, NOTE_ON_THRESHOLD, 1023, 0, 127);
        usbMIDI.sendAfterTouch(atVal, MIDI_CHANNEL);
        atSendTime = millis();
      }
    }
  }
}


Here are a couple of recordings I made. In the first, I play some long notes that have a hard initial attack, then I immediately back off the breath, and blow harder and harder until I release the note (a fp plus a crescendo for you musicians).

In this first example, the synth is not responding to aftertouch, so you just hear a static note.

In the second example, I've modified the synth patch to apply vibrato to the patch, and the amount of vibrato depends on the aftertouch value.

Are you able to hear the vibrato (wavering sound) at the end of the notes?

What's Next


With the ability to add expressiveness via MIDI note velocity and aftertouch, we can make some pretty interesting sounds, but we're still mimicking a keyboard instrument. To realize the full potential of an electronic wind instrument, we're going to need to get synthesizers to respond to us in a way that makes sense for the way that a wind instrument works.

While I am by no means an expert in synth programming, I'll share what I know, and maybe we can come up with some interesting sounds.

Monday, January 21, 2013

Expression, part 1 (MIDI Note On Velocity)

In our previous Arduino sketches, we created musical instruments that were very limited in terms of expression. In this post, I'll discuss two ways that we can give the instrument more expressive capabilities that utilize the performer's breath - mapping breath articulation to MIDI note on velocity, and mapping breath values to MIDI aftertouch after the initial attack.

These two techniques are useful if you are trying to play an existing synthesizer patch that is not specifically designed for wind control. They still leave a lot to be desired if you want to create an instrument that plays like an acoustic wind instrument, but I'll cover that topic in a later post.

An Inventory Of Expression Parameters


Before I go much further, let's take a moment to understand the various ways the the MIDI spec conveys expressive data, and how that MIDI data relates to a breath sensor.

Note On Velocity


With a velocity-sensitive keyboard, the MIDI note on velocity describes how hard the key on the keyboard was pressed (strictly speaking, it's the speed with which the finger moves the piano key through its range of motion - that's why it's called "velocity" and not "force"). For percussive instruments like drums or keyboards, it usually controls the overall volume of the ADSR envelope. Note on values range from 0 to 127, with 0 representing the lightest possible touch, and 127 representing the maximum force.

For a wind controller, it's not so clear. When a wind player articulates a note, the note starts from zero breath and increases at some rate controlled by the player. In the case where the player is using a hard articulation (that is, one with a fast rise time), it may make sense to try to map the rise time of the sensor to a note on velocity. This can be helpful if you are trying to play a patch that behaves like a percussive or plucked instrument. We'll implement this in the first sketch in this series, and see how it works out. As a hint, it's kind of a dead-end if we really want to build an instrument that responds like a real-world wind instrument, but the concepts here are generally useful, plus if you really do want to play a piano or drum patch, it'll help you play that patch with more expression.

There is also a corresponding note off velocity. I don't think this is widely used in synth patches, but it would control the duration of the R phase of the ADSR envelope. We won't implement it in our instrument's code, to keep things simple.

Aftertouch


In addition to detecting how hard a key was initially pressed, many MIDI keyboards can detect how hard a key is being pressed while it it being held down and transmit that data via MIDI aftertouch messages. With many synth patches, pressing harder on the key will engage a vibrato effect like the modulation wheel.

With our wind controller, It's pretty simple to send aftertouch data that corresponds to the breath values. So, if a patch is configured to respond to aftertouch, we should be able to make it respond to how hard we blow after starting the note. We'll implement that in our sketch and see how it affects a few different synthesizer patches.

Continuous Controllers


We saw how continuous controllers work in a previous post. They are MIDI messages that aren't associated with any particular note. There are many different continuous controllers defined (here's a complete list).  Some synthesizers, and especially software-based synthesizers, allow you to route any continuous controller to any synthesizer parameter. When we get to the post about designing synth patches for wind control, we'll see how powerful this capability is.

Mapping Breath to Note On Velocity


 Here's a sketch that will allow you to play MIDI patches that respond to note on velocity. Most piano, drum, and guitar patches will probably respond to note on velocity information.

The basic approach is to take the reading from the breath sensor at the time the note begins, and map that to a value in the range 0 to 127 (the minimum and maximum allowable MIDI note on velocity values), and send that with the note on event. We can use the Arduino map() method to do that math, like we did in our continuous controller sketch.

The only slightly tricky thing is that, when the breath starts, it takes a few milliseconds to build to its final value, so if we use the first value we read, it won't be as "loud" as the player intended. To get around that, we actually wait a little while after we see the breath go above the note on threshold value, and then re-sample the pressure sensor. The second sample is the one we map to the velocity.

The other concept in this sketch that you may not be familiar with it the use of a very simple finite state machine. While it may sound complicated, it's actually pretty simple. At any time, the sketch is in one of three states:

  • Note Off State - no note is sounding
  • Rise Time State - the performer has started to blow into the sensor, and we're waiting a bit for the pressure to rise to its final value
  • Note On State - a note is sounding
 For each state in a finite state machine, you also have to know what actions will move you from that state to some other state. One way to do that is via a table:


Current State   Input                       Next State
======================================================
NOTE_OFF        Breath value goes above     RISE_TIME
                NOTE_ON_THRESHOLD 

RISE_TIME       RISE_TIME milliseconds      NOTE_ON
                have elapsed

RISE_TIME       Breath value goes below     NOTE_OFF
                NOTE_ON_THRESHOLD 

NOTE_ON         Breath value goes below     NOTE_OFF 
                NOTE_ON_THRESHOLD
  

Another way to visualize a state machine is with a state graph. The states are shown as ovals, and the transitions between states are the edges (curved arrows) in the graph. Note that two of the states have transitions that point to themselves (I didn't include those in the table above). That's perfectly ok and shows that some inputs might not cause a transition out of the current state. Click the diagram to see a larger version if it's hard to read.




Here's the sketch: 

#define MIDI_CHANNEL 1
// The threshold level for sending a note on event. If the
// sensor is producing a level above this, we should be sounding
// a note.
#define NOTE_ON_THRESHOLD 80
// The maximum raw pressure value you can generate by
// blowing into the tube.
#define MAX_PRESSURE 500

// The three states of our state machine
// No note is sounding
#define NOTE_OFF 1
// We've observed a transition from below to above the
// threshold value. We wait a while to see how fast the
// breath velocity is increasing
#define RISE_TIME 10
// A note is sounding
#define NOTE_ON 3

// The five notes, from which we choose one at random
unsigned int notes[5] = {60, 62, 65, 67, 69};

// We keep track of which note is sounding, so we know
// which note to turn off when breath stops.
int noteSounding;
// The value read from the sensor
int sensorValue;
// The state of our state machine
int state;
// The time that we noticed the breath off -> on transition
unsigned long breath_on_time = 0L;
// The breath value at the time we observed the transition
int initial_breath_value;

void setup() {
  state = NOTE_OFF;  // initialize state machine
}

int get_note() {
  return notes[random(0,4)];
}

int get_velocity(int initial, int final, unsigned long time_delta) {
  return map(final, NOTE_ON_THRESHOLD, MAX_PRESSURE, 0, 127);
}

void loop() {
  // read the input on analog pin 0
  sensorValue = analogRead(A0);
  if (state == NOTE_OFF) {
    if (sensorValue > NOTE_ON_THRESHOLD) {
      // Value has risen above threshold. Move to the RISE_TIME
      // state. Record time and initial breath value.
      breath_on_time = millis();
      initial_breath_value = sensorValue;
      state = RISE_TIME;  // Go to next state
    }
  } else if (state == RISE_TIME) {
    if (sensorValue > NOTE_ON_THRESHOLD) {
      // Has enough time passed for us to collect our second
      // sample?
      if (millis() - breath_on_time > RISE_TIME) {
        // Yes, so calculate MIDI note and velocity, then send a note on event
        noteSounding = get_note();
        int velocity = get_velocity(initial_breath_value, sensorValue, RISE_TIME);
        usbMIDI.sendNoteOn(noteSounding, velocity, MIDI_CHANNEL);
        state = NOTE_ON;
      }
    } else {
      // Value fell below threshold before RISE_TIME passed. Return to
      // NOTE_OFF state (e.g. we're ignoring a short blip of breath)
      state = NOTE_OFF;
    }
  } else if (state == NOTE_ON) {
    if (sensorValue < NOTE_ON_THRESHOLD) {
      // Value has fallen below threshold - turn the note off
      usbMIDI.sendNoteOff(noteSounding, 100, MIDI_CHANNEL);  
      state = NOTE_OFF;
    }
  }
}




Here's how it sounds. I play four notes quietly, four notes loud, four more notes quietly, and then do four notes of increasing volume (a crescendo, in musical terms), and eight notes of decreasing volume (a diminuendo). The sketch is randomly picking which notes to play, but the attack velocity of each note is under my control.




Looking at the MIDI data, it looks like the values are ranging from a low of about 4 to a maximum of about 100, so I could alter the MAX_PRESSURE value in the sketch to fix that. But you get the idea.

Here's another rhythmic motif in 9/8 that I played on a different wind controller, a Yamaha WX-7, that also maps breath to note on velocity. Because of this mapping, I'm able to accent the 1st, 4th, 6th, and 8th notes of each group of nine, resulting in a 3 + 2 + 2 + 2 pattern.


In part two, I'll add MIDI aftertouch to this sketch.




Friday, January 18, 2013

Breath and Note On/Off Transitions

If we're going to build a MIDI wind instrument controller, it's going to need to send MIDI note on and off messages - it's just part of the MIDI spec. But the tricky part is knowing when your breath is producing enough pressure to justify sending the MIDI note on message.

An approach that makes sense for our project is to choose some value a little above the "idle" value that the pressure sensor reads (that is, when you're not blowing into it). My sensor produces values of about 65 when I'm not blowing into it, and a threshold value of 100 seems to work well. In the Arduino sketches in this post, you may need to change the threshold value to something appropriate for the way your air tubing is set up, as well as your playing style. To adjust that threshold, look for the line:

#define NOTE_ON_THRESHOLD 100

And experiment with different values until you find something that works. Don't forget to recompile and upload the sketch after you make changes.

One Note


The following sketch reads the pressure sensor and sends a MIDI Note On event for middle C (the C about in the middle of the piano keyboard) when it detects that the pressure is above the threshold value. It sends a MIDI Note Off event when the pressure is below the threshold value. It also keeps track of whether a note is sounding or not, so it knows if a Note On/Off message needs to be sent (if the note is already on, we don't need, or want, to send another Note On message).

#define MIDI_CHANNEL 1
// For this sketch, we only can play one note
#define MIDI_NOTE 60 // Middle C (C4)
// The threshold level for sending a note on event. If the
// sensor is producing a level above this, we are in note on
// state, otherwise note off
#define NOTE_ON_THRESHOLD 100

// We keep track of whether a note is sounding or not,
// so we know whether to send a note on or off event.
boolean noteSounding = false;
// The value read from the sensor
int sensorValue;

void setup() {
  // Nothing to initialize for this sketch
}

void loop() {
  // read the input on analog pin 0
  sensorValue = analogRead(A0);
  // Send the appropriate MIDI note on or off message
  if (sensorValue > NOTE_ON_THRESHOLD) {
    if (noteSounding) {
      // Nothing to do - note is already on
    } else {
      // Value has risen above threshold - turn the note on
      usbMIDI.sendNoteOn(MIDI_NOTE, 100, MIDI_CHANNEL);
      noteSounding = true;
    }
  } else {
    if (noteSounding) {
      // Value has fallen below threshold - turn the note off
      usbMIDI.sendNoteOff(MIDI_NOTE, 100, MIDI_CHANNEL);
      noteSounding = false;
    } else {
      // Nothing to do - note is already off
    }
  }
  // Delay a bit to avoid glitches (very short notes that
  // sound because the breath falls below the threshold
  // value, then goes back above it). Adding 20
  // milleseconds of delay reduces the responsiveness
  // of the instrument, and we'll discuss better ways
  // of handling this in later posts. For now, this is
  // good enough.
  delay(20);
}

Here's how the sketch sounds when playing the Grand Piano patch from GarageBand.

Four long notes:

A synth pad, long notes:

And to test the responsiveness, here I'm playing faster and faster notes (using a technique called double-tonguing and then flutter-tonguing). It keeps up pretty well:


Ok, great. We can send MIDI Note On/Off messages. But this is pretty boring, only playing one note. We'll be talking about how to select notes based on fingerings in later posts, but let's at least make our sketch choose a couple of different notes at random.

Here's a modification to the previous sketch. Instead of always sending a middle C for the note, whenever a Note On event is to be sent, it randomly chooses one of 5 notes from a pentatonic scale by using the random() method from the Arduino library. Look at the get_note() method - that's where we pick the random note to play. The Arduino library's random() method picks a number from 0 through 4 for us, and we use that to select one of the MIDI notes 60 (middle C), 62 (D), 65 (F), 67 (G), or 69 (A).

#define MIDI_CHANNEL 1
// The threshold level for sending a note on event. If the
// sensor is producing a level above this, we are in note on
// state, otherwise note off
#define NOTE_ON_THRESHOLD 80  

unsigned int notes[5] = {60, 62, 65, 67, 69};

// We keep track of which note is sounding. The value
// -1 means no note is sounding.
int noteSounding = -1;
// The value read from the sensor
int sensorValue;

void setup() {
  // Nothing to initialize for this sketch
}

int get_note() {
   return notes[random(0,4)];
}

void loop() {
  // read the input on analog pin 0
  sensorValue = analogRead(A0);
  // Send the appropriate MIDI note on or off message
  if (sensorValue > NOTE_ON_THRESHOLD) {
    if (noteSounding != -1) {
      // Nothing to do - note is already on
    } else {
      // Value has risen above threshold - turn the note on
      noteSounding = get_note();
      usbMIDI.sendNoteOn(noteSounding, 100, MIDI_CHANNEL);
    }
  } else {
    if (noteSounding != -1) {
      // Value has fallen below threshold - turn the note off
      usbMIDI.sendNoteOff(noteSounding, 100, MIDI_CHANNEL);
      noteSounding = -1;
    } else {
      // Nothing to do - note is already off
    }
  }
  // Delay a bit to avoid glitches (very short notes that
  // sound because the breath falls below the threshold
  // value, then goes back above it). Adding 20
  // milleseconds of delay reduces the responsiveness
  // of the instrument, and we'll discuss better ways
  // of handling this in later posts. For now, this is
  // good enough.
  delay(20);
}


Here's how it sounds. I'm playing a syncopated rhythm, using the GarageBand Grand Piano patch. Notice how the note pitches change randomly:

Here I'm playing the new sketch and using the "Kotu Chords" patch from GarageBand's Synth Textures collection, but playing the same rhythm. This patch harmonizes the input notes, so even though the get_note() method only produces one randomly selected note, once I feed that note into the synthesizer, I get about 4 notes out.


A cool aspect of this sketch is that, since we're using the random() method from the Arduino library to choose which note to play, two performances of the same piece on this instrument are likely to be very different. And by combining our pretty simple breath based controller with some interesting patches from GarageBand, we're able to make some interesting sounds. Try playing around with different patches in GarageBand, or if you're using a different audio environment and/or OS, experiment with what you have. Upload your creations and share links to them here.

Next

While these sketches can produce some interesting sounds, they are pretty much devoid of expression. All the notes are exactly the same volume, and we have no control over how the note evolves over time. In my next post, I'll talk about how to create an instrument that is much more responsive to the nuances of breath control.

Tuesday, January 15, 2013

Building a Breath Controller


In this project, I'll build on my previous post on reading breath pressure into an Arduino or Arduino clone. We'll use the same circuit from that post, and write some new code that maps the sensor values we read to a MIDI continuous controller (which I'll refer to as a CC from here on out). That CC data will, in turn, control a parameter of a software synthesizer.

What's a MIDI CC?


MIDI continuous controllers are a standard way for performers to modify the sound produced by the synthesizers they are playing. The "continuous" part of the name means that the values sent on the MIDI bus control some parameter with a range. If you've played a MIDI keyboard that has a modulation wheel:




you know that the more you turn the "mod wheel", the more vibrato you hear, at least with most common synth patches. In the following example, I play a chord, and turn the modulation wheel from zero to full on, then back to zero.

If you dig into the MIDI spec, you'll discover that the mod wheel is only one of many continuous controllers defined. Each one has a unique number assigned to it, and some have a name, like "Modulation Wheel" or "Pan". The controller name describes what type of control is typically going to generate that data. On a traditional MIDI keyboard, if you move the mod wheel, you'll generate Continuous Controller 1 data.

If you think about it, there are many real-life things that naturally can be expressed as a continuous controller: How far you have twisted a knob. How far to the left or right your are tilting your hand. How far apart your hands are. Or how hard you are blowing air. All of these things can be mapped to some number that ranges from some minimum value to some maximum value (provided you can measure them and translate them to MIDI).

The MIDI spec states that continuous controller values vary from a minimum value of zero to a maximum value of 127. This means CC values have 7 bit resolution, which, for some applications, is not acceptable - the results sound odd. I'll talk about those later, but for many of the common synthesizer parameters that are controller by CCs, 7 bits is fine.

How the Pressure Sensor Works


Before we get into wiring up and coding the project, let's dive into how the Freescale pressure sensor works. It relies on something called the Piezoresistive Effect.

There are some materials that exhibit the property that, as you press on them, the resistance through the material changes. The Freescale sensor has a small piece of this type of material inside, and when the pressure inside the case of the sensor increases, the resistance through this material changes. The sensor also has circuitry to amplify the signal and make it work consistently even if the temperature varies.

Advances in chip fabrication techniques have allowed manufacturers to make these type of sensors in very small packages. By contrast, the Yamaha WX-7, a 1980s-era wind instrument controller, has a breath sensor that is much larger than the Freescale sensor used in this project. Although I don't know how the WX-7's pressure sensor works, I suspect it's based on the same principle.

Mapping Sensor Values

We'll now build on the circuit in my previous post and generate MIDI continuous controller data based on how hard a performer is blowing into the breath sensor.

Remember that our Arduino's analog inputs convert the values they read into a value that varies between 0 and 1023. But the MIDI spec wants you to provide values between 0 and 127. What to do?

Well, the math is pretty simple. Just divide the value read from the input by 1024, and multiply it by 128. But the arduino library has a nice convenience function named map() that does exactly this. For example:

  int sensorValue1 = analogRead(A0);
  int ccVal = map(sensorValue1, 0, 1023, 0, 127);

The code snippet above will linearly map values in the range 0-1023 to values in the range 0-127.

Generating MIDI CC Values

The PJRC USB MIDI support makes sending MIDI data over USB just ridiculously simple. From the PJRC USB MIDI reference:

usbMIDI.sendControlChange(control, value, channel)

 Where "control" is the MIDI controller to change, "value" is the mapped sensor value, and "channel" is the MIDI channel on which to send the data. Although we haven't talked about MIDI channels yet, for these exercises we'll send the data on MIDI channel 1 and then make sure that our MIDI synthesizers are either set up to listen on channel 1 or are set to "omni" mode, in which they respond to MIDI data on any MIDI channel.

Our First, and Imperfect, Sketch

#define MOD_WHEEL_CONTROLLER 1
#define MIDI_CHANNEL 1

// The value read from the sensor
int sensorValue;
// The CC value we will send
int ccVal;

void setup() {
  // Nothing to initialize for this sketch
}

void loop() {
  // read the input on analog pin 0
  sensorValue = analogRead(A0);
  // Map the value, which may range from 0 to 1023,
  // to a value in the range 0 to 127, which is
  // the valid range for a MIDI continuous controller
  ccVal = map(sensorValue, 0, 1023, 0, 127);
  // And send the value as a MIDI CC message
  usbMIDI.sendControlChange(MOD_WHEEL_CONTROLLER, ccVal, MIDI_CHANNEL);
}


 To load this sketch, first go to the "Tools" menu and choose "USB Type" and select "MIDI". Then click on the upload button.

Once you've loaded the sketch, you'll need to load a software synthesizer host on your Mac/PC/Linux box. While I can't cover every possibility in this post, I'll cover the basic steps for running Garage Band on a Mac and getting mod wheel output from our circuit.

  1. Start Garage Band.
  2. If a project opens automatically, choose Close from the File menu and choose New Project...
  3. Select the Keyboard Collection template and give the project a name in the dialog that appears.
  4.  In the list of instruments that appears, click on Solo Star - it's an interesting-sounding synth that responds to mod wheel input.
  5. Select Musical Typing from the Window menu. A window appears where you can click on a virtual MIDI keyboard.
  6. If your Teensy controller isn't plugged in, plug it in now. When you plug in a MIDI-USB device, GarageBand should pop up a window informing you that the number of MIDI inputs has changed.
  7. Click and hold down the mouse button on a note in the Musical Typing window. In the sound sample below, I clicked and held the "F" key.
  8. You should be hearing a synthesizer playing a note now. Keep holding the mouse button and blow into the tube connected to your pressure sensor. Start blowing gently, blow harder and harder, then gradually blow less and less.
  9. You should hear something about like this

And if you double-click the segment you just recorded, and select "Modulation" from the "View" menu, you can see a graph of the values the Teensy sent.

Pretty cool, huh? Actually, no, there are two serious problems with my sketch.

Shut Up, Already!

Notice that we send a MIDI CC value every time the the loop() method is called. This means that you're spamming the MIDI instruments as fast as your microcontroller can make it through its loop() method. This is not good because (a) the MIDI bus has a finite bandwidth, and (b) you can overload software synthesizers with this data, as they try to adjust internal parameters in real time.

There are two approaches I can think of to address this problem:
  1. Only send a new CC value if a certain amount of time has passed, e.g. 20 milliseconds, or
  2. Only send a new CC value if the new value is different from the previously sent value to be interesting to the synthesizer.
The first method is really easy to implement.  Here's a sketch that will only send CC values every 20 milliseconds.

#define MOD_WHEEL_CONTROLLER 1
#define MIDI_CHANNEL 1
// Send continuous controller message no more than
// every CC_INTERVAL milliseconds
#define CC_INTERVAL 20

// The last time we sent a CC value
unsigned long ccSendTime = 0L;
// The value read from the sensor
int sensorValue;
// The CC value we will send
int ccVal;

void setup() {
  // Nothing to initialize for this sketch
}

void loop() {
  // read the input on analog pin 0
  sensorValue = analogRead(A0);
  // Map the value, which may range from 0 to 1023,
  // to a value in the range 0 to 127, which is
  // the valid range for a MIDI continuous controller
  ccVal = map(sensorValue, 0, 1023, 0, 127);
  // And send the value as a MIDI CC message
  if (millis() - ccSendTime > CC_INTERVAL) {
      usbMIDI.sendControlChange(MOD_WHEEL_CONTROLLER, ccVal, MIDI_CHANNEL);
      ccSendTime = millis();
  }
}

Don't Send Useless Data

The other problem is that, even when you aren't blowing into the tube, it's sending data to the MIDI instruments. If no air is going through the tube, then why send any data at all?

This is pretty easy to fix. Recall that, even when no air was being blown through the tube, it produced a voltage that the analog-to-digital converter on the Arduino interpreted as about 64. So, if the value we read from the input port is less than about 70, let's just not send anything at all. Problem solved.

One subtle issue is that when the pressure falls below the threshold value, we need to  send a zero value. Otherwise, when you stop blowing, the controller would remain at the last value we sent, rather than zero. We handle this in the last else clause.

#define MOD_WHEEL_CONTROLLER 1
#define MIDI_CHANNEL 1
// Send continuous controller message no more than
// every CC_INTERVAL milliseconds
#define CC_INTERVAL 20
// Only send CC data if the pressure sensor reading
// a value larger than this.
#define BREATH_THRESHOLD 70

// The last time we sent a CC value
unsigned long ccSendTime = 0L;
// The value read from the sensor
int sensorValue;
// The CC value we will send
int ccVal;
// The last CC value we sent
int lastCcVal = 0;

void setup() {
  // Nothing to initialize for this sketch
}

void loop() {
  // Only read the sensor if enough time has passed
  if (millis() - ccSendTime > CC_INTERVAL) {
    // read the input on analog pin 0
    sensorValue = analogRead(A0);
    if (sensorValue > BREATH_THRESHOLD) {
      // Map the value, which may range from BREATH_THRESHOLD
      // to 1023, to a value in the range 0 to 127, which is
      // the valid range for a MIDI continuous controller
      ccVal = lastCcVal = map(sensorValue, BREATH_THRESHOLD, 1023, 0, 127);
      // And send the value as a MIDI CC message
      usbMIDI.sendControlChange(MOD_WHEEL_CONTROLLER, ccVal, MIDI_CHANNEL);
      ccSendTime = millis();
    } 
    else if (lastCcVal > 0) {
      // The pressure has just dropped below the threshold, so
      // send a CC value of zero
      usbMIDI.sendControlChange(MOD_WHEEL_CONTROLLER, 0, MIDI_CHANNEL);
      ccSendTime = millis();
      lastCcVal = 0;
    }
  }
}


Another thing you can do with this code is convert it to a MIDI Breath Controller and do cool stuff like in this video:





You can build that For about $36.

Next


In the next post, I'll show how to use the pressure sensor to manage MIDI Note On and Note Off events, which will allow us to articulate like a woodwind or brass player does.




Sunday, January 13, 2013

Breath Sensing 101

In this post, I'll discuss very basic breath sensing. We'll use a Freescale pressure sensor to detect how hard a player is blowing into a tube, and we'll print out the values being read. In later posts, I'll show how to convert those raw sensor values into MIDI continuous controller messages that we can use for expressive control of a MIDI synthesizer.

What you'll need:
  • A microcontroller. In my examples, I will use the Teensy 2.0 microcontroller from PJRC. You can use any Arduino-compatible microcontroller for these examples, but once we start using MIDI, it will be a lot easier if you have the Teensy, as it has MIDI-over-USB support built in. This means that you can plug the Teensy into your computer's USB port and directly drive a software synthesizer. I have a Mac so I'll use Garage Band for the demos, but, you can use any instrument "host" that allows you to run Apple or VST instruments. Hosts are available for Macs, PCs, and Linux.
    By the way, I recommend ordering the Teensy with pins pre-soldered, so that you can easily plug it into a breadboard while prototyping.
  • A USB cable for the microcontroller.
  • A Freescale MPXV4006GP (pdf spec sheet). You can order one from Mouser Electronics (direct link). They are about $13.00 in single quantities.
  • A suitable breadboard and jumper kit for connecting the components together. Maker Shed is a great place to get things like this, and also has a bundle of a breadboard and a jumper kit. For prototyping, I prefer flexible jumper wires, which Maker Shed also has.
  • Some heat-shrink tubing, which we'll use to make an initial attachment to the pressure sensor. I would recommend getting an assortment of heat shrink tubing sizes either online or at Radio Shack - you'll use it a lot if you do any serious amount of hacking.
  • Some 1/4" drip irrigation tubing - a few feet will do. This should be available at any hardware store or garden supply center. We'll slip this tubing over the heat shrink attached to the sensor, and the inside diameter of the irrigation tubing is close enough to the outside diameter of the heat shrink that it makes a decent seal, even without gluing it.
  • A few pushbutton switches for use in later projects where we'll be simulating woodwind keys and trumpet valves. I like the tactile button assortment available from SparkFun, but any momentary pushbutton switch that can plug directly into the breadboard will work. If you get a "Getting Started with Arduino" kit, available from a number of places, it will probably include something suitable.
  • Some solderless headers, which we'll use to attach legs to the Freescale sensor. Since the sensor is a surface mount device, it won't directly plug into the breadboard. However, its pins use the same spacing as the holes in the breadboard, so soldering 4 pins on each side of the sensor will allow us to plug it in.
  • Soldering iron, solder, and some basic soldering skills.
Preparing the Pressure Sensor

As I mentioned, the Freescale pressure sensor is a surface-mount device. Typically, a machine will place the part on a circuit board and use hot air to melt a solder paste that affixes the part directly to metallic pads on the board. This is cheaper to make/assemble than the older "through-hole" type of part, where legs on the part go through the circuit board and are soldered into the hole. It's getting harder and harder to find through-hole versions of components, so some companies like SparkFun provide "break-out" boards, which a small circuit board with the surface-mount component soldered to it, and standard-spaced holes which can be soldered to. For example, look at SparkFun's breakout board for the VS1033D MP3 chip. The chip has 50+ very tiny pins which would be extremely difficult to hand-solder (some people can do it - not me).

Fortunately, the Freescale sensor we're using is much simpler. In fact, even though there are 8 pins on the device, only three are used (in this drawing, the active pins are the three on the right side - pins 2, 3, and 4.
  


What I did was use a Helping Hands to hold the sensor and a set of  of the header pins against the sensor legs, after I flattened out the legs so they pointed straight down. I then soldered each of the 4 header pins to the sensor pin it was touching, and repeated it with the 4 pins on the other side. The result looks like this:



Try to work fast so you don't overheat the sensor electronics.

In that photo you can also see how I attached some heat-shrink tubing (the red tube) to the input port of the sensor, and then slipped some irrigation tubing over that (the black tubing). Use a lighter to heat the heat shrink tubing where it mates with the sensor's input tube so it makes a tight seal.

Now we're ready to hook things up on a breadboard (click to view a larger version):

This shows a Teensy 2.0, so if you're using some other microcontroller, hook up pin 4 of the sensor to Analog input zero.

A schematic of this circuit is:


Once that's all wired up, attach the USB cable to the controller and hook it up to your PC. Start the Arduino development environment (if you're using a Teensy, you'll also want to install PJRC's Teensyduino add-on which makes it possible to use the Teensy just like any other Arduino device from within the dev enviroment. Here is a simple sketch that will just print out the values being read from the sensor:
// the setup routine runs once when you press reset:
void setup() {
  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);
}

// the loop routine runs over and over again forever:
void loop() {
  // read the input on analog pin 0
  int sensorValue1 = analogRead(A0);
  Serial.print(sensorValue1);
  Serial.println();
  delay(100);        // delay 100 milliseconds (1/10 of a second)
}

If using a Teensy, make sure the "USB Type" option in the "Tools" menu is set to "Serial". Choose the correct board type and serial port from the Tools menu, then upload the sketch to the board.

To see the values being read, choose "Serial Monitor" from the "Tools" menu and set the baud rate to 9600. You should see a series of values being printed. Without blowing the tube, I see values of about 64, which probably corresponds to ambient air pressure. Blowing into the tube, you should be able to max out the sensor, meaning it will produce a reading of close to 1023 (the maximum value that the 10-bit analog-to-digital converter on the Arduino will produce).

In the next post, I'll describe how to map these raw values to MIDI continuous controller data, and how to use that to control MIDI synthesizers.

A Series: Basics of DIY Wind Controllers

Over the past few years I've spent some time thinking about and designing wind instrument controllers. I thought a good way to give something back would be to produce a series of blog posts describing what I've learned while tinkering with my projects.

As it turns out, I'm not a very skilled craftsman, so most of my projects end up looking like something Homer Simpson would have created. But I think I've learned a few things about building the electronics and writing code. So, in this series of posts, I'm going to concentrate on sharing some basic building blocks and core concepts, like the following:
  • Why electronic wind instruments are hard
  • Breath Sensing 101
  • Mapping analog readings to MIDI continuous controller values
  • MIDI note selection methods
  • Using sensors to alter performance data in real time
  • And more, as I think of them

Since I've been using Arduino and Teensy microcontrollers to do my experiments, I'm going to focus on those, so the code examples will target those platforms.

If you are a performer who uses an EWI, EVI, or WX-series controller, there won't be a lot of practical advice for you here, but the circuits and code may help you understand what's going on inside your instrument. Also, the posts on building synth patches that work well with wind controllers will certainly be applicable to your live rigs. So, please - read on!

So, onto post number one:

Why Electronic Wind Instruments are Hard

First of all, if you're not familiar with what an electronic wind instrument is, I'll define the term.

An electronic wind instrument is a musical instrument that employs electronics to produce the instrument's sound, and is articulated by blowing into the instrument.

There are a number of commercially available electronic wind instruments. The most common instruments are the EWI series from Akai, and the WX-5 from Yamaha. Both are woodwind-style controllers - that is, they are fingered in a way that is easily learned by someone who knows how to play the saxophone, clarinet, or flute. The Akai instruments also support a mode that is more natural for trumpet players to use.

The Akai instruments are the latest in a long line of wind controllers that started with Nyle Steiner's work in the 1970s. For more information on this history of the Steinerphone/EWI, see the Nyle Steiner home page. For more links to learn about wind controllers, check out the Wind Controller links page from Patchman Music. These two paragraphs don't come close to describing the history of wind controllers, but the links page on the Patchman site is an excellent resource to learn more.

(Aside: Nyle Steiner also invents lots of other crazy stuff. And he's a ham like me.)

ADSR


The majority of electronic instruments you can buy are really good at emulating instruments that can be modeled with the ADSR model (Attack, Decay, Sustain, Release):

 
This model describes how a sound evolves over time. For example, when you hit a key on a piano, there is an initial attack A, when the piano's hammer hits the string. After the initial strike of the hammer (the attack phase of ADSR), the string starts vibrating, and the vibration starts to lose energy. In most cases, the majority of the string's vibrational energy dissipates quickly (the D - decay phase), but then the string continues to vibrate at a lower volume, fading out gradually (the S - sustain phase). When the key is released, the piano's felt damper touches the string, stopping the vibrations (the R - release phase). Most synthesizer patches have a fixed ADSR envelope, a "recipe" for the sound as it progresses through time. For a plucked or struck instrument, the performer has some control over the duration of these phases, and can also exert some control over the initial input, e.g. how hard the string is plucked or how hard the drum head is struck.

ADSR works really well for modeling instruments that are plucked or struck, which includes most of the staple instruments of popular music like:
  • Guitar
  • Bass
  • Drums
  • Piano and other keyboards
Wind instruments, on the other hand, don't follow this model at all. The sound is produced by a column of air emanating from the performer's lungs, which in turn causes something to vibrate - a single reed (clarinet/saxophone), two reeds (oboe/bassoon), lips (trumpet/horn/trombone/tuba), or the air column itself (flute/recorder). Articulation (the starting and stopping of sound) is generally accomplished by interrupting the stream of air using the tongue. The ADSR model simply doesn't reflect the way wind instruments work. It also doesn't model the way that bowed instruments like the violin make sound either.

Due to the popularity of the instruments that ADSR models well, manufacturers of electronic musical instruments have generally not found other types of instruments to be commercially viable. Yamaha and Akai have a series of wind controllers that emulate woodwind instruments, and some smaller companies produce small quantities of instruments that emulate other types of instruments, including trumpets and violins, but for the most part, wind players have not been invited to the electronic music party until they learn to play a different instrument.

For this reason, even if you have a wind instrument controller like one from Yamaha or Akai, you're faced with the difficult task of finding synthesizer patches that work well with your controller. If you *want* to sound like a Fender Rhodes electric piano, no problem, but if you want to make that Rhodes fade in from nothing, swell up, and fade out, sorry, you're out of luck. The ADSR envelope of the Rhodes patch you have models the characteristics of the real Fender instrument.

I'll cover this topic in more detail in a later post, but the important thing to remember is that if you want to play your wind instrument controller in an idiomatic way, you're going to have to either go find some patches specifically designed for wind controllers, or build your own.

I should also mention that my work has focused on building instruments that send MIDI data, but an equally valid approach is to build instruments that send raw sensor data to a device that makes the sound itself, rather than relying on a MIDI synthesizer to make the sound. The original Steiner EWI and Akai variants had a dedicated synthesizer that directly read the instrument's sensors. Another option is to feed all the sensor outputs to a computer. The computer, in turn, uses a sound system like pd or Max to realize the sound. There are a number of artists using that approach, but one of the most exciting, in my opinion, is Onyx Ashanti, who is really pushing the envelope on the form factor for wind controllers. He started with a Yamaha wind controller, deconstructed the functionality it provided, scratched some personal itches he had with performing live, and arrived at the Beatjazz Controller. I encourage you to follow his work.

What's Next


In the next post, I'll select an inexpensive sensor that you can use to sense breath pressure in a wind controller. We'll cover how to connect it to an Arduino or Teensy controller, and how to connect tubes to the sensor so you can blow into it and measure the breath intensity.