In the ReWire Essentials tutorials (linked at the bottom), we used Max as both a mixer (hosting application) and "device" (controlled application). These are the two sides of the ReWire connectivity equation, and Max can work equally in both modes. In order to dive into ReWire at a deeper level, let's look at a connection to one of the most-used ReWire packages there is: Propellerheads Reason.
In order to have the most fun with our Max/Reason combination, we are going to do some sequencing and audio processing in Max, and use Reason as a synth/sampling and mixing device. What we *won't* do is run the Reason sequencer or use its recording capabilities. In this way, we'll get to do goofy and interesting Max sequencing and processing (something Max is really good at...), and let Reason handle the synthesis (something Reason is damned good at).
Let's start by creating a very basic connection between Max and Reason. Here's the patch that I created:
Unlike what you see in most of the ReWire help files, I'm using the rewire~ object with a named device. This allows me to state explicitly that this is a connection to Reason, and I don't have to mess around with application selection or other confusing UI elements. I connect the outputs of the rewire~ object to an audio chain (live.gain and ezdac~), and I create two message for the input: "openpanel" and "closepanel".
Different ReWire clients work differently, and even the same application not work the same on Windows vs. Mac. In my case (Max OS X, Reason 6.5), clicking on the "openpanel" message will actually launch the Reason application in ReWire client mode, and will be completely active with no other interaction. If I create a Reason instrument (Kong, in this case), I can play that instrument and receive the audio within my Max patch.
The next thing we want to do is to fire notes into the Kong instrument using MIDI messages from Max. To do this, we have to send a specially formatted message into the rewire~ object. The format of the message is:
midi <timestamp> <bus number> <MIDI message> <note value> <velocity value>
Since we don't care about sequence timing or routing, our timestamp and bus number are always 0. Since we are sending notes, our MIDI message is always 144. The note number and velocity information is created by a makenote object, which will take our incoming note information and turn in to MIDI note pairs (noteon and noteoff messages).
The basic note-playing patch will look something like this:
In order to virtually "play" any of the Kong's pads, just click on one of the message boxes (numbered 1-16).
The next step is to create some way to do an interesting sequencing system in Max. Let's start by making a simple drum matrix sequencer that is run off the transport:
In this case, we have a transport-based timing system that uses a counter to output a step position. This goes into a live.grid object (set to matrix mode), then the output is split apart and sent to our input keys. These keys are used to send the MIDI messages from the previous patch to the Kong drum machine. This creates a basic grid-style drum sequencer that can play back Kong without having to mess around with pad programming.
But why program the grid at all. By watching for the first step of the sequence and randomizing the grid, we can have Max do the hard work for us! In this updated patch, I have a compound message that is activated whenever the first step is seen:
At that first step, the message will clear and randomly place one note in each column. But I also want a four-on-the-floor kick drum, so I'm using the setcell message to force the kick to fire on every downbeat. While this is really simple generative stuff, it also is surprisingly good-sounding. In fact, some of the patterns are so good that I don't want an immediate change to the next pattern, so I placed a switch at the output of the generator to allow me to "hold" a pattern until I'm sick of it.
Here it is as a copy-compressed patch:
Jumping back to Reason, I've now added a second instrument: a SubTractor analog-ish synth. When you create a new instrument, it makes a new track in the sequencing area of application:
If you start our grid-based sequencer, you will hear that the MIDI stream is not routed; rather, the MIDI input is used by whichever track is currently selected. This isn't optimal, so we want to find a way to force our sequence to be routed to a chosen instrument. Performing this sort of routing magic will require two things: MIDI routing setup within Reason, and manipulation of the midi message that we are sending to the rewire~ object.
Let's start with the Reason MIDI routing setup. If we go to the top of our instrument rack, our basic Hardware Interface display doesn't even have anything related to MIDI showing. Clicking on the Advanced MIDI will reveal a MIDI router, which is where we do our dirty work.
In this case, the MIDI Interface shows "No MIDI Input" (because I didn't set it up in Reason's preferences), but that doesn't matter - we will access these devices directly. For the first channel, we set the MIDI routing to the Kong 1 Input; for the second channel, we set the MIDI routing to the SubTractor 1 In (make sure you are selecting the In option as opposed to the Mixer connection). Now, within Max, if we can access the MIDI Bus A device, we should be able to send MIDI to the individual devices - either individually or simultaneously.
Next up is the changes to our Max patch. We need to change the contents of our midi message to route the message to the correct MIDI channel of Reason's interface device. Luckily, the changes are pretty simple using a few extra inputs and some message formatting.
We now use the bus number value of the midi message to choose a MIDI bus: #1 is Bus A (in the Reason Advanced MIDI interface), #2 is Bus B, #3 is Bus C and #4 is Bus D. We also have to adjust the MIDI channel by changing the message number (144 in the earlier example) to the range from 144-159; we do this using a "+ 143" after a channel input to set the channel number. Now, if we select a device number of 1 and switch between midi channels 1 and 2, we can switch the MIDI output between the Kong and SubTractor devices.
Here's the updated version of the patch:
At this point, we can directly access individual Reason devices, so we probably want to have sequencers for each device that match their capabilities. The grid device that we created is perfect for a percussion synth (like Kong), but doesn't really work that well with a standard synthesizer like Subtractor. In order to deal with this, let's reformat our patch a little (in fact, we'll hide some of it inside of an encapsulation to free up some on-screen room), and create a second sequencer that will produce basslines suitable for Subtractor.
You will notice quite a few changes in this patch. First, we've hidden much of our logic within subpatchers (named timing-and-randomize and different-timing-and-randomize) to free up a little space. Since the two sequencers are of different types (live.grid and live.step), we need somewhat different timer/randomizer functions, so peering inside these subpatchers might be useful as you create your own, personalized version of this patch. The other place where we've tucked in some interesting logic is in the formatter subpatchers. Here is where we format the MIDI messages that properly route the data to the correct devices. It is important that you either make this logic very flexible, or you make sure you are always using the same Reason setup, since the MIDI message formatting is specific to the Advanced MIDI setting of the Reason device set that you use.
As cool as it is to generatively fire off notes to Reason, we can take Reason even farther if we can automate the parameters of our Reason devices. Not surprisingly, this can also be accomplished by sending MIDI messages (in this case, MIDI CC messages), but we need to know which MIDI controller messages to use, and we need to properly format the messages for the ReWire connection. This first part of this is provided by our friends at Propellerheads; the Reason 6.5 MIDI Implementation Chart gives us MIDI CC mappings for virtually every knob, slider and switch of the devices available. We will be referring to this manual extensively in the next section, so it is probably wise to download it now...
Our next addition to the patch is to create a parameter animator. The easiest thing to do - and to hear - is to manipulate the filter. With a few simple additions, we can get an animator that randomly changes the filter 1 cutoff and resonance of the SubTractor synth in time with the rest of the piece. The animator looks like this:
Here we have to use the raw MIDI CC message type (which starts at 176 for channel 1, and here is set to 177 for channel 2), along with the controller number and the value. The value is coming from the random objects, and the controller number is straight out of the MIDI Implementation Chart. This gives us the following patch:
At this point, we've created a pair of unique sequencers and a pair of random number generators, and have them use the rewire~ object to control a pair of devices within Reason. Unfortunately, that's not really why we would want to use ReWire; this same functionality could be accomplished by sending MIDI data through Max's Virtual MIDI ports, and wouldn't require ReWire at all. Where rewire~ becomes necessary is when we want to get the audio out of the devices and further manipulate it within Max - allowing us to hand-roll our own audio processing to create sonic mayhem that couldn't be done within Reason itself. Let's use the audio outputs of the rewire~ object to further mess with our sounds, and see what we can do!
We have to start off by changing the patch cord wiring of our Reason Device Rack. Basically, we are going to bypass the built-in mixer, and route the outputs of our devices directly to audio outputs of the Interface. This will allow us to treat the audio of each of the synthesizers separately within our Max patch. (Note: In order to make the back panel more clear, I've removed all of the cables connecting the default effects processors.)
Now, instead of mixing the device outputs in Reason, they are available to the ReWire host: Channels 1 and 2 will be the stereo output of Kong, and channel 3 will be the mono output of the Subtractor synth. Now, let's jump back to the Max patch to subject these channels to some MSP mayhem.
Gaining access to the new channels is pretty simple: we just change the number of channels in the rewire~ object to 3 (to match the outputs of Reason that we are going to use), then use live.gain objects to create a mix of the two devices for our output. The next stop is to create a few idiosyncratic effects processors for the out-bound audio.
There are many kinds of effects available using Max; in this case, we are going to allow the drums to pass through unchanged, but apply a "chopper" effect to the SubTractor line that is in sync with the main tempo. Since all of this information lives within the Max patch, it is easy for us to use tempo, subdivision and content cues from our Max-based objects.
This is a work in progress...