Max for Eigenharp

Using Max/MSP to control the Eigenharp

Easy VST hosting with MaxMSP

Over the last few years, I have depended on MaxMSP to support my keyboard rig and eigenharp for live use with The Security Project and Beyond The Wall.

I recently started a complete overhaul of my design, partially to address some deficiencies in my earlier version but more importantly to make it even easier to modify going forward. I come away from each tour wishing that I had the ability to do x, y, or z and my original design eventually became too “hacky” for continued maintenance.

My system was originally developed as a replacement for Apple’s MainStage, a rather wonderful program which was unfortunately extremely buggy when it first came out and so not reliable for live use. Although today MainStage is an extremely good product, I have added sufficient new functionality to my custom system such that it is no longer possible for me to revert to MainStage.

A key goal is to make it very easy to put together “patches” for songs as efficiently as possible. To that end I rely on a lot of abstractions with some naming conventions. The naming conventions allow most internal connections to be made using send/receive and send~/receive~ objects with automatically inferred names.

In this tutorial, I show how to create a single patcher that lets you create as many VSTs as you need and very simple mechanisms to edit and play them.

Let’s see a very quick example of how this works in practice for a musician. Here’s a picture of the complete patcher. Below the picture is an explanation of the various objects in that patcher.

screenshot_372

The details.

screenshot_362

Here, we have created a new patched and instantiated two poly~ objects that will hold and manage VST~ objects, named V1 and V2 respectively. V1 has 4 individually controllable VST~ objects and V2 has 6 of them. Typically you would determine how many of these objects to create (and how many instances in each of them) based on the number of cores in your system, leveraging Max’s ability to distribute different instances in a single poly~ to different cores as available.

Muting and unmuting of individual instances is handled automatically by detecting activity or lack thereof. This allows you to keep the overall CPU utilization as low as possible, particularly useful where you need to have many VSTs available but you’re typically only playing a couple of them at any one time.

How would you use them? Well, here’s a simple patcher that lets you use a single keyboard to play on two VSTs.

screenshot_370

TopLeftCore produces regular MIDI events such as notes, pitchbend and aftertouch. There is also a TopLeftSurface object that represents the sliders, knobs and buttons of that keyboard.

Note events are filtered by KeyboardLayer objects. These objects allow a split to be defined where only MIDI notes within the defined range are allowed through. The optional third parameter defines a transpose amount that should be applied to each MIDI note. So in this example, all notes played in the bottom octave are sent to one VST and the remaining notes are sent to another VST. From the names, we can see that the first VST will be the third instance of the first poly~ object and the second VST will be the fourth instance of the second poly~.

Getting at the audio

So how do we get access to the audio coming from these VSTs? Well, an object called PolyFromStereoVirtualOutput can be instantiated with arguments that match the desired VST. For example,

screenshot_365

(There’s an optional third parameter which is used to index an internal gain, more on that later). Finally, we connect these up to whatever audio devices are available, through an object that provides adjustable gain  (for easy volume control). In the example here, I have a single stereo output pair from my computer so that the channels would be numbered 1 and 2 for left and right respectively.

screenshot_366

In normal use, you would have a single background patcher open all the time containing the desired PolyGenericTwoChannelVSTController objects (producing your audio inputs) along with the PolyFromStereoVirtualOutput objects connected to their corresponding gain objects (producing your outputs). Then, for each desired song, you would only need to load the patcher containing your desired routing.

So how do you load a VST?

Fortunately, another object to the rescue, the VSTPolySynthManager.

screenshot_371

These objects are used to control what VST gets loaded into particular instances. In this case, we’re loading the Native Instruments FM8 plugin into both instances. Banging the rightmost port opens the GUI editor for the loaded VST. The two middle ports are used to load and save respectively the edited settings of a VST.

These objects work flawlessly under Max 5.1.9. Unfortunately, Max 6.1.7 crashes from time to time when I use these objects. I have not been able to find reproducible cases and I’m hoping that the MaxMSP community will be interested in trying out these objects and helping to track down what seem to be rather obscure VST~ related problems in Max 6.

 

Leave a Reply

Your email address will not be published. Required fields are marked *