Max/Fts: A primer

Max/Fts: A primer

Curtis Roads, Editor

Department of Pedagogy

IRCAM

1, Place Igor Stravinsky

75004 Paris France

Beta version of the documentation, September 1996

Copyright 1988, 1993, 1996 by IRCAM

All rights reserved

Max is a trademark of IRCAM

Introduction

This document is aimed at readers who are new to Max. We explain the Max windows, how to create and edit patches, and present an overview of the types of objects available. Even though this primer is aimed at novices to Max, we recommend that the reader have some programming experience, if only to understand our use of basic concepts of computer science. Some familiarity with Musical Instrument Digital Interface or MIDI protocol would also be helpful. Reading this chapter should give you a good idea of the facilities and protocols of the Max environment. The best way to learn Max programming well is to carefully study existing patches, copying them and modifying them in small ways. Gradually you'll learn what works and what doesn't. Since Max is a real-time system, its feedback (sometimes sonic) often tells you instantly what it's doing. If you are not familiar with the Apple Macintosh version of Max, you can skip the next section. It is for readers who have already learned Max by using the Apple Macintosh version.

Main Differences Between Opcode Max and IRCAM Max

Many of the objects in IRCAM Max are compatible with the Apple Macintosh version of Max marketed by Opcode. A big distinction between the two version is that IRCAM Max integrates real-time audio signal processing into the environment of Max. To cite all the small differences between the two environments would take up too much space. Instead, here is a list of the main differences between the two environments. Signal processing objects are smoothly integrated in IRCAM Max, and lead to a different style of Max programming. Opcode Max has a more developed visual interface The graphical tools provided with the table object are different in the two versions The NeXT computer has a single serial port, so there are no facilities for multiple MIDI ports as in Opcode Max Default message order depending on graphical layout of objects does not apply in IRCAM Max Creation of external objects is different in the two versions Pathnames are handled differently by the two underlying operating systems The rest of this chapter presents a basic Max tutorial. If you are familiar with the Apple Macintosh version of Max, you might want to skip to the section on signal processing objects. After that you should try out the online tutorials described in Chapter 4.

Max Windows

Your interaction with Max revolves around three types of windows:

The Max window

The Max window shows the results of computations, status, and error messages as they occur. Keep a spare eye on the Max window, especially if something is going wrong. The center of attention is the patcher window, described next; this is where you program and play with Max. Later we'll talk about function table editing in detail. Also see the entry on the table object in the Max Object Reference.

The Patcher Window

The patcher is the most important window in Max. To open up a patcher, select New Patcher under the File menu. This opens an untitled patcher with a palette of symbols on the top left and a processor display at top right. (The processor display is explained in the Chapter 6, Special Topics. It is not important in this tutorial.)

Patches and Objects

The contents of a patcher, called a patch, is a collection of boxes connected by patch cords. (Sometimes these are also called wires or lines.)The boxes represent Max objects that send and receive messages to and from one another. The object boxes can work as:
controls
like sliders and buttons that you can control with the mouse or keyboard;
indicators
that inform you of a numeric value or that an event has occurred;
objects
that perform computations
message holders
that contain text that is sent to other boxes.The messages can be symbols like bang, numbers, or contain a combination of the two.

Making an Object

Object palette

The picture shows the Max object palette. Each type of object is explained in the following list, following the left to right order. To create an instance of an object, click anywhere in the object palette and drag the selected object into the center of the window. When you release the mouse button an object is officially created and can be connected to other objects. Named object boxes (number 2 in the list above) appear blank when you first drag them into a patcher window. Once you type the name of a known object, the box sprouts inlets and outlets. These appear as dark rectangles on the top and bottom of the boxes.

Title ???

Inlet Inlet     ¬ Resize point ­ Outlet The resize point+/-a small mark on the right side+/-changes the size of the box, as in the example below: ¬®

Note that some boxes grow and shrink in one dimension only.

Run Mode Versus Edit Mode

The presence of the palette indicates that the patcher window is in edit mode. This means that you can add new objects or modify the interconnections between objects. When you have finished creating a patch, you can set it to run mode in three ways: In run mode, the interconnections amongst the objects cannot be altered, thus protecting the patch from accidental modifications. Max interprets gestures from the mouse and the alphanumeric keyboard as real-time controls. To switch back to edit mode, use any of the commands just listed; they toggle between run and edit mode.

Editing Patches

Editing a Max patch is equivalent to writing a computer program in a traditional programming language. When you drag an object from the palette, you are creating an instance of a class of similar objects. By drawing a line from one object to another, you set up a pathway over which messages can flow from one object to another. The rest of this section explains the editing protocols of the Max patcher window, as a prelude to explaining the different types of Max objects. Sometimes we describe the textual contents of an object within a paragraph; when we do this, we enclose the text in brackets, as in {foo bar}, where foo is the object and bar is an argument to it.

Connecting and Disconnecting Object

When a patcher window is in edit mode, users can modify objects and interconnect them. To make a connection, click on an outlet at the bottom of one object and drag the patch cord to an inlet of another object; then let go of the mouse button. Notice that you can let go of the mouse button anywhere in the object box; the patcher connects to the nearest inlet. You can also take more than one patch cord from an outlet, plugging it into several inputs. A general rule in Max is that any message sent from an outlet passes to all connected inlets.

Connecting a single outlet to several inlets.

To delete a connection, select the line and choose Cut from the Edit menu, or press the "delete" key (backarrow).

Importance of Proper Connections

It is often important to connect the proper outlet to the proper inlet. Some objects transmit different information through each of their outlets, and many objects interpret their input data according to the inlet through which they receive it. Incompatible connections can arise. Max tries to determine if the connection between two objects makes sense. If it can determine this at the time that you try to connect an outlet to an incompatible inlet, it won't allow the connection to be made. Sometimes this can't be determined ahead of time and Max prints an error in the Max window when the incompatible message is actually sent.

Selecting and Moving Objects

You can select object boxes and patch cords by clicking on them. To select (or deselect) multiple objects, press the shift key as you click on the mouse. Cut, copy, and paste work from the Edit menu and via their command key equivalents according to the usual NeXT protocol. If you copy and paste a collection of objects, the lines connecting objects are also copied. To move an object, select anywhere in the box and drag it while holding down the mouse button.If you select two or more boxes and change one of them, they all move or grow in parallel. Patch cords move only as a result of objects moving or growing. You can also move selected boxes by using the arrow keys.

Editing Text in Boxes

Although Max has many graphical elements, you should expect to do a fair amount of typing as well. Some Max object boxes accept typed text. To demonstrate, pull down one of the three objects on the left from the palette. You can type directly into these objects.

To edit the text in an existing patch, be sure that the patcher is in edit mode, and that the text box is the only selected object. Click on the text to edit. Changes you make in the text are validated when you deselect the box. Note that the Return key does not finish text entry; it merely starts a new line. As you might expect, when text is selected, operations such as cut and paste apply to the selected text, not the whole object box. For example, if you give the command to cut when text in a box is selected, you cut only that text and not the whole box. Subpatches If a patch becomes too big for one window, you can put parts of it in a subpatch. The subpatch appears as an object with the name patcher in the main patch.

When you study existing patches, you will often see patcher objects somewhere on the screen. Double-click on the patcher object in Run mode to make the subpatch visible. If you close the subpatcher window, the subpatcher becomes invisible but it will still exist. Later we'll explain how to make subpatches.

Obtaining Help

The Help item in the Info window prints out a list of Max objects.

Max help file on the stripnote object.

For specific information about a particular object, Max provides a help file facility. Click on any object with the Alternate key down to see a help file on that object.

Saving Your Work

The patcher and function table editor windows can be saved as files and recalled with the Open, Save, and Save as... commands in the File menu. It is important to know that Max saves the contents of a patcher window by writing an interpretable text. This mechanism is also used for cutting and pasting or parts of patches. You can even open up a Max patch file within a text editor, to see its alphanumeric representation.

Specifying Pathnames

IRCAM Max may require you to specify Unix pathnames in order to load waveforms, subpatches, externally-loaded code modules, and soundfiles. There are several ways to do so: If the file you want is in the same folder as the patch that uses it, no pathname is necessary. If the file is nearby, a relative path can be given (for example ../sounds). If the file is in a far away directory, an absolute path (from the root /) can be specified A patch inherits the current path when the patch is loaded, unless the patch overrides it with a declare. There is no way to query the patch from Max to find out its current path. If you wish to access resources in specific directories, give a Unix pathname, that is, a series of directories beginning with a directory name or a slash (/), where a directory name specifies a relative path and a slash specifies an absolute pathname.

Predefined Max Objects

IRCAM Max comes with about one hundred predefined objects. This section summarizes this set. Since there are many objects, all we hope to do here is to present an overview of the range of functions they can perform. Later, in the tutorial chapters, you'll learn how each object works in actual Max patches. See the Max Object Reference manual for technical details on a particular object. For our purposes here we can divide the range of objects in Max into ten basic types: This ten-part division is just a teaching device and has no significance in a Max program. The only real distinction between objects is the division into control objects and signal objects, which we'll discuss later. To get a sense of the facilities available in Max, the next ten sections briefly explain the objects in each type.

Message Processors

Message processors operate on Max messages. The int and float objects send integers and floating-point numbers, respectively, to their outlets; they can also store values to send out later, so they act as data structures for individual numbers. The pack and unpack objects put together and take apart lists. The trigger and bangbang objects emit up to ten messages, right to left, and are useful for solving order problems. In this task, trigger is more general, since bangbang puts out only bang messages. The swap object switches the order of two messages.

Arithmetic Objects

The arithmetic objects include the usual + - * / (addition, subtraction, multiplication, division) operations, and also a group of relations that put out 1 or 0 depending on whether the result is true. In this category are: % to obtain the remainder from a division; << and >> to shift a number left or right; |, ||, &, && for logical and bitwise OR and AND; split to divide a musical keyboard into several independent regions, accum to accumulate sums or products; abs for absolute value. The drunk and random objects offer two kinds of random number sequences. The expr lets Max programs evaluate C-like expressions and provides access to useful library routines for trigonometric functions, type conversion, square root, factorial, exponentiation, logarithms, and pseudorandom number generation. The +, -, * and / objects can be forced to calculate in floating-point by supplying them with floating-point arguments, as in {+ 0.} or {+ .3}. In this case, the output is generated in floating point format. You can always send floating-point values to a fixed-point object but it will be converted to an integer before the operation is calculated, as in the following example:

¨7

The floating-point input is rounded before the integer addition.

® 7.5

The period after the 4 indicates that this adder handles floating-point numbers. The six arithmetic relations can also be made to do floating-point comparisons as in {>= 0.}; in this case, however, the value at the output is always fixed-point.

Clock and Line Objects

The clock objects let you manage the timing of events in Max. The timer reports the time in milliseconds between two incoming messages; delay and pipe are simple and complicated delay lines, respectively. The metro object is a delay loop that emits a regular, metric pulse, while speedlim slows down the speed of a changing number. The line object can be put into this category because it generates a smooth ramp from one value to another over a specified period of time.

Subpatch Objects

Subpatch objects are extremely valuable. They let you hide the details of a complicated patch by breaking it into several modular parts called subpatches.The patcher object creates an embedded window. You can put your own inlets and outlets on the patch you create in this embedded window. Then when you close the embedded window only the presence of a patcher object in a superior window indicates the presence of the subpatch.

MIDI Objects

Max has a variety of objects for processing MIDI data. MIDI data is transmitted and received via the serial port of the NeXT computer, connected to a Macintosh-type MIDI interface. In the MIDI protocol, notes have a pitch, velocity, and channel which correspond to the three inlets of noteout or the three outlets of notein, and so on for the other message types. The seq object is a MIDI sequencer (raw MIDI bytes in and out), makenote and stripnote are for adding or removing note-off messages from a note stream; midiparse and midiformat convert raw MIDI bytes to and from their real numeric information.

Broadcast Objects

The broadcast objects are send (or s), receive (or r), and value (or v). These let you transmit information from one place to another without the need for a connecting line. Any message you pass to {s foo} , for example, appears in the outlet of all the {r foo} boxes in any active patch. You can use {v bar} as a global storage cell for one number bar. The convenient thing about value is that you can set and read the value of bar from any active patch.

Keyboard and Screen Input/output Objects

Max's key and keyup objects let users communicate with a patch using the NeXT keyboard. Print types all messages it receives on the MAX window.

Filter and Selector Objects

Filter and selector objects operate on the data flowing through a Max patch. The select object filters a stream of numbers for a specific value or values, putting out bang for each match. The route object is similar but it can also select for symbols, and can pass the rest of an incoming message after stripping the selected item off. The change object filters out the repetitions in a stream of numbers. The gate object lets you make or break a connection in a patch according to an arbitrary event. The poly object handles polyphonic voice allocation. That is, it segregates a single stream of incoming MIDI note data into several streams sent on different channels.

Table and Stack Objects

This set of objects act as compound data structures. That is, they contain more than one item in the form of an array or a stack. The table object opens up a subwindow with a rectangular drawing surface. The bag is a kind of stack. That is, it maintains a list of integers that you can insert/delete and dump. The funbuff object stores sets of (x, y) values that can grow and shrink dynamically.

Signal Processing Objects

Signal processing objects handle audio signals. They include the following:
sig~
converts a constant to a signal, so it can be input to a signal object

phasor~
a sawtooth generator

osc1~
interpolating table lookup oscillator

tab1~
specifies envelopes, waveforms, and other functions that osc1~ refers to.

sig~
converts messages to signals

line~
generates ramps (for envelope generators)

snapshot~
converts signals to messages.

dac~ and adc~
generate and sample audio signals

writesf~
writes a signal to a sound file on disk

print~
prints signal values on the Max window

up~ and down~
double and halve the sample rates of their inputs

delwrite~
defines a delay line and writes a signal into it

delread~
inserts a noninterpolating tap into a delay line

vd~
provides a variable-delay, interpolating tap

table~
defines a sample table

sampread~ and sampwrite~
read and write sound from/to the defined sample table

samppeek~
provides a message interface for reading samples

2pole~ and 2p2z~
are two-pole and two-pole-two-zero recursive filters, respectively

wahwah~
is a variation of 2pole~ that lets you specify center frequency and filter Q

samphold~
is a sample-and-hold unit

clip~
limits the values of a signal to a given range.

Control Objects Versus Signal Processing Objects

A fundamental distinction in Max is the division between control objects and signal processing (or DSP) objects. It is easy to tell the difference between the two types by their names. In particular, signal objects always end in tilde (~), as in osc1~. Control objects are so-named because they usually implement the logical operations in a patch; they react to external events and make decisions. By contrast, signal processing objects handle audio signals. They generate streams of sound samples or process incoming samples from the ADCs and digital input ports of the IRCAM Musical Workstation. This distinction is fundamental because it also applies to the data passed between objects. Every type of data except audio signals is considered to be a message. The inlets and outlets of control objects only deal with messages. Correspondingly, the inlets and outlets of signal processing objects may handle both signals and messages, depending on the specific object. Constants and other parameters have to be converted to signals (using sig~) before they can be accepted by a signal processing object. The next two sections explain the operation of control and signal processing objects, respectively.

Operation of Control Objects

Control objects are event-driven. That is, they perform computations only in reaction to an action.This action is usually caused by a message coming down a line to one of its inlets, but an action also occurs when timer goes off or when one clicks on the box. When any of these events happen, control passes to that object. The object can send messages down lines connected to its outlets, draw something on the screen, or set a timer.

Operation of Signal Processing Objects

Digital signal processing (DSP) objects manipulate signals. Signals can be thought of as streams of messages, where each message is an audio sample. Signals flow through a Max patch at the sampling rate. Internally, the DSP objects handle signals in blocks of 64 samples at a time. That is, every 64 sample periods, all running DSP objects perform their operations. Keep in mind that although an inlet on a DSP object accepts only a single signal, it may also take a control message. Contrast this with control objects whose inlets handle many message inputs.

Activating and Deactivating the Signal Processing Network

A Max patch with signal objects is a kind of signal processing network. To turn this network on and off globally, send start and stop messages, respectively, to a dac~ or adc~ object. Another way to start the network is with the following message, typed in a message box:

For now, ignore the initial semicolon in the message box. We will explain the syntax of message boxes later. Typing a 0 instead of 1 shuts off the network. A status inquiry message such as:

(i.e., the message print sent to the object named max) prints the status of the signal processing network, including idle time and number of signal buffers used.

Sampling Rates Supported

Signals (i.e., the objects emitted from signal outlets), can have different sampling rates. The available rates are R, R/2, R/4, and R/8, if R is the dac sampling rate. The DAC sampling rate is 44100 by default but can be overridden in the Max command line if you call Max from a shell. The up~ and down~ objects perform sample rate conversion.

Messages in Max

Messages passed between objects can consist of integers, floating-point numbers, or symbols. A slider, for example, sends integer messages like 123. The most frequent messages sent and received by objects are numbers, lists of numbers, and the symbol bang, which is widely used as a trigger to initiate some sort of processing. By convention, when an object has more than one inlet, its leftmost inlet is the "active" one. Sending a message to that inlet causes something to happen, and sending messages to the other inlets simply changes the internal state of the object. For example, the object {* 10} multiplies two numbers taken in from the two inlets (call them x and y). The values of x and y are initially 0 and 10. When the number 5, is sent to the left inlet, x is set to five and the box sends the product x * y, which is 50:

® 50

If you send the number 3 to the right inlet, y is set to 3 but nothing is output, because there is noting in the left input to trigger the multiplication:

® Æ

Now send 2 to the left inlet and you obtain 2 * 3 or 6 at the output:

® 6

This is because the 3 in the right inlet overrides the default value of 10 in the multiply box.

Message Boxes

Most objects send preset messages. For example, a slider object sends out a number between 0 and 127; the Max Object Reference lists the messages emitted by each object. To send a message that is not preset, or to send several messages at a time, use a message box, which looks blank like this when you first drag it down from the object palette:

To specify the message you want to send, type some text into the box. To send the message, connect it to another object, such as print. Then in run mode, click on the object. The print object types the message it receives in the MAX window.

Other ways to trigger the message-sending are to send the message box a bang, or a number, symbol, or list.

Sending Multiple Messages

A message object can send more than one message; the only limitation is that there can be no more than 256 atoms in a text box. Multiple messages are separated by commas (,) or semicolons (;). They can be sent via the message box's outlet or to a named receive object. (A receive object is a kind of "wireless" message receiver; you don't have to make a graphical connection to it; it lets you transmit global messages across patchers, for example. We present more on send and receive objects later.)

The rules for sending multiple messages are straightforward.

As an example of the first rule, the message box:

sends the messages 1, 2, 3, and 4 to its outlet, one after the other, each time it receives an appropriate trigger (such as a bang or a mouse click). As an example of the second rule, the message box:

sends walk the dog to its outlet and water the horse to a receive object named Dot, as the following diagram shows:

To connected To unconnected inlet object named Dot There is no need to send anything directly to the outlet of a message box. Look at the following message box:This sends the message 5 to a receive object named Paris and 3 to a receive object named Lyon.

We'll explain receive objects in a moment.

Message Arguments

If you activate a message box with a number or a list, you can use the information you receive in the message via the arguments, which in Max are labeled $1 through $9. For example, if you send the message box a number, $1 becomes that number and its arguments $2 through $9 are 0 (integer). Consider the following patch:

Here the argument $1 takes the value 23.7. If you send a message box a list, the arguments $1 through $9 are replaced by the first nine arguments of the list; if the list has less than nine arguments the remaining arguments are set to 0. If you send:

the lower message box sends the three messages 144, 60, and 100. Notice that this is a simple way to format raw MIDI messages out of a stream of notes.

Sending, Receiving, and Accessing Global Values

We have seen how communication in Max is usually handled via patch cords between object boxes. This representation provides a graphical picture of data flow in a Max program. In many instances, however, patch cords are not desirable or possible. Sometimes the screen is too cluttered with cords, or one wants to send a message to many subpatches at a time. For these cases, Max has a "wireless" and "global" communication mode using the send (or s), receive (or r), and value objects. It is wireless because one can access and transmit values without patch cords. It is global because these objects can communicate across any open patch. Recall our previous example of a message box:

¨ water the horse

The receive box named Dot gets the message and prints it even though there is no patch cord connecting it to the message box. You must name send, receive, and value objects. Their name serves as their link to the rest of the world. While send and receive do as their name implies with messages, the value object serves as Max's form of global variable. That is, you can assign a number or symbol to a value object and then access this number or symbol from any open patch, without a patch cord link. Another type of named object is a table object+/-an array with a graphical display. Send and receive make a pair that can share the same name. Once this name is taken by a send/receive pair, you can't give a table object the same name. The send object is somewhat faster than a generic message box for specific send/receive communications.

Special Characters in Max Messages

To fully understand Max message passing you have to know certain special characters, listed below:
,
Splits a single message into two messages
;
Sends a message to a named receiver
$
Specifies a placeholder for an argument
#
Specifies a placeholder for an argument in abstractions
\
Converts a special character into an ordinary character

Changing the Contents of a Message Box

You can change the contents of a message box dynamically with the set and append messages. The contents can be any mixture of symbols and numbers. The message can contain the special characters comma, semicolon, or dollar sign in is they are preceded by a backslash (\); for instance the message set \; foop 12-tone sets the contents of a message box to:

Importance of Message Order

Understanding the protocols for message order is one of the most direct paths to Max enlightenment. Since the receipt of a message in the left inlet of an object box initiates computation, it is important to to send messages to their destinations in the correct order. This usually means sending messages in right-to-left order, initiating computation with the last argument, which is sent to the left inlet. In general,the order that an object sends a message down the lines connecting it to other boxes is not predefined by Max. A simple example helps show this. Look at the patch below, which connects a message box to a + box. This patch sends two copies of the number 2 into the inlets of the + box, which computes the sum of its two inputs and emits the result via its outlet.

This patch, as simple as it looks, is not guaranteed to put 4 on its outlet every time you activate the message box. It might be that a 2 is sent to the left inlet first, initiating computation before the other 2 is received in the right inlet. Since the + object has default arguments of 0, it emits the value 2 instead of the intended 4. What is more, the patch immediately hides the evidence of what happened, setting the right inlet to 2 before finishing. Since Max does not guarantee message order, confusions in message order result in patches that sometimes work as intended as sometimes not. Nonetheless, there are two popular techniques for ensuring proper message order: Note: There are two exceptions to the "right-to-left" inlet rule: timer and gate; see the Max Object Reference volume.

Using Multiple Outlets

By convention, objects with more than one outlet activate their outlets from from right to left. Thus it is often possible to make definite connections like the following:

The ctlin object passes all incoming MIDI control changes to its outlet. The ctlout object passes control change message to the MIDI output port. Its right inlet interprets the incoming message as the channel number on which to transmit the control change message. Thus this patch repeats all incoming control change messages to the MIDI output with the channel offset by one. There is no order problem for ctlout because it receives its leftmost value last, after its channel number value correctly.

Sending List Messages to the Left Inlet

If you send a list (any message that starts with a number and also has other arguments) to the left inlet of an object, the items of the list are passed to the corresponding inlets, in right to left order. Note: Lists should be sent only to the left inlet of a box. (A minor exception is midiformat; see the Max Object Reference.) Thus to avoid ambiguity in the 2+2 example previously shown one could use the following patch:

When there are more arguments in the message list than there are inlets, extra arguments are dropped starting from the rightmost and moving left. Thus the following patch:

adds 3 and 4 and discards the 5. The next example shows how a list with fewer elements than there are inlets does not affect the unused inlets.

This patch sets the left inlet (a control value) to 127, and sets the middle inlet (a controller number) to 16. The right inlet (a MIDI channel) is not affected.

Optional Arguments to Inlets

By convention, boxes that have more than one inlet can take optional arguments to "preset" the value at the inlets. This convenience can save work when the value in question is often left constant. Even if you preset an inlet's value, you can override it with a message. There is one exception to this rule: an argument can never be applied to the leftmost inlet. The left inlet must always be free to accept an initiating message. Not every object handles optional arguments. Refer to the IRCAM Max Object Reference manual for details on a particular object.

Making Subpatches

Subpatches let you break the spaghetti of a complicated patch into a collection of simpler modular units. To make a subpatcher, type the word patcher in the object box; a new subpatcher window appears on the screen. We'll call the subpatch the child and the initial patch the parent. To communicate between the parent and the child you can select and drag down inlets and outlets while in the child. These appear in the parent as dark rectangles on the patcher box in the parent. For instance, if the subpatcher has the following inlets and outlets:

the patcher appears with two inlets and three outlets:

If you send any message to an inlet of parent patcher the message appears on the corresponding inlet in the child; if you send a message to any outlet in the child, it comes out of one of the outlets of the parent. Sub-patchers can in turn have their own subpatchers, and so on, to any depth. You can name subpatches by typing a symbol after the word patcher. When you are editing, use the Windows menu in Max to navigate around patch and subpatch windows. In Run mode, double-click on a patcher object to see the subpatch. Notice that the name of the subpatcher window is enclosed in brackets. When a subpatch contains another subpatch, the name is enclosed in two sets of brackets. Thus the brackets indicate the sublevel offefe the patch hierarchy.

Making Abstractions

Subpatches are quite useful, but they only work within a single Max program. What if you have created a subpatch that could serve a useful function in many programs? Max lets you create abstractions+/-subpatches that are stored a file and act as library functions that can be accessed by many programs. To make an abstraction, type the name of an already-saved patch in an object box. This patch must reside in one of the following: