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.
All LFO tutorials in this series:
- LFO Tutorial 1: The Zen of the Silent Patch
- LFO Tutorial 2: Making Some Noise
- LFO Tutorial 3: Extending Our Generators
- LFO Tutorial 4: Building Complexity
- LFO Tutorial 5: LFO Child Slight Return
- LFO Tutorial 6: Live If You Want It
- LFO Tutorial 7: Rattle and Hmmm
- LFO Tutorial 8: Valediction
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)
- We add a pattrstorage object to our patch and give it a name (playahstore) as an argument (since we want our preset names to be global rather than local, I’m not going to begin the name of the object with three dashes as we did with buffer names).
- Select the pattrstorage object and click on the Inspector icon in the Patcher Window toolbar to display the object’s Inspector. Click in the checkbox for the parameter_enable attribute, which lets you save parameter data in the pattrstorage object itself.
- Add an autopattr object to the patch.
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.
- Add a preset object from the Max palette, and then select the object and click on the Inspector icon in the Patcher Window toolbar to display the object’s Inspector. If you scroll down to the very bottom of the listings in the Inspector window, you’ll see one called pattrstorage.
- Double-click in the Value column to get a cursor and type in the same name you gave the pattrstorage object (playahstore), and then close the Inspector.
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).
A little local color
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.
Dragging and Dropping
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 FileSelector. 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:
After that quality time, I’d figured out a few useful things:
- Darwin’s patch was loading mono files (see that message box in the previous illustration that contains the message replace belldog:Users/gtaylor/Desktop/borg_ward.aif 0 -1 1? Looking at the replace message in the refpage sorted that out). I’m going to be wanting to work in stereo, so I’ll send the message replace [filename] instead.
- He’d added some really clever code that allowed him to load MP3 files. I definitely want that.
- His user interface was pretty interesting, once I’d toggled back and forth between Patcher and Presentation modes a few times to see what was happening. He was using a set of overlaid textbutton objects with transparent borders to work as his interface – one textbutton object displayed a startup message that was removed any time a file was loaded. Another textbutton object was used to display an error message if you tried to load a file that it didn’t recognize, and a third textbutton was used to display the name of the loaded file. I didn’t really need or want the waveform display, but I could resize the textbutton objects and use ‘em all. Great!
There was also some stuff in Darwin’s patch I didn’t need or wanted to change.
- Darwin’s Loop Shifter instrument used the pattr system to store one preset per key. I could safely get rid of that.
- His original patcher also had all the buffer~ object stuff inside his subpatcher. I’d rather have the buffer~ object at the top level of my patch, personally, so I need to add a new outlet and move the buffer~ outside of the subpatch.
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.
The road goes ever on and on….
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..