Using the preset capabilities of pattrstorage

Image

 

[In order for this example to work properly, you should first download the file called noiseburstpresets.json and save it with that name somewhere in the Max file search path.]

This patch shows some features of pattrstorage, and demonstrates how it might be used to structure a series of different settings to shape the formal structure of a longer period of time.

The first thing to notice is that there is not a single pattr object anywhere in this patch. However, each of the nine labeled number boxes that provides parameter data to thepatcher noisebursts subpatch has been given a scripting name in its object Inspector. The autopattr object, as soon as it is created, finds not only all the pattr objects anywhere in the patch but also all the UI objects that have scripting names, and it makes available all of those names — pattr object names and UI scripting names — to anypattrhubpattrforward, and pattrstorage objects in the patch. So, without needing any pattr objects or explicit bindings, all we need to do is include an autopattr at the top level of our patch, and automatically all the UI objects that have scripting names will be storable and recallable by pattrstorage.

The sonic/musical function of this patch is to generate different randomized patterns of short bursts of filtered noise. The patterns are generated inside the patcher noiseburstssubpatch — and all the MSP objects that create the actual bursts of filtered noise are isolated in another subpatch within that so that they can be easily enabled and disabled to turn the sound on and off — but the UI objects that provide the parameters that shape the noiseburst patterns are all in the main patch. Those UI objects all have scripting names, so they can be controlled by the pattrstorage object, and the pattrstorage can in turn be controlled by the preset object.

Before the whole system of pattr-related objects existed, a standard way to store the settings of all UI objects was with a preset object. (You can see the standard usage of thepreset object in action in an example from one of the original Max tutorials, and another good example can be found in the tutorial patch for MSP Tutorial Chapter 7.) The presetobject was notoriously a bit buggy and problematic, so the pattrstorage system is ultimately superior. Nevertheless, the straightforward graphic interface of the preset object is very effective, so a feature was added to it that would allow it to be used with pattrstorage. All you need to do is create a preset object, then send it a pattrstorage message indicating the name of the pattrstorage object you’d like it to control. From then on, you can use that preset object to store and recall presets in the named pattrstorage.

When the patch is loaded, the pattrstorage object tries to load in the JSON preset file of the same name, called “noiseburstpresets.json”. If you have saved that file correctly in a location that’s findable by Max (i.e., within the Max file search path), that should happen automatically. Because the preset object is bound to the pattrstorage object, You should be able to choose different settings for the parameter UI objects just by clicking on different buttons of the preset. Note that the preset is not controlling those objects directly, as it would in a traditional usage of the preset object; it is controlling the pattrstorage object, which is actually in charge of controlling all the UI objects that have scripting names. You can double-click on the pattrstorage object to see its “Client Objects” window. Note that the on/off toggle does not have a scripting name, so it’s invisible to thepattrstorage; that’s intentional, so that we can turn the sound on and off independently of any preset changes we might make.

Click on the ezdac~ to turn MSP on, use the toggle to turn the noisebursts on, then try choosing one of the 16 saved presets to change the sound.

There is also a subpatch called patcher autopresetchooser that’s intended to demonstrate one possible approach to automating preset changes and preset interpolations. Double-click on it to see its contents. The subpatch is designed to choose a new preset number every 15 seconds, form a recall message that will enable interpolation from the previous preset to the newly chosen present, and then trigger a 5-second interpolation from the old preset to the new preset. The resulting messages will thus say recall <previouspreset> <nextpreset> <interpolationvalue>, with each message having a different interpolation value progressing from 0 to 1 over five seconds. Try turning on the “autopresetchooser” subpatch to cycle randomly through all the different presets. This demonstrates how one might automate changes over a long period of time to create a certain formal structure, one that is either determinate or, as in this case, indeterminate because of randomized decisions.

The composition of known states of a patch, governing its behavior, can be composed in non-real time and stored in a whole collection of presets within pattrstorage, and those presets can then be recalled interactively or automatically in a performance to recreate known behaviors at the desired time.

Storing and recalling multiple pattr values

Image

[In order for this example to work properly, you should first download the file called twocloudspresets.json and save it with that name somewhere in the Max file search path.]

The pattrstorage object allows you to store and recall the states of any and all pattr objects in the patch or its subpatches. Each set of states is stored in a numbered “preset”, and pattrstorage can store as many presets as you’d like. The presets can then all be saved in a separate file, in JSON format, and can be loaded in when the patch is loaded. Thus, we can recall any of a number of states for the entire patch at any time. An additional, and very powerful, feature of pattrstorage is that it can interpolate between two different states.

For this demonstration, I made a subpatch called “twoclouds” that generates two streams of MIDI notes. (They’re really just two motorhythmic melodies of randomly-chosen pitches. I call them “clouds” because when the melodies are very fast the random behavior is reminiscent of the random movement of particles in a compressed gas.) The parameters that can be controlled are the rate of the notes (notes per second), the loudness (MIDI velocity), the timbre (MIDI program number), and pitch register, which is specified by height (the lowest pitch that can be chosen) and range (how far above the minimum the pitch might be). There is also a pattr bound to the on/off toggle switch, so that the process can be turned on and off remotely. Note that the UI objects attached to the pattrs do not have scripting names, but they are bound to the pattr by the patch cord coming from the pattr‘s middle inlet. This allows you to see the value of each pattr, and also to modify the contents of each pattr by changing the UI object.

We can store the current state of all the patch’s pattr objects in pattrstorage by sending pattrstorage a store message specifying the preset number where we want it to keep the data. In the main patch, we use a pack object to construct the store message. This allows you to choose a preset number, and then click on a button to trigger the storemessage. (The fact that you have to explicitly click on the button after having specified the preset number in order for anything to be stored helps prevent accidentally overwriting previously-stored presets. If you were simply to use a number box attached to a message box saying store $1, every single number from the number box would cause a preset to be stored.) To recall a preset, all you have to do is provide pattrstorage the number (int or float) of the preset you want to recall.

The preset file “twocloudspresets.json” contains five presets. Use the number box labeled “recall preset #” to choose a preset from 1 to 5. You should see the UI objects in the subpatch change accordingly, showing the values that have been recalled for each pattr. If you don’t see that, perhaps the preset file was not loaded properly into thepattrstorage. (When the patch is first loaded, pattrstorage uses its own name to look for a .json file of the same name, but if it can’t find such a file, it will contain no presets.) You can read in a preset file by sending pattrstorage a read message. You can also create new presets, if you’d like, by using the UI objects in the subpatch to change the pattrvalues the way you want them, then storing that data in a pattrstorage preset (presumably in presets 6 and higher). You can then write the presets to a new file with the writemessage, or directly to the same file with a writeagain message.

One of the most interesting aspects of pattrstorage is its ability to calculate pattr data that is somewhere in between two presets, using a process of interpolation between the values in two presets. You can specify an interpolation between two adjacent preset numbers just by using a float value with a fractional part. For example, to get data that is right between the values of presets 1 and 2, you could send pattrstorage the number 1.5. Try using the float number box labeled “interpolate between adjacent presets” to try this out.

If you want to interpolate between non-adjacently numbered presets, the syntax is a bit more complicated. The message should start with the word recall followed by one preset number (let’s think of it as preset A) and then another preset number (we’ll think of that as preset B) and then a value from 0. to 1. specifying the location between preset A and preset B. A value of 0 is preset A, 1 is preset B, and intermediate values are some degree of the way from A to B. In this patch, you can specify the two presets between which you want to interpolate, and you can then drag on the number box labeled “interpolation between preset A and preset B”, from 0. to 1., to trigger well-formed recall messages topattrstorage.

You can see the current value of each pattr by double-clicking on the pattrstorage object, which opens a “Client Objects” window. Try that. If you want to, you can even double-click on the data values in the client window to type in new values. You can see that you also have a choice of what type of interpolation you want between presets for each pattr. (See the reference page for a description of the different types of interpolation.) Since interpolating between different MIDI program numbers would mean hearing the timbre of every intermediate program number, interpolation doesn’t make much sense for those pattrs, so we have set the interpolation for those items to “none”. In the leftmost column of the client window, you can also enable and disable the effect of the pattrstorage object on each pattr. Notice that we have disabled pattrstorage‘s control of the pattr onoffobject in the “twoclouds” subpatch, because we don’t want that to be affected by preset changes. We’ll control that separately by another means.

In the main patch, you see yet another useful object, pattrforward. By sending pattrforward the word send followed by the name of a pattr, you can set the destination for thatpattrforward object. Then any subsequent messages to pattrforward will be forwarded to the named destination. So in our case, each time we click on the message boxes saying 0 or 1, the message will be forwarded to the pattr onoff object in the “twoclouds” subpatch. This shows yet another way to communicate remotely between main patch and subpatch.

Try out a few of the presets, try interpolating between presets, and if you’d like, try creating, storing, and recalling new presets of your own making.

Communicate with many pattr objects from a central hub

Image

In large and complex patches that have many pattr objects, it might be useful to be able to communicate with all of them at one central location. That is the purpose of the pattrhub object. With pattrhub you can alter the contents of any pattr just by using the name of the pattr followed by the data you want to put in it. You can also query the current contents of any pattr by preceding its name with the word “get” (as in gettempo if there is a pattr tempo object somewhere in the patch). You can query the contents of all the pattr objects in the patch with the message getstate. Whenever you query the values of pattr objects, the information comes out the right outlet of pattrhub, preceded by the name of the pattr(s) in question. Thus, you can use a route object to look for and parse the values of the various pattrs coming out of pattrhub.

In this example, we have made a program that performs simple rational polyrhythms. We specify a numerator and denominator for the ratio of one rhythm to another, and we divide those values into 1920 (the number of ticks in a whole note) to determine the correct number of ticks to use as the time intervals for the two metros. We’re using a named transport object, with the name “clock1”, to keep it distinct from the global transport. The numerator, denominator, and beat tempo are all stored in pattrs so that we can set them in one part of the patch and use them in another part.

Whatever the values of the pattrs are when the patch is saved, those values will be saved with the patch and will be sent out when the patch is loaded. Using the getstate message to pattrhub, we can query the saved contents of each pattr, and can use that information to set the initial values of the UI objects. Notice that in this case, the pattrs are not explicitly bound to any UI objects, and the UI objects don’t have any scripting names. We’re just using the getting and setting capabilities of pattrhub to make the communication between the UI objects and the pattrs.

Binding pattr objects between a subpatch and its parent patch

Image

pattr object can be remotely bound to another pattr or to a UI object, using the bindto attribute, even if one of them resides in a subpatch. To indicate an object in a subpatch, the syntax for pattr‘s bindto attribute is to use the subpatch name, followed by two colons — :: — followed by the name of the object to which you want to bind. Use of that syntax is shown in the pattr in the main patch. Notice that to do this with a patcher object, the patcher needs to have a name typed in as an argument. And of course the object to which you intend to bind needs to have a name, too. If you look inside the patcher degtorad subpatch, you’ll see a pattr object with a typed-in name degrees. The pattr in the main patch can bind to it by using the patcher object’s name and the name of the pattr object inside the subpatch.

To communicate in the opposite direction, from a pattr in a subpatch to some object in the main patch, you just refer to the patch one level above using the name “parent”. In our subpatch, we have a pattr that is bound to the number box named “radians” in the parent patch. (Although it’s not demonstrated here, you could even bind objects through multiple levels of subpatches, using multiple :: symbols, as in @bindto parent::parent::radians.)

You may wonder, “Why couldn’t we just put an inlet and an outlet in the patcher subpatch, and communicate with it via patch cords?” And you’d be quite right. In this simple example, that would be easier. (But it wouldn’t have given us the pretext to discuss the :: syntax.) In more complex situations, you’ll see how the ability to bind a pattr to objects on other hierarchical levels can be useful.

Notice how, in this example, the pattr objects in the subpatch have typed-in names, but the one in the main patch does not. We didn’t bother to give that pattr a name because no other object needs to bind to it. (It takes care of binding to the degtorad::degrees object all by itself.) As far as Max is concerned, though, all pattr objects have a name. If you don’t type one in, Max internally assigns it a quasi-random name.

Binding objects to each other, and to a pattr

Image

If you want two user interface objects always to display the same information, it might seem sensible to connect the outlet of one to the inlet of the other and vice versa. However, that will lead to an infinite loop unless you do something to stop one of them from always sending out the value. The set message is useful in that regard, because it allows you to set the contents (and the display) of a UI object without causing that object to send out a message of its own. The top part of the patch demonstrates this technique. Whenever the slider is moved by the mouse, it sends its value out to the number box. The number box displays that value and passes it on out its outlet, so both objects end up showing the same (most recent) value. But what if the user changes the number box directly with the mouse? We would want the slider to be updated as well. That’s why we use the setmessage to set the content and appearance of the slider without causing it to send out that value again (which would cause the feared infinite loop). In this way, no matter which object is moved by the mouse, they both correctly show the most recent value.

A pattr can be bound remotely to one of those two UI objects by referencing the object’s scripting name (as set in the object’s Inspector). Since the two UI objects are bound to each other using the set technique described in the previous paragraph, the effect is as if the pattr were bound to both of those UI objects.

Binding a pattr object to another object

Image

pattr object can be “bound” to another object, so that the two objects share the same data. By setting the pattr‘s bindto attribute, you can bind it to any other named pattr object, or a user interface (UI) object that has a scripting name. In this example, we have set the scripting name of the number box at the bottom of the patch to “panning” in the object’s Inspector. That allows us to bind it remotely (with no patch cord) to the pattr. (Incidentally, although it’s not demonstrated here, you can also bind a pattr to a UI object, even an unnamed one, by connecting the UI object to the pattr‘s middle outlet.) Once the two objects are bound together, any change to the contents of one of them will be shared by the other, and the contents can be recalled from either of them with a bang. Also, both of them will send out their stored message when the patch is loaded.

Introduction to the pattr object

Image

The pattr object and its related objects such as pattrhubpattrforwardautopattr, and pattrstorage make it possible for you to store data (or any sort of message, really), recall that data when the patch is reopened, store and recall it from other parts of the patch, and make transitions from one set of stored data to another.

The basic unit of storage is the pattr object. It can store any message, its contents will be saved as part of the patch, and it will recall and send out its saved message when the patch is loaded.