The BlowChucks Wind Instrument Controller
My latest musical instrument contraption
Over the past couple of years I've been experimenting with electronic wind instruments that mimic the way that a trombone player interacts with his/her instrument. The two instruments I made, the Gordophone and the 3d Trombone, were interesting and fun to build, but there are a couple of problems I haven't been able to solve, and until I solve those problems, the instruments aren't as playable as I want them to be. Because of that, I've gotten kind of stuck and didn't do much music hacking for a while.
To get unstuck, I decided to write a series of posts describing things I've learned while I was building those controllers, which I am still working on. In that series, I've tried to be as hands-on as possible, publishing diagrams that describe the physical construction, wiring, and source code.
Along the way, I wondered if there was a way to make a wind controller that was more accessible and easier to play than the instruments I'd been designing.
Coincidentally, my wife and I finally broke down and bought a Wii system for our kids, which came with the standard WiiMote and Nunchuck accessory. The first time I used the Nunchuck, I thought "wow, this would be a pretty cool controller to use for an electronic instrument." After I did a little web research, I discovered that it has:
- 2 momentary pushbuttons
- a joystick
- a 3-axis accelerometer
I'm a big fan of Onyx Ashanti's work, and I've always been impressed with how his beatjazz controller frees up his hands to move around independently. This lead me to think about using two Nunchucks in a single instrument, in addition to the pressure sensor.
The instrument is really simple - only 4 parts are needed. A Freescale pressure sensor (the one I discussed in a previous post), the two nunchucks, and a Teensy 3.0 microcontroller. If you've read my previous posts, you'll note that I'm now using the Teensy 3.0 instead of the Teensy 2.0. I'll discuss why I made that change in the section "Challenges" later in this post.
The wiring is pretty simple:
The pressure sensor gets a reference voltage on pin 2, ground on pin 3, and the output connects to pin 4. The output voltage varies between 0 and the reference voltage depending on the breath pressure (so this part should work fine on either 3.3 or 5 volt controllers, and that's been my experience).
The pressure sensor output goes to the Teensy analog pin 0, which is read to determine how hard the performer is blowing.
Each Nunchuck gets a connection to ground and power, and a distinct i2c bus connection to the Teensy.
I began work on this project by using a Teensy 2.0 controller (which is awesomely cool because it has USB-MIDI support built in) and one Nunchuck. I was able to build an instrument that can manage Ableton Live scenes (previous/next, launch), using one Nunchuck.
While working on the next iteration of the controller I ran into one serious roadblock. The nunchuck is designed to plug into the WiiMote game controller's single accessory port. The nunchuck wasn't designed in a way that allows two of them to be hooked up at the same time. This is because each device on an i2c bus needs to have a separate identifier, but all nunchucks have the same i2c id.
To solve this problem, I switched to the Teensy 3.0, which has two sets of i2c pins. Although it looks like the ARM Cortex M3 that the Teensy 3.0 is based on has two separate i2c buses, there is only one i2c block on the chip. Still, with a bit of creative programming, you can make things work by configuring one set of i2c pins, polling one nunchuck, then configuring the other set of pins and polling the other nunchuck. Thanks to Brian in the PJRC forum for his new i2c library and also for the help in figuring out how to make both i2c "buses" work.
Another option would have been to stick with the Teensy 2.0 and use something like a 4053-series analog multiplexer to let the Teensy talk to both nunchucks. At some point I'll adapt this instrument so it can work with a plain Arduino, and I'll include the multiplexer in that design.
How It WorksFirst, an explanatory video:
The code, which is available on github, works as follows:
Each time through the loop() method, we do the following
- Poll each nunchuck and record the joystick position, button state, and the current pitch (up/down) and roll (side-to-side) position.
- Record the current analog value read from the breath sensor
If notes are currently sounding, we also send new MIDI continuous controller values for breath controller and also send updated aftertouch values. We send both because some synthesizer patches respond to breath controller input, while others, such as the Korg M1 software synth I use in the video, only respond to aftertouch values.
When it's time to send note on messages, we first calculate a "base" note (not a "bass" note), by looking at the "compass position" of the right joystick, and map those positions to the notes of a pentatonic scale:
The left joystick can be used to transpose the base note by an octave up or down by moving it in the X axis. If pushed to the left, the base note is transposed down an octave, by subtracting 12 from the base MIDI note value. If pushed to the right, the base note is transposed up an octave by adding 12 to the base MIDI note value (centered leaves the base note as is).
Once the base note has been calculated, a harmonization of the base note is created. There are several different harmonization algorithms, which can be cycled through by using the buttons on the left joystick. In the code, we use a function pointer to select which harmonization function gets called for note on events.
There are several parallel harmonization algorithms, as well as two that create slash chord voicings by choosing a bass note randomly from one of several choices.
Then, we decide how many notes of the harmonization to turn on by examining the roll value of the left nunchuck. When rolled all the way to the left, only the base note sounds. Rolling the nunchuck to the right enables more and more of the notes of the harmonization.
One final thing we do on each loop is look for button presses on the right nunchuck, and map those to MIDI note on messages on a second MIDI channel. If the upper button is pressed, we send MIDI note on and note off messages for MIDI note C0. If the lower button is pressed, we do the same, but with note C#0, and if both buttons are pressed and released, we send a MIDI D0 note on/off pair. This is intended for use with Ableton live to navigate up and down the list of scenes with the up and down buttons, and to launch the currently selected scene by pressing both buttons.