Using Max with the Eigenharp Alpha
Aptril 26th, 2012
A new website has been created that focuses specifically on using Max with the Eigenharp. Please visit http://max4eigenharp.com for more details as well as for the Max patchers to support the Eigenharp.
The Eigenharp Alpha is a wonderful electronic instrument controller with amazing sensitivity for expressive control of synthesizers such as MIDI devices or VST soft synths. Unfortunately, I found the EigenD environment too difficult to learn. As a result, after some initial attempts to work with it, it ended up sitting in the corner of my studio.
I'm quite heavily invested in Max/MSP (Max from now on) as an environment for managing my live music environment. Although used by some programmers, Max is very accessible to people in the art/theatre world who are not particularly experienced (if at all) in the art of software development. It's very easy to manipulate MIDI and audio data using Max objects and there are a number of third party libraries (free and paid) that add even more functionality.
Just recently, the Eigen folks added support to send raw data over OSC. Since Max/MSP already has OSC support, this was a wonderful opportunity to try and use Max/MSP instead of the EigenD environment. As with my previous work to start using Max to manage my live music rig, the goal was to make it as painless as possible to create new patchers with minimum work.
Because I already had a nice working environment, the first (and hardest) problem was to figure out how best to reformat the raw OSC data coming from the Eigenharp to make it easily connectable to other objects. At the bottom level, we have a patcher called [Eigen.OSCInput].

I'm not going to go into deep details about how this patcher works as it's not something that needs to be touched on a day to day basis. (It's also a bit of hack, particularly the embedded [Eigen.OSCProcessor] object.)
Fortunately, this object just needs to run in the background. Once it's running, four pieces of data are made available globally through the use of [send/receive] objects.
- [send EigenKeyInfo] (key pressed or released)
- [send EigenX] (continuous horizontal movement)
- [send EigenY] (continuous vertical movement)
- [send EigenZ] (continuous in/out movement)
These all send out a two item list of integers. The first item is always the physical key number, which is between 1 and 120. (I have not yet added support for the 12 percussion keys at the bottom of the Alpha). For the EigenKeyInfo, the second integer is either 64 or 0 representing whether the specified key was touched or released respectively. I have not yet decided how best to capture the initial velocity with which the key was touched.
For EigenX and EigenY, the second value is an integer between -16000 and +16000. For EigenZ, the second value is an integer between 0 and 32000. You're probably wondering how I came up with those values. First of all, these values represent work-in-progress and I'm not permanently committed to them. The raw data coming from the Eigenharp appear as floating point values between -1.0 and 1.0 for X and Y and between 0.0 and 1.0 for Z. However, for the most part, it's much more convenient to work with integer numbers in Max and so I wanted to retain the high resolution as much as possible rather than immediately reducing the data down to MIDI levels. While I could have used the full integer range like -32768 .. +32767, I just figured that rounding to the nearest thousand resulted in a very minimal loss of resolution while providing numbers that were much easier to remember.
Now that we have this data available from the bottom level, let's go "top-down" and examine a patcher that would be a typical example to be created by a user.
Here's a complete patcher that allows you to play bass with one hand and saxaphone with the other hand. The fingering is the same as the top 5 strings of a guitar. The objects here are intended to be used as-is without ever drilling into them.

The [Eigen.Alpha.Keygroup] object defines a range of rows that will be detected. In the example above, [Eigen.Alpha.Keygroup 1 8] means that if you touch any key within the top 8 rows of the Alpha, that information will be made available. We'll use this for our bass control. If you touch any key outside that range, it will just be ignored. Note of course that there is a second object [Eigen.Alpha.Keygroup 10 20] which is of course used for the saxaphone.
The output of this object is not however the physical keynumber data that was produced by the lower level patch. If we open up the first [Eigen.Alpha.Keygroup] object, we see the following.

Focus on the leftmost structure which handles key down/up events. The raw key number is converted by [Eigen.KeyToRC 24] to a row and column number. The argument 24 represents the number of rows on an Alpha. The same object could be used with the value 9 for the Pico. The down/up value is passed through unchanged. We then unpack the list again so we can examine the row number by itself. The [split] object then allows only events whose row number is between 1 and 8 to be forwarded (along with the original column number and down/up value). We then normalize the row number so that the first row will always be zero.
The other structures perform similar processing for the X, Y and Z values.
Assuming you want to actually play these 8 rows, you will need to feed the output of [Eigen.Alpha.Keygroup] into an object that converts the row and column to note numbers. The [Eigen.Scale.Guitar] object is one such object that accepts row and column values and converts them to note numbers in such a way that the fingering is the same as a standard guitar. This object takes two parameters the first of which defines the starting note number for the very first key of the group. The second parameter defines the MIDI channel on which note numbers are to be sent. This is particularly useful for multi-timbral MIDI synthesizers, whether they are external hardware devices or internal VST soft synths.
If you want a different scale, such as a major or minor scale, or perhaps a chromatic scale whose intervals match violin tuning, you would replace the [Eigen.Scale.Guitar] object with something else. At this point, I'm only interested in guitar-style tuning and so have only created this particular object so far.
Going back to the main patcher, you can see that the output of each [Eigen.Scale.Guitar] object is fed into the [GenericVST] object, which is a wrapper for VST synths. The [GenericVST] object is described here in more detail and is part of the library I have been developing for managing a live keyboard rig.
In the example, we're using Kontakt, a multi-timbral sampler which has been loaded with the bass and flute sounds on MIDI channels 1 and 2 respectively.
This is work in progress and will undergo significant change rapidly as I have time to explore and experiment further. If any readers decide to play with this library, please let me know and I will help as time permits (but no promises!).

Scorecerer: the musician's 

