Artist and educator Chris Coleman is recognized in the Max community for his work on Maxuino, a Max interface to the popular Arduino microcontroller board. When I spoke with him, Chris also discussed his early sculpture work, teaching, collaborations, and how Max/MSP and Arduino fit into the evolving landscape of electronic media tools and practices.
A simple truth emerges from the practice of writing Max patches like the Max for Live device we’ve been working on: The trajectory of “finishing” your Max patch is something you approach on an asymptotic curve – you approach being “done,” but never quite reach it. This tutorial is an attempt to honor that curve of near-completion.
There’s always something new or something more you can add. It seems as though the difference between patches in this regard is how long you work with something before you decide to make the change. I’ve used the same basic approach to performing and improvising for a number of years now in the patch that I use, but the actual insides of the patch itself are very different with what I started with when I thought my performance patch was “done.” It changed in tiny increments very slowly over a long period of time – I’d make a change, go do a few gigs or some recordings with it, and slowly decide whether my great improvement really was great or really was an improvement.
Download the patches used in this tutorial.
Writing tutorials like this series hides that process in two ways. First, since you’re looking over my shoulder while I do the patching instead of approaching the problem solving yourself, you’re only seeing the end product. Second, the sequence of tutorials has more to do with grouping ideas pedagogically rather than replaying the sequence in which I would actually have developed a patch.
With luck, I’ve finished my tutorials without having made some specific change you might have in mind, which might give you the motivation to leave behind a life of passive Maxing to add the thing(s) you care about.
This time out, I’m going to focus on adding a few new features to the waveplayah Max for Live device I ported in the previous tutorial. I’m also going to focus a little bit on trying to update the patch in ways that might be more generally useful for your own Max programming rather than being mere tweaks to a single Max for Live device. Okay, let’s begin.
The waveplayah.amxd Max for Live device allows you to create Live presets in the same way as you do with any other Instrument, Audio or MIDI effects device; you set your parameters and save the patch with a new name. The Live application also includes the hot swap feature that makes it a breeze to switch presets while you’re working. In this tutorial, I’m going to show you another way to create and save parameter values in a Max for Live device by using the pattr family of Max objects.
For reasons I don’t entirely understand, many Max users would rather mess about with the Max preset object rather than take the plunge into using the robust and insanely useful pattr family of objects. One possible reason for this (besides simple risk aversion) seems to be that people think that pattr is hard to learn and use. While I showed you just how easy it is to pattrise your Max patch in the first tutorial in this series, let’s assume that you’re a Max for Live user who hasn’t read back that far and take another look….
In fact, we have already done almost all of the work to use pattr with the waveplayah device in the previous tutorial when we used Max’s Parameters Window to set all the UI objects in our patch as part of the process of porting it for use in Max for Live. One of the things we did was to give each UI object in our patch a “Scripting Name” which we linked to the “Long Name” of the object. We did this so that it would be easy to identify a particular UI object whenever we want to add automation to a parameter.
Doing that work last time out makes pattrising this Max for Live device a snap (giving your parameters names is really the only time-consuming part of adding pattr functionality)
That’s it. We’re done. No, really.
If you’d like to see what adding the pattrstorage and autopattr objects has done, hold down the command (Macintosh) or the control (Windows) key and double-click on the pattrstorage object. The pattr Client objects window will appear and show you all of the parameters of your Max for Live device that are registered and whose values will be stored. Neat trick, eh?
We can now store values for all of the parameters in our device by sending the message store [number] to the pattrstorage object, and recall patches by sending the message recall [number] to the object. But I’m going to add a nice visual interface for saving and recalling presets while I’m at it.
You’re done – the preset object now talks directly to the pattrstorage object, and clicking or shift-clicking on the preset object’s dots will recall and store presets (you will want to add your preset object to the Presentation layer and decide where to put it in your user interface, of course).
There’s an interesting and subtle feature of Max for Live that you may not have noticed yet – when you change the skin of the Live application (using the Look/Feel tab in the Live application’s Preferences menu) Max for Live automatically adjusts the colors of all Live user interface objects to match the Live application’s new color scheme.
Give it a try – close the waveplayah device’s edit window, open Live’s Preferences window, choose the Look/Feel tab, and change the skin using the pull down menu. Cool, huh?
There’s only one problem with our waveplayah device – the non-Max for Live user interface objects (the rslider objects and the multislider object we’re using for our visual display) stay the way they are regardless of the skin we choose. Unlike the Max for Live UI objects, they don’t automatically adapt. We’re going to add some patching to our device that will let us automatically change those colors, too.
The color schemes you see when you use any Max UI object are attributes of the object. You can see what they are by using the object’s Inspector, and you can use messages to Max objects to change how any object is displayed.
Max for Live includes a special object called live.colors that you can use to find out what the current color scheme associated with a Live skin is, and you can use standard Max patching techniques to set the colors of the rslider and multislider objects.
Here’s how it works. Each Live skin includes a set of color tags used to identify how some part of the Live UI looks – the color used for backgrounds, text, the color that is used when a UI element is selected, and so on. The live.colors object lets you use Max messages to ask about what color is used for any of these tags, and you can take that information and format it for use as a regular Max message that changes the color of a regular Max UI object.
So what are the names of these Live color tags used when skinning the application? There’s a helpful example that will show you the names and current color values of all of the different colors that make up a Live skin in the help file for the live.colors object (click on the message box containing the word everything, then double-click on the “View.All” subpatch to open it and show you the colors and tag names).

Likewise, we can use Max’s object Inspector to find out the names of each attribute that correspond to the current color of the UI object by selecting the object, slicking on the Inpsector icon in the Patcher Window toolbar, and then scrolling down to see the color attributes. To see the attribute names associated with the color attributes, just click on the Show Attribute Names icon in the Inspector window toolbar. Here’s an example that lists the attribute names and colors for the rslider object:

We now have a list of color tags for the Live skin, and another list of attribute names for the rslider object. How can we use the live.colors object to automatically set the color of an rslider object in our Max for Live device?
The live.colors object will take the name of a color tag as a message in its inlet and output a list of the four RGBA color values as a list of four floating point numbers, preceded by the name of the color tag we asked for. From there, it would be a simple matter to use dollar-sign style Max messages to strip off the name of the color tag and format a message we can send to an rslider object:

But we’re going to be making several different queries – it would be nice to have a little more efficient way to get what we want. So let’s consider how we might make things a little easier.
To set everything up, all we need to do is to decide on the color tags we want to use and the attribute names of the rslider and multislider objects we want to change. The fact that the live.colors object starts its output list with the name of the color tag we asked for means we can use the Max route object to route its output to a different output for each different request. That means we only need one live.colors object to do everything for us. And since the route object strips off the first item of its input list, the route object will spit out a nice four number list ready to go – all we need to do is use the append object to attach the name of the UI object attribute whose color we want to change.
The version of the waveplayah device file included with this tutorial contains a simple subpatch called “skinner_box” that checks for the current Skin colors whenever you add the device to your Live session and uses that information to change the color scheme for the rslider and multislider objects. A little investigation of the subpatcher will show you another neat trick that allows you to update the colors whenever you load a new skin.

In the original version of the waveplayah patch, I had decided on a really simple UI for loading files – the inclusion of a button that initiated a file load via the Max filedialog object. It was quick and easy and it worked like a charm, but I kept thinking that I’d like to have a nice drag and drop interface that would let me grab AIFF and WAV files from the Live file browser. Although I don’t really use MP3 files very much (They don’t sound as good as AIFF/WAV files and they don’t use less memory since the file format is converted on import), I thought it would be nice to have the option of using them. That’s a little bit of a problem, however – the message that loads AIFF and WAV files (replace) isn’t the same message you use to load MP3s into a buffer (import) – I’d have to have a way to figure out what kind of file I have and load it accordingly.
I was sitting and staring at my list of imagined features when it suddenly hit me – My pal and colleague Darwin Grosse’s insanely great Loop Shifter MIDI instrument that comes with Max for Live had a drag and drop interface already in it!
And, of course, that patch had an edit button. So I decided to give Darwin’s patch a look to see if I could borrow and modify it. I loaded the Loop Shifter MIDI instrument and hit the edit button, and toggled from Presentation to Patching mode in the toolbar to see the insides of the patch.
It wasn’t too difficult to locate the part of Darwin’s patch that seemed to be doing the heavy lifting – a subpatch called file selector. Here it is:

I started as I usually do – by looking at what’s connected to the inputs and outputs of the subpatcher itself (what messages does the subpatch get and from where? What comes out of the outlets of the subpatch?). I tried the message box containing the word “open” and watched what happened, and looked at what Max objects were connected to the inlets and outlets.
In this case, I had what looked like two ways to specify the patch to be loaded – the message box and the live.drop object connected to the right inlet of the file_selector subpatch. The four outputs were less obvious, so I thought I could figure out some of it by double-clicking on the file_selector subpatch to open it and look at its contents.
Technical digression: Along with a number of other people, I suggest again and again to new Max for Live users that they begin by doing the beginning Max tutorials. Although opening and messing with Max patches is easy and fun, there is simply no substitute for having a good working knowledge of how a Max patch works – objects, messages, and the order and way that data flows through a patch. And there’s no other place where that knowledge is more crucial than when you start porting someone else’s patch knowing the basics makes all the difference. Really.
Don’t get me wrong here – the way Darwin’s subpatch worked wasn’t immediately obvious to me, either. So I did what I always do – I try to straighten the patch a bit and work out what’s going on by paying attention to the way messages travel through the patch. That particular bit of quality time included the liberal use of message box objects that let me see what the message coming from an object or subpatcher looked like

along some judicious use of the trusty Max Clue Window to help me quickly read through the refpage documentation (choose Clue Window from the Window menu to show the Clue Window if it’s not already visible, then hold down the Shift key and mouse over the inlet of an object to display a complete listing of all the various kinds of messages and attributes for the object. When you roll your cursor over any of the listed messages or attributes, you’ll see the description of the message or attribute from the object’s refpage displayed in the Clue Window).

After that quality time, I’d figured out a few useful things:
Technical digression: If you want to slow the transition between patching and presentation down, choose Patcher Inspector from the View menu to see the Patcher Inspector, double click in the Value column for the Box Animate Time attribute, and type in a high number (like 2000).
There was also some stuff in Darwin’s patch I didn’t need or wanted to change.
Armed with this knowledge, I poured myself a nice glass of chilled Rosato and got to work on some remodeling – removing and moving things around, renaming the subpatches with names I’d be more likely to remember, and loading the patch with comments to help me remember what a patch was doing.
After I was all done, the patch I’d copied out from Darwin’s instrument looked like this:

I had a nice drag and drop interface that collapsed in Presentation mode into a simple and clearly labeled file box that displayed instructions, file names (when loaded), and error messages, too:

At this point, you’re probably thinking the same thing that occurred to me – that I would probably be using something like this pretty regularly for creating audio effects and Instruments. This bit of patchery is a prime candidate for what we call a clipping in Max. A clipping is a snippet of a Max patch you can save in a certain place and simply paste into another Max patch with the touch of a key and a click.
Creating a clipping is easy. Choose Save As… from the File menu and save the patch to the clippings folder inside the patches folder inside your Max application folder.
Once you’ve saved your clipping, you can add it to any Max patch by control-clicking (Mac) or right-clicking (Windows) in any blank space in an open Patcher window to show the patcher contextual menu. You then choose your clipping from the Paste From submenu, and the patch will be pasted into your patcher window, ready to use.
Things are looking pretty cool now. Am I done?
Don’t be silly. I’m done for now.
And there’s one thing I haven’t mentioned. Once I placed my drag and drop interfaces on the front panel and made room for a preset object, it occurred to me that maybe I might do better with my user interface if all three LFOs were arranged horizontally with their corresponding parameters grouped vertically. The Max for Live audio device included with this tutorial reflects all of those changes. Give it a try, and see if you can think up a few modifications of your own. That should give you some things to do and think about…
…for now, anyway..
One of the most feared and respected objects in the Jitter collection, jit.expr arrived on the scene as part of Jitter 1.5. In some circles, there is a belief that harnessing its power will bring you great powers and enable you to achieve untold wonders.
The fact is, jit.expr is a really amazing tool, but unfortunately many users are intimidated by the syntax, which includes a lot of square brackets, parentheses, and special variables. While these sorts of things are common for programmers, they can seem very esoteric and strange to many Max users. Many avid readers of the Jitter Recipes got stuck when jit.expr was used to generate the quads in the TinyVideo and Shatter recipes. Upon getting familiar with the expressions, however, it will become an extremely handy tool that makes seemingly difficult and complicated tasks much simpler. Through this article, I hope to demystify this elusive object and help you to achieve the wonders that you are dreaming of. We’ll start by covering the basic elements of jit.expr expressions and then use these to create some basic geometry and image masks.
Download the patches used in this tutorial.
The jit.expr object doesn’t do much out of the box. In order for it to output anything more than black pixels, you’ll have to give it an expression to work with, using the ‘expr’ attribute. The expressions work in a similar fashion to jit.op where you are performing some arithmetic on each cell of the incoming matrix. If you’d like to just pass through the input from the first inlet of the object, you can type ‘@expr in[0]‘. The in[0] variable stands for the pixel value from the first inlet. The second inlet would be in[1], and if you have more inlets, they are numbered sequentially (in[2],in[3],etc.). If you’d like to add two jit.matrix inputs together (similar to jit.op @op +), you can use ‘@expr in[0]+in[1]‘. Still with me? This is where it starts getting fun.
In addition to accessing specific inputs, the ‘in’ variable also allows you to access a specific plane of the incoming matrix in your expression by using ‘.p’. For example, if you use ‘@expr in[0].p[0]‘, that gives you the first plane of the first input. To get the second plane, you could write ‘@expr in[0].p[1]‘ or ‘@expr in[1].p[2]‘ to get the third plane of the right input matrix. So, if we use ‘@expr in[0].p[1]*in[1].p[2]+in[1].p[0]‘ we would be multiplying the second plane of the first inlet with the third plane of the second inlet, and then adding the first plane of the second inlet. That was quite a mouthful, but hopefully you get the point. This can be really useful when you have an expression that requires multiple variables, and can take the place of using jit.unpack/pack in some cases.
On a related note, you can also create a unique expression for each plane of the output matrix by simply passing a list of expressions to the ‘expr’ attribute. Each expression is passed in as a symbol, so it is often beneficial to put quotes around your expressions, especially if it includes spaces. For the most simple case, we could type ‘@expr in[0].p[0] in[0].p[1] in[0].p[2]‘, which will just pass the appropriate planes from the first inlet. It’s a lot of typing for something so simple, but we’ll be making a lot of use of this feature later, so keep it in mind. It’s especially useful when generating geometry, since you will often need to use different equations for the x,y, and z values.
When generating geometry or image masks, you will often need to generate a whole matrix full of values based on an equation. For the simple cases, you could probably use an object like jit.gencoord to generate unique values for each cell of your matrix. One of the great features of jit.expr is the ability to generate cell values by working with the norm[],snorm[],cell[], and dim[] variables. Which one you use will depend on what you are trying to accomplish.
These variables each require you to specify which dimension you would like to generate values across (horizontal=0,vertical=1,etc.) between the square brackets. The dim[] variable simply passes the size of your matrix across the specified dimension. This will be the same for all of the cells of the matrix, and is useful for situations where you would like to adjust values in proportion to the size of the incoming matrix.

The simplest of the other three variables is cell[]. This variable generates integer coordinates across the specified dimension. So, if we have ‘@expr cell[0] cell[1]‘, the first plane of the matrix would have values {0.,1.,2.,3.,…} across the horizontal dimension (starting on the left) and the second plane would have values {0.,1.,2.,3.,…} across the vertical dimension (starting from the top). While this might not be so useful as an actual output value, it makes certain things like modulo (%) expressions a lot easier to write when you are working with integers.
Note: You may have noticed the decimal point in all those values. This is to remind you that jit.expr uses floating-point arithmetic internally, and will convert to whatever data type you are using upon output.
Now that we know how to use cell[], norm[] is pretty simple. This handy variable outputs values between 0. and 1. across the specified dimension. Writing ‘@expr norm[0]‘ will generate the numbers {0.,…,1.} across the horizontal dimension, starting on the left. This also creates a nice horizontal linear gradient. This expression is the equivalent of ‘@expr cell[0]/dim[0]‘ but requires much less typing. Our final variable, snorm[] is very similar to norm[], but with the numbers stretched out to cover values between -1. and 1. This is especially useful when generating vertex values for OpenGL geometry.
In working with imagery, it is often necessary to do things like generating an oval mask for an image, or other shapes that allow you to escape the oppression of rectangles. Now that we’ve gone through how to use the built-in variables and put together simple expressions, we’ll use them to create a few different simple mask shapes. To start, let’s try creating a simple oval mask.
Now, in order to create an oval mask shape, we’ll need a way to generate values that radiate out from the center of the matrix, rather than just generating linear values. To do this, we can use the hypot() function built into jit.expr, which calculates the length of the hypotenuse of a right triangle, often used as a distance equation for two points. If we use @expr hypot(snorm[0]\,snorm[1]), we’ll get values that increase as they get further from the center. Remember that snorm[] creates values between -1. and 1. so the center cell will be 0. So, we’re getting close, but we have the opposite of what we really want (although an inverted oval mask can be pretty useful too). To invert the values, all we have to do is alter our expression slightly: @expr 1.-hypot(snorm[0]\,snorm[1]). Now we have a nice radial gradient. Now, you might notice the “\” in that expression. That’s there because Max likes to interpret commas in a special way, and we need to include the comma as part of the expression. The backslash prevents the comma from getting eaten up by Max. Suppose we would rather have a hard-edged mask instead of a soft gradient. We could easily add a threshold value by altering our expression again: @expr (1.-hypot(snorm[0]\,snorm[1]))>in[1]. This little extra portion sets the output value to 1. if our expression result is greater than the value at the second inlet. The parentheses are there to enforce the appropriate order of operations.
We could now take this a step further and create other mask shapes based on simple geometry functions. The first one we will look at is using sin() to generate another gradient shape. If we use ‘sin(norm[0]*TWOPI)’ we will get a full-phase sine wave across the horizontal dimension. In this expression, we are using “TWOPI”, which is one of the built-in constants (2.*PI) for jit.expr, provided for our convenience. There is also PI,HALFPI, etc. Multiplying the “norm[0]” by an input value will change the frequency of the sine-wave, which can be useful for creating repeated shapes. We could then take this expression further by multiplying a horizontal sine gradient by a vertical sine gradient. Now, if we are using this to generate imagery or masks, the negative values aren’t going to do us much good. To invert the negative values, we can use the abs() operator (absolute value) on the result. Now we have a nice repeating lump gradient pattern.
By now you are probably noticing that these expressions can get pretty long and complicated with just a little tweaking. An important thing to remember is that jit.expr is an object like any other object, and there is no rule that you have to do all of your math within a single expression. In fact you will probably find situations where you need multiple jit.expr or jit.op objects to accomplish what you need.
As you are experimenting with jit.expr, you will probably want to have some sort of visual feedback to get a better sense of what is going on. For simple cases, jit.cellblock is a great solution, since it allows you to peek at the number values of the output matrix. You can also visualize your jit.expr output using a jit.window which will represent the values as color intensities. Often times this gives the most intuitive feedback. Another way that jit.expr really shines though is in generating 3D geometry that can be visualized using jit.gl.mesh. Without going into too much detail, jit.gl.mesh allows you to create different sorts of 3D forms by passing in a Jitter Matrix. The matrix is then translated in different ways depending on the chosen “draw_mode”. By experimenting with different modes, you can visualize your jit.expr expressions in different ways. And once you get comfortable with the different modes, you can start creating expressions specific to the draw_mode you would like to use. Remember that jit.gl.mesh expects a 3 plane (x,y,z), float32 matrix for the vertex input, so you will need to think about how you would like to generate positions for each of the coordinates. If you would like to apply a texture to your 3D shapes, you will also need to generate texture coordinates for each cell (2 plane float32, 2nd inlet).

A very simple thing, which is very useful in real life, is to create a simple textured plane (similar to jit.gl.videoplane). To do this we can use a 5 plane float32 matrix, and use the following list of expressions in jit.expr: snorm[0] -snorm[1] 0. norm[0] norm[1]. If we break it down, we are just creating a simple grid for the x and y values by using snorm[]. You may have noticed that we left the third expression as “0.” Since we are creating a flat plane, we can just zero out the z values. For texture coordinates, jit.gl.mesh expects values between 0 and 1., so we are just generating a grid of coordinates using norm[]. Simple, right. Now, I’ll leave it up to you to imagine different sorts of equations that might provide more exciting results. You might need to brush up on your trigonometry, or if you are like me, fake it. I’m including a patch called simple-shapes that demonstrates a couple of simple and potentially useful shapes using the tri_grid draw_mode.
I hope this is enough of a boost to get you started writing your own expressions with jit.expr. In future articles, we’ll look at some of the more advanced features of jit.expr and ways to combine it with other Jitter objects to create unusual and wonderful results. With a little practice and study, you too can learn to tame this mysterious animal.
In this review, Nick Rothwell explains Max for Live in terms of what the addition of Max offers to Live users. He also shares his perspective on what Live offers to Max users, something that is less commonly discussed.
Since a lot of people are interested in what the process of porting a Max patch for use in Max for Live looks like, I thought I’d take this tutorial as an opportunity to go over the steps I used to take my waveplayah patch and to convert it to a Max for Live device waveplayah.amxd.
In my last LFO tutorial, I took the basic LFO module I’ve been working with in the previous tutorials, added some new extensions, and created a nice little patch called the waveplayah that used a summed set of the LFO modules to drive the playback of the contents of a buffer~. A good deal of my thinking about and creating it overlapped with the arrival of Max for Live – it’s where I got the idea for the different modulation styles I talked about in our last tutorial, after all.
Download the patches used in this tutorial.
Although every instance of porting a Max patch for use as a Max for Live device varies a little bit, here’s what the basic procedure looks like:
The first part of the patch to device conversion is simple copying and pasting. You’ll need to think of what kind of Max for Live device the patch you’re porting is going to be – an audio device, a MIDI instrument, or a MIDI effect device. Since our patch is going to become a Max for Live audio device, we start as we always do when creating Max for Live audio devices – by clicking on the Max Audio Effect icon in the Live browser and dragging it into the Effects rack on a Live track to create the familiar and popular starter patch, then clicking on the edit button in the device’s toolbar to launch the Max editor. We really don’t need anything else in the audio device starter patch except for the plugout~ object, so select and remove everything else, then move the lonely plugout~ object to the side for now.
Next, we’ll open the waveplayah.maxpat file from inside the Max editor as well. Choose Select All from the Edit menu, and then choose Copy to copy the contents of the patch to the clipboard. Go to the audio device starter patch and choose Paste from the Edit menu to copy the contents of the Max patch into the Live audio device patch. Before you forget, name and save your patch as waveplayah. Now, let’s get down to business.
The first and most obvious thing about converting a Max patch for use with Max for Live has to do with making the changes that will help the Max patch function most easily in the Live environment. That’s really composed of three different things:
Since the waveplayah patch loads a waveform into a buffer, we don’t really care about the audio input. This patch doesn’t need a plugin~ object at all, but we do need a way to load an audio file into our buffer. In this case, I’m going to keep it really simple and use a technique in the original patch that uses a button object to load an audio patch.
For output, we’ll use the plugout~ object from the audio device starter patch in place of the ezdac~ object in the original patch. And since we’re working in Max for Live, we also don’t need the transport object any more. When we use Max objects that support ITM (such as the phasor~ objects in our patch), the Live transport automatically becomes the transport that the patch uses. So we can remove the transport object, too.
In the Max world, that’s a nice advantage and not that big of a deal, but when we deal with Max for Live, things can get complicated. In the case of the waveplayah patch, the wave~ object plays back the file loaded into the buffer named source (since the wave~ object includes the name of the buffer as an argument). That means that any wave~ object in any Max for Live audio effect device that makes reference to a buffer named source will refer to that buffer. That could get awkward when you use the waveplayah device in more than one audio track in a Live session.
Happily, there’s a very simple change I can make to sort this out. In Max, whenever the name of a buffer~ or table or coll object begins with three dashes (—), the named object will be used only within that specific device. So in my waveplayah patch, all I really need to do is to change the name of the buffer I’m using from source to —source, and then make sure that the wave~ object references that new buffer name as an argument.
That’s really the part of the patch porting that takes most of the time, and I’ll describe that process in detail below.
The next task involves going through our patch and replacing every single Max user interface object with the Max for Live object that is its equivalent – every slider should be replaced by a live.slider object, and so on. We’re doing this because the Max for Live user interface objects have some special attributes that make assigning MIDI controllers and automating parameters much easier.
When converting large Max patches to Max for Live devices, I like to do this by adding a single Max for Live object to my patch, copying it to the clipboard, selecting every object I want to replace with that one and then choosing Paste Replace from the Edit menu (and then going through and filling in menus or tabs as needed). Your mileage may vary!
Technical detail: Although we aren’t doing it in this patch, you should keep in mind that the live.numbox object can be used to replace both floating point and integer number boxes in Max for Live. Since the Live application only works with integer values in the range 0 – 255, you should always replace integer number boxes with live.numbox objects whose Type attribute is set to Float and whose Unit Style attribute is set to Int.
There are a few rslider objects in my patch, and those objects don’t have a Max for Live equivalent. Since the range slider values can be set using the two number box objects to the left of each range slider, I decided that I didn’t need to worry about them and could leave them as is. Similarly, I really don’t care about the button objects I’m using to load audio or reset center and range values, either. But I did decide to replace the *~/number box stuff I was using to control output volume with a live.gain~ object.
Now that I’ve got all of my user interface objects swapped over to Max for Live objects, it’s time to do some housekeeping that’ll make our experience using the new device easier. Here’s what we need to do:
When you unlocked the original waveplayah Max patch, you probably noticed that a pair of objects – a loadbang object and a trigger (t) object – and a bunch of previously invisible patch cords suddenly appeared (If you’re wondering how that trick is done, you can Option-click (Macintosh) or Alt-click (Macintosh) and drag to select the objects and patch cords you want to hide or reveal and choose Hide on Lock from the Object menu. Any selected patch cords or objects will now be invisible when the Patcher window is locked. In the days before Max 5, that was how we initialized values in a patch). You can select the loadbang and trigger objects and just delete them. We’ve got a much nicer way to handle that now.
These tasks can be a little time-consuming in a patch that includes a lot of user interface objects, but Max for Live includes a new feature that makes the whole process a lot simpler – the Parameters window. The Parameters window provides you with a listing of all the relevant data about all the UI objects in your device in one place where you can view and edit them.
To view the Parameters window, choose Parameters from the View menu.
You’ll see a nice long list that includes every single Max for Live UI object in your patch. It will look a little scary at first, since every UI object is listed as something like live.slider[4] or live.numbox[14], but we’ll fix that in a minute.
The smart thing to do is to go through and give all the UI objects easily identifiable names so we can identify them if we want to automate a device parameter. But how do we know what’s what? Simple – click on the blue dot in the leftmost column in the Parameters window and watch your user patch – you’ll see the UI object turn a nice lime green.

To give the UI object a name (e.g. phase_1), double-click in the Name column in the Parameters window and type in a name. Then click in the Link checkbox to the left of the Name column to link this name to the Long Name attribute of the object (which is what Max for Live uses to identify parameter names for automation). Using the Parameters window, you can just go down the list and rename everything all at once.
You’ll also want to set each entry in the Parameters window to enable saving an initial value by clicking in the checkbox in the parameters column labeled “I” (initial value), and then double-click in the Initial Value column and type in a value (for menu items, use an integer and remember that the first menu item is 0). When you save and close your patch, all of your UI objects will be set to the initial values you type in.
Finally, you’ll want to set a modulation Range value for each parameter (the modulation ranges were what I described here, in case you’d like to refresh your memory). The Bipolar mode works well for nearly everything. In situations where you’re adding modes for things like toggle objects, you should choose Absolute.
Again, the great thing about using the Parameters window is that you do all the housekeeping in one place. Now that things are named and enabled, the only thing left to do is to arrange your interface.
The next thing we’ll need to do is to create the user interface for our device – to take all the parameters in the Max patch and arrange them within the Live audio rack space. Max 5 comes equipped with the tools to make this process easy – the Presentation Mode. When using the Presentation Mode, you select only those portions of your Max patch you make up the user interface and arrange them as you want without affecting the layout of the original patch.
To create the audio effect’s UI, all we have to do is to select those parts of the patch we want to have visible – number boxes, sliders, menus and labels – and choose Add to Presentation from the Object menu. When we do that, every item we’ve selected will display a pink Presentation mode halo. When we click on the Presentation mode icon in the Max patcher window toolbar, everything but the objects we’ve added to the Presentation layer will vanish, letting us arrange the UI objects for our effect in a way that is pleasing and makes sense. This is often the step in creating any Max patch that takes the most time and fine-tuning, but hey – it’s your interface, so take a little time to get it looking just the way you want.
While working on porting the waveplayah patch, I decided that it would be nice to have some kind of visual indication of what the waveform driving the wave~ object in my device looked like, so I made one small addition to the original waveplayah patch– a bit of patching that samples the waveform output and uses a multislider object with its Slider Style attribute set to Reverse Point Scroll to draw a nice moving graph.

Once the design is formalized, we’ll need to set the patch so that the Presentation layer is displayed by default. To do that, choose Patcher Inspector from the View menu and click in the checkbox marked Open in Presentation. When you save and close the patch, you’ll see your layout displayed in the effects rack (If you re-open your patch to edit it, you’ll need to click on the Presentation layer icon in the toolbar in order to display the rest of your patch).
If you want to share any Max for Live device you create with anyone else, you’ll want to freeze your device. Freezing is a way of preparing a device for distribution to other people by including all the files your device needs to work. That includes things like third-party Max external objects, subpatchers, audio files, image files, and Javascript code.
Note: If your device uses third-party objects that only run on Windows or Apple platforms, you can only share devices on that platform.
Max will analyze your patch to locate any files it needs – these files are called dependencies – and then combine these files with your device when you freeze it. Whenever you open a Max for Live device that’s frozen, the files inside that device will be used even if someone else using the device happens to have files with the same name on their system.
In the case of the waveplayah patch, this part of the job is simple – there aren’t any third party Max externals in my patch, I’m not using any abstractions that I’ve created for use elsewhere else, and I’m not using messages to add files (such as loading sound files or wavetables using the loadbang object) in my patch.
That’s not always the case, however – you might have forgotten what you put into your own patch at some point in the past, or you might be working with a patch that someone else made. So I still make it a practice to always to check for things I might need to include in my device as a matter of course.
With your patch open for editing, choose Dependencies from the View menu to display the dependencies window. In the case of the waveplayah patch, the window is reassuringly blank.
But suppose that my patch contained an abstraction I’d made previously (for those of you who are beginners, an abstraction is a Max patch that you can create and save and use in the same way you’d use a Max object in another patch. For more on this, see Max Tutorial 15). No one else but me would have that abstraction, and any audio device I made that used it would be broken for anyone I gave it to.
For example, let’s suppose that I have an abstraction called gt_bundle in my patch. If my patch includes that abstraction, here’s what we’d see in the dependencies window:

You’ll see that it’s listed as a patcher file. This means that when I freeze my audio device, the patcher file will be included. In any case where the Dependencies window shows me a file and lists its type as Missing, the file or objects would need to be manually included in the dependencies list (see the Sharing Devices vignette for more on this).
But the waveplayah file doesn’t have any problems at all, so we’re ready to freeze the device. To freeze the device, click on the Freeze icon in the Patcher Window toolbar.
That’s it. The next time you save your devices, any dependencies you have in your file will be included.
That’s the basic procedure for converting a Max patch to a Max for Live device. For your enjoyment, I’ve included an already-ported version of the waveplayah patch for your edification. But don’t be lazy – it would still be a good idea to try converting the patch and creating your own user interface yourself for practice. After that, there are a whole lot more cool Max patches floating around than there are Max for Live devices, so you know enough to start finding things that interest you in the Max forum and on the web and converting them for your own use.
In the next tutorial, we’ll discuss life in the “tweak loop” – that cycle of living with and improving your devices with things like presets, drag-and-drop interfaces, and the judicious application of color.
A while back, I wrote a series of four tutorials based around the idea of how you could generate and organize variety in Max patches. I wrote them first and foremost because that idea of generating and organizing variety by some means other than random numbers or noise sources has been an interest of mine for a long time. I thought it might be useful to show some examples of how one could make use of these basic techniques not just for generating raw material, but also for ways to transfer explicit control of a Max patch in live performance from the operator to some automated process (think of it as outsourcing) in ways that were less jarring than I often hear in live performance.
Download the patches used in this tutorial.
I guess people liked the tutorials, which is always flattering. The email that followed was a mix of praise (which I always enjoy), responses that ran the gamut from requests about what to write about next to full-on patch grovels, and even some complaints that I was “doing obvious stuff” (I sure hope that these ideas appear to be obvious, in retrospect – that’s how I know an idea is a good one). In the final tutorial, I’d made the specific decision not to provide any kind of prejudicial example of specific implementation, figuring that no one would be in a better position to imagine what might be done next than readers themselves.
For this tutorial, I’ve tried to address a variety of suggestions and feedback and to extend the ideas covered in parts one, two, three, and four of my humble set of LFO tutorials. This tutorial contains three parts:
Throughout the previous tutorials, I’ve been working with a simple single LFO module that included the ability to slave the LFO output to the Max transport, provided a number of different output waveforms, and also allowed for scaling the output waveform within the -1.0 – 1.0 waveform output range. That waveform is then sampled using the snapshot~ object and the output was used to control other parameters. Here’s what it looked like:

This tutorial uses a new variant of that basic single oscillator LFO with some added features. For the sake of functionality and readability, I’ve created subpatches that contain those new changes. Let’s look at those new features:
In our original LFO patch, the speed of the phasor~ object that generated waveforms was set using ITM-based note value settings to determine the rate. While that works just fine, I thought that I’d rather have a choice about whether or not to derive the speed of the phasor~ using Max 5 note values or to specify the phasor~ rate as a floating-point number that describes a frequency. The obvious reason for that is simple – I might someday want to use another LFO (or summed network of LFOs) to modulate the phasor~ rate. I realized that I could also consider the values stored in the umenu as representing a kind of synchronized sequence of frequencies that I could step through using some process (a counter? The contents of a coll object?). So it seemed like a good idea to build some flexibility into the LFO module here. I also realized in the course of patching that it’d be useful to know how the current tempo values represented by the ITM note values mapped to frequency in order to switch between time-synced to free phasor~ rates. So my new subpatch also includes some logic that will automatically set the frequency of the “free” oscillator to match the current value of the note value and the tempo I’m working with.
Let’s look at the inside of the subpatch.

The bulk of the patch is exactly what you’d expect: some logic to select whether you want note values or numerical frequencies using the selector~ object as a switch (and that second argument to the object sets the default behavior). But I’ve added another useful feature in the center of the patch – the translate object that automatically converts the current note value into an equivalent frequency value in Hertz. There’s some trigger-based logic added to the inlets to make sure that the calculation will be triggered whenever a new note value is chosen, and also to make sure that the frequency value is sent to the second phasor~ object before switching to it (think of the zl reg object as the symbol equivalent of a Max int or float object that stores a value and will output the most recently stored value when a bang is received in the left inlet), but the translate object is right in the heart of things. If you spend much time working with the new musical time features of Max 5, this object will become one of your best friends. It takes two arguments – one to specify the kind of value you want to translate and a second argument to specify what kind of values you want to end up with. In this case, we’re translating note values (notevalues) to frequency (hz).
Choosing between manual frequency values or note values is certainly useful, but there’s another reason for wanting to derive the frequency value that corresponds to a given note value. Although I’ve not done it in this patch, you could use that value to derive a subdivision of frequency for generating tuplets well outside of the triplets and dotted notes and intervals described by standard Max 5 note values. If you’re interested in doing it, I’ve already done most of the heavy lifting and will leave the rest as an entertaining and potentially useful “exercise for the reader.”
Here’s your question: what would be the easiest way to specify phasor~ outputs that would give me tuplets that weren’t duples or triples? It’s not rocket science, but I’ve got other fish to fry, at any um… rate.
Although the wave_select subpatcher might look similar to the one we used in our last LFO tutorial, I’ve added a few things – things I use in my own practice, and some bits and pieces that began their lives as reader requests. Here’s the inside of the new and improved subpatcher.

The first change is something simple that I can’t believe I didn’t add in the first place: the ability to set the phase of the output waveform. This isn’t at all difficult – we’re using a rate~ object already to provide a time multiplier to work LFO frequencies that are longer than a dotted whole note, it’s a simple matter to send a floating point value in the range 0.0 – 1.0 to the left inlet of the rate~ object. This lets us sum multiple versions of the same waveform that differ only in their phases, and create interesting effects by being able to place the start point of an oscillator’s output. It’s something I use all the time.
The second addition was a reader request for a negative-going ramp. To be honest, I didn’t add it because I tend to simply invert a positive going ramp waveform when I need one (Extra credit: is there a situation you can think of where this might be an important feature to have?). So I thought I’d add the new waveform as a way to point out a lovely feature of the triangle~ oscillator – its ability to use a signal input to change phase offset of the peak value. In effect, this lets us derive a standard ramp signal (the kind of output we see from the phasor~ object), a triangular waveform, and a reverse ramp signal merely by modifying the phase offset.
It may have occurred to you at this point that you could modify this patch so that there’s only one triangle~ oscillator object that takes an input value between zero and one to produce a variety of waveforms along the “positive-ramp to triangle to negative ramp” continuum. A fair number of savvy Max programmers use this feature to create oscillators with morphing waveforms, in fact. I’ll leave this as yet another interesting project for your edification. For this subpatch I’ve instantiated the triangle~ object three times, each with an argument that gives me a phasor~-style positive-going ramp (0.), a negative-going ramp (1.0) and a triangle wave output (.5).
Using square wave output in an LFO provides some interesting effects (it allows you to create ostinati, and the sudden jumps in mixed waveforms can be really useful), I thought it’d be useful to have a square wave output with a variable duty cycle that would allow me to relative amount of time at which the square wave output was high or low.
Finally, After I had the variable duty-cycle square-wave working properly, I realized that there was something else I would like to have. As nice as the square wave output is, the “jump” when it’s summed with existing waveforms is always a fixed amount. I was thinking that it would be nice to be able to use a sample and hold technique to provide random jumps at ITM rates rather than the set vertical offset, so I added a noise~ source and the Max sah~ object to sample the noise output to provide that non-deterministic vertical offset.
In the fourth tutorial, I spent a lot of time talking about what the relationship between a modulating LFO and a parameter would be, and tried to suggest some interesting ways in which you could using value scaling and value ranges to gradually turn control of a give parameter over to the LFO in a way that seemed smooth.
As you might imagine, a number of us here at Cycling ’74 have been pretty intimately involved with working with the new version of Ableton Live as we prepare for the release of Max for Live. One side effect of this frenzied activity for me personally has been encountering the ways in which the Live application thinks about modulating a parameter. Although they certainly have one method for modulating parameters that matches my personal approach, Live 8 recognizes a number of what they refer to as “Modulation Modes.” In brief, here’s what they are and how they work:
Working with these modes in Live suggested that I generally use what Live calls “bipolar” modulation (it’s what the previous tutorial did when controlling the amount of modulation added to an LFO, in fact), but that there are some interesting features to doing that in other ways. So I sat down and decided to try to create a Max patch that would implement these modes of modulation. In part, I thought it would be useful to actually see all four modes operating next to each other at the same time to get a better sense of how they worked with various parameter changes. After some quality Max time, I emerged from my studio weary and singed, but holding aloft the modulation modes patch you see here.

It uses the same value and range controls you saw in the previous LFO tutorials, but applies those inputs to four subpatches that implement each of the four modulation modes (feel free to open the subpatches up and poke around in them, of course), and then displays the new output ranges using 0-127 range slider (rslider) objects and applies the output range to a simple sampled sine wave for demonstration purposes.
This demonstration patch requires audio input to help you visualize the changes associated with each mode, and I initially kept the 0-127 range I used in the last tutorials. But when it came to adding the modulation modes to my patch, I realized that I could modify the patch just a little bit and make things easier to use. First, I really didn’t need to watch the output modes, so there wasn’t really any reason to be working with audio inputs, so I could remove that logic from the subpatch. After a little thought, I realized that I already had the patch functionality necessarily to scale the waveform output – the numerical outputs for the wavescale subpatch from a couple of tutorials back. All I needed to do was to modify the output of my modulation mode patch to output numbers in the range -1.0 – 1.0 instead of 0-127, and then connect the outlet of the subpatch that calculated modulation modes and I was all set. A nice bonus here was that my output was still in the signal domain – none of the waveform sampling we worked with in the last tutorial. So I sat down and removed some outlets, added a couple of scale objects to transform data ranges from 0-127 to -1.0 – 1.0, and I was ready to go.
Here’s the handy new LFO module with all the new added features and the modulation modes built right in, ready for use as a waveform or ready to be sampled for some other means:

The careful reader will notice that I’d added some subpatches here that allow me to reset range slider (rslider) objects with the click of a button. I’m very partial to this technique – particularly for the ability to return to initial state in live situations. In I generally like to add the UI elements to the Presentation Mode and then make the buttons really tiny and position them at the position associated with a variable or locate them near to the UI I want to reset.

You’ll notice that I used the phrase “generating and organizing variety” at the very beginning of this tutorial to describe my interest as a Max programmer and performer. The phrase has two parts, and I’ve arguably only dealt with half the question. I purposely left that the business organizing variety (i.e. making noise) as an exercise for my readers last time out. This time, I thought I’d finish off this tutorial by taking the LFO module we’ve just made and put it to work doing something interesting, or at least audible.
The humble Max wave~ object lets you use the contents of a Max buffer~ object with which it is associated with by name as a wavetable. All you need to do is to use a phasor~ object to drive the rate at which the wavetable is read.

At low speeds, you can get something like regular buffer playback, and higher speeds will yield waveforms (that usually don’t have anything to do with the pitch or the original audio sample, of course. In these cases, the contents of the buffer translate to timbre rather than the sample at normal playback rates).
But we’re talking about Max patches here – the wave~ object accepts a signal input that is uses to read through the wavetable. There’s no particular reason that the signal input needs to be a single phasor~ object, or even that the input needs to proceed in a stately manner from 0. to 1.0 as the phasor~ object does. Consider the little LFO object I’ve just put together as an input source for a wave~ object.
There might be a couple of things to consider when using the LFO to drive the wave~ object for playback:
The LFO outputs signal values in the range -1.0 – 1.0, whereas the phasor~ object produces output in a narrower range of 0. – 1.0. What happens when the wave~ object gets a negative value between -1.0 and 0, as it would for one-half of the period of a sine wave? (Feel free to try it and see what happens).
If the phasor~ object’s output doesn’t start at 0. and end at 1.0, will we get complete playback of the sample? What if the sample goes from 1.0 to 0. or changes direction?
Square wave output won’t be particularly useful, since that kind of output won’t do much interesting in terms of audio playback – the horizontal portion of the square wave output will just output a steady value associated with a particular portion of the waveform. However, what do you think might happen if we were to mix square wave output with another kind of waveform (a ramp or triangle, for example)?
These questions suggest some interesting things we can take advantage of. We can modify or constrain the range the phasor~ object whose input the wave~ object uses for playback to produce interesting playback patterns – patterns that are locked to the current tempo of the Max transport, in fact. And we can combine the output of several synced LFOs to produce all kinds of interesting nonlinear playback.
The waveplayah patch is an attempt to do just that. Simply put, it takes a trio of the LFO modules we created earlier in the tutorial, sums their output, adds some playback logic that we can use to add a little interest to the proceedings, and lets us produce various kinds of nonlinear playback.
The amount of logic we need to add to create the waveplayah patch beyond simply duplicating the LFO module three times over is pretty simple. One thing we do need to keep in mind is that since we’re summing waveforms, the summed output range of the waveform will now potentially be in the range -3.0 – 3.0. We can fix that easily by multiplying the output waveform by .33 using the *~ object.
And since our summed output range doesn’t match the expected 0. – 1.0 range of a phasor~, we have some interesting opportunities to modify the way that our summed and synchronized waveform drives the wave~ object. The waveplayah patch has a subpatch called playback_mode that lets us map our LFO output in one of several ways. Here’s an example of how the playback_mode subpatch works.

The first example uses signal multiplication and signal scaling to move the entire waveform so that it falls into the 0. – 1.0 range. The Max clip~ object is used for the same thing we did when we needed to create square wave output – arguments to the clip~ object set the low and high ranges for the output; anything that falls above or below that output range is simply clipped at the lower or upper range (We’ll leave it to you to imagine or discover what that sounds like). Finally, we’re using the Max pong~ object in the subpatch to provide us with two new playback options – folding and wrapping. The pong~ object can do both things – its first argument sets the mode of signal treatment (0 for wrapping, 1 for folding) and the second and third arguments set the lower and upper ranges below or above which the signal folding or wrapping will happen. The playback_mode subpatch provides all those options by using a gate~ object together with a menu object whose index number (with 1 added to that number so that we don’t have a 0 value – that would turn the gate off) sets which mode to use in playback.
Technical note: If you take a look at the inside of the playback_mode subpatch, you’ll notice, too that the first choice (scale) also includes a gate to turn the output of the *~ and +~ objects off. We’re doing that because the output of these two objects is always “on” and will be added to the other output waveforms if we don’t.
I’m kind of stunned by the range of kinds of output this little patch will produce, and hope you enjoy playing with it. There are some obvious improvements you might want to make, such as adding objects to the Presentation Layer to create your own UI for the playback unit, or pattrizing your patch to allow for quick preset loading. Or you just might want to spend a few days getting acquainted.
Next time out, I’ll show you how to turn the waveplayah patch into a Max for Live audio effect device (and, more generally, how to port a Max patch for use in Max for Live).
In this article, Jim Aikin reviews the new add-on product to Live, developed by Ableton and Cycling ’74, with a detailed account of his experience. In you are new to Max for Live, this is a helpful introduction before downloading the demo and trying it out yourself.
Matthew Davidson aka Stretta is a talented guy. He’s an accomplished graphic artist and video producer/editor but we talked to him about his music. Stretta’s music is lush, modest and dreamy in the tradition of Brian Eno but it definitely has character of its own. Stretta comes from a tradition of modular synthesis that led him to discover Max/MSP.