While there are many methods to move MIDI and audio data between programs on a computer, ReWire (developed by Propellerheads
) has become the most popular system. It allows a fairly seamless integration of client and host applications, and is also well supported by most major DAW applications.
Tutorials in this series:
In this tutorial, we will show connections to two major software packages: Ableton Live and Digital Performer. However, if you use a different application, you should check the documentation to learn more about its ReWire implementation. In most cases, the process is the same:
- You set up Max/MSP to speak to ReWire.
- You start your host application.
- You create a channel in the host to accept Max/MSP input.
- You create (or load) a Max/MSP patch and turn on the DSP output.
In order to allow Max/MSP to speak to your ReWire host, you have to use a special output driver named ad_rewire. This output driver provides a connection to the host for routing audio, MIDI and timing information between the client (Max/MSP) and the host (your DAW application). You select this driver in the DSP Status dialog (available from the Options menu). When selected, you are also given the option to select the number of virtual MIDI ports that will be exposed by the ReWire interface. In this case, we will leave the number of ports set to "1".
In order to create a simple test patch for our ReWire connection, I've created the most simple audio patch possible: a cycle~ object connected to an ezdac~ object. Since I will want to control the volume in my host application, I've avoided adding any other controls to this simple patch. Once created and locked, I can click on the output object to begin audio generation.
Within Ableton Live, I need to set a channel that will receive the ReWire audio input sent from my Max patch. Selecting an audio channel, I've changed the "Audio From" menu to select MaxMSP, and verified that I am using the first two outputs (the default output of the ezdac~ object). Now, if I change the Monitor setting from Auto to In, I can see the level meters light up, and will hear a 74 Hz tone coming through Live's audio output.
Connecting a Max/MSP patch into Digital Performer is equally simple. Since Max (and my patch) is already operating as a ReWire client, there is no need to change anything there. I start DP and change to the Mixer view of my project, then create a new Aux channel – making sure it is routed to an appropriate audio output. I then select MaxMSP 1-2 from the "New Stereo Bundle" list to complete the setup. If I start the output of the patch, I will see that the audio is routed into the Digital Performer channel, and I can change volume, pan or add effects.
While it is nice that we can get audio from Max/MSP into our host application, anything beyond the most basic patch will need to get some information from the host – particularly timing and transport information. This is one of the powerful features of ReWire: it not only pipes audio, but also provides the necessary data to create host-aware patches. In order to access this data within Max/MSP, we need to learn about the hostsync~ object.
The help patch for hostsync~ is very informative; it shows the object retrieving the transport status, current time, current "musical" settings (like time signature and tempo) and even the current loop settings. This is most of the information necessary to make a custom patch interact with the host in a more predictable way.
You have probably noticed that there is a metro connected to the input of the hostsync~ object. Why? Because data streaming in from a ReWire connection happens very fast, and using this data would, in most cases, require more conversion than necessary. By having all of the output as standard Max data types (integers, floats and lists) and using an input bang to "sample" the high-speed datastream, we can reduce the amount of conversion necessary to make use of the output data.
Using the hostsync~.help patch, then running it while connected to our host, we can see the interaction between the host program and a Max patch.
Each time metro generates a bang message, hostsync~ reports the current state to the connected display objects. The next step is to use this information to create a host-aware patch.
To create this patch, I'm going to use a subset of the hostsync~ data: specifically, I'm going to use the beat output to trigger random frequency settings, and the bar output to trigger random filter changes. It's a simple patch, but you should be able to see some of the possibilities when using the hostsync~ object.
The output of the bar and beat outlets are used to drive two random objects, scaled to an easily audible note range, changed into frequencies (using the mtof function) then routed to audio objects. If you turn on the ezdac~ and metro objects, then start the transport of your ReWire host, you will hear the output of the patch match the timing of the host.
This patch could easily be improved by turning off the output when the transport is stopped (by using the transport state outlet to control the ezdac~ object), or by speeding up the output (using the fraction beat outlet). But this patch is a good example of using the host information for musical/compositional purposes.
While the output of the hostsync~ object can be useful, sometimes you need a faster or more precise output. This is the domain of an object named hostphasor~, which provides a synchronized phasor-like output tied to the host transport. Altering the above patch to use hostphasor~ (in this case, for filter cutoff animation) is fairly simple:
Since the one-cycle-per-quarter-note movement of the filter may not be to your liking, you may want to use the rate~ object to speed up or slow down the movement of the waveform, or even use the hostphasor~ output to drive a different waveform (using it as a phase driver, rather than a direct output).
In this case, we've used the hostphasor~ object to drive a triangle~ object (tweaked to our liking), at a rate 16x slower than the typical beat cycle. We've also scaled the output to 0-8000 Hz, giving us a basic filter sweep that occurs in time with the host's timing.
At this point, you are probably getting a little tired of the random note generation, and would like to control the notes from a MIDI channel in the DAW. You might also like to make the sound of the oscillator a little more interesting, so we will use frequency modulation (FM) to make the sound more complex. These two changes will make up the last patch of this tutorial.
In order to create and access incoming MIDI, we need to start at our host. Create a MIDI channel with some notes in it, and route the output to the Max/MSP ReWire MIDI output. In Ableton Live, this means selecting the "MaxMSP" MIDI output (not the "to MaxMSP" outputs!). You will see that the port changes to "ReWire 1", indicating that the first (and only) ReWire MIDI channel will be used for output.
Within our patch, we need to disconnect the random system from controlling the saw~ object, and use the output of the notein object instead. In order to choose the MIDI port, we use the common "midiinfo-to-menu" selection objects that you will see in most MIDI-based patches. We follow it up with a stripnote object (to remove the note-off messages), and route the note number through an mtof object to control the sawtooth waveform frequency.
To make the patch more interesting (and to use that forlorn hostsync~ object), we will extend the patch to use the "fractional position" output of hostsync~ to drive a second oscillator, and have it frequency modulate the main oscillator. The output of hostsync~ is scaled (to +/- 4.0), then combined with the note value to create a fractional note value that is constantly changing. This value drives a cycle~ object, which in turn is scaled and used to drive the sawtooth oscillator. Initially, there won't be any difference in the sound, but if you increase the "FM Depth" number box (especially past a value of .25), you will hear the sound become more uncontrolled and harsh. Large setting will drastically change the timbre and perceived pitch of the base notes.
Finally, in order to make it even less irritating, we can set up the velocity part of the note message to trigger a line~ object, which in turn closes down the output when no MIDI messages are being received. This prevents the patch from squawking when the ReWire transport is turned off.
In this article, we've created a ReWire connection to a host, and used the hostsync~, hostphasor~ and ReWire MIDI connection to create a Max/MSP patch that is controlled by the host. There are many ways you could extend this patch: you could add a synchronized sequencer for the note or filter settings, use the hostphasor~ for adding LFO-like modulations or add time-sync effects. One of the great side effects of the ReWire interface is the ease of creating patches that are responsive to the host environment.
In our next ReWire tutorial, we will look at having Max/MSP be the ReWire host, and using the rewire~ object to create a connection to several commercial ReWire clients. But until then, patch up a storm!