The first half of the title says it all - this is the first in a series of articles about getting used to the gen~ patching environment if you're a beginner - and yes, I mean beginners. The goal of this series of articles is about becoming comfortable with the gen~ object, and the approaches you might take to do interesting work. I'm not going to be talking about what is necessarily the most clever way or the most efficient way to do something - in my experience, clever solutions often leave beginners feeling uncomfortable. I am also solidly with my friend Perry Cook’s advice on designing new musical instruments that you can find in his 2001 NIME keynote address on the subject:
Instant music, subtlety later
All the tutorials in this series: Part 1, Part 2, Part 3, Part 4, Part 5, Part 6, Part 7 Follow-up video tutorials: Working with Abstractions, Debugging and Signal-Rate Processing This is also going to be a little different kind of tutorial because I’m starting out by asking a few questions. In the course of talks with beginner Max users that are interested in learning gen~, there are some common things I’ve encountered again and again.
- New users are curious not only about what gen~ is, but what it is that’s special about it and why they might want to invest the time to learn it. While it’s always fun to learn new things - and learning to work with gen~ is really worth the time, I think - you might want to know what really practical advantages it offers.
- It’s also the case that there’s a kind of anxiety associated with encountering gen~ for the first time. It’s like working with Max/MSP in some ways (there’s a patcher window that you add things to and connect together to make a patch that does something), and unfamiliar in some other ways. The balance between similar and different can be unnerving when you are just starting out.
For example, you may have noticed some odd things the first time you opened someone else’s gen~ patchers:
- Some of the operators have names you recognize, but they're missing the tilde (~) you associate with MSP audio-rate objects. Simply put, there are no tildes because everything in a gen~ patcher is running at single-sample rate. They are all equal.
- If and when you start adding operators and paying attention to autocompletion, it becomes clear that the set of operators you have to work with isn't exactly like MSP. However, some gen~ operators look and act very much like their MSP counterparts. How do you find out what’s what?
- Sometimes, even objects you think you recognize look different inside of Gen - operators inside of a gen~ patcher window may have a different numbers of inlets than their Max equivalent. From time to time, you may even see two identical operators with the same name and different numbers of inlets.
These are sources of real anxiety, since so many other things look the same as Max. Another goal in this series is to try to work a kind of gen~ Anxiety Top Ten that seeks to explain the things that are scary or different and to explain why they are the way they are. I also hope to provide some examples of how we solve certain kinds of problems in the Gen environment in light of those differences. There may not wind up being 10 top items, but I think you can get the point.
Why Would/Should I Learn gen~, anyway?
The gen~ environment is fun to mess around with in the same way that MSP is: you crack open a gen~ object, add a few operators, and you can hack audio programming while you listen to the results. While it’s always fun to learn and engage with new things, our time is limited, so there’s nothing wrong with wanting to know up front why it’s useful to learn the new thing. Here are some areas where people with whom I’ve interacted with have found learning gen~ to be useful:
- While the Max world is full of lots of objects created by both Cycling ‘74 and the Max community, you may find yourself in a situation where there’s no clear solution for the problem you wanted to solve. Before Gen, your only other choice was to download the Max SDK and create your own external objects. Working with the gen~ object provides you with a third option - a way to make your own custom compiled MSP object without ever having to leave the Max environment.
- Here’s an advantage to using the gen~ object that may not be apparent, but which might be useful to you regardless of your experience level: using gen~ as a way to achieve greater efficiency as you patch. Within the gen~ environment, you can create reusable bits of programming that you use in much the same way as you use abstractions in Max. One of the advantages of this ability is that you can create gen~ patches that gang together smaller units inside of a single gen~ object. For example, a multi-channel panner/filter/mixer gen~ patch you create can run with greater efficiency than a similar MSP patch composed of individual objects and abstractions. And the components used don’t have to be complex to see an efficiency improvement. My colleague (and the father of the gen~ object) Graham Wakefield shared an interesting table with some numbers on this subject (see below).
- MSP works by processing blocks of samples (called signal vectors). The size of the signal vector was the smallest slice available to you when working with things like delay times, and it meant that there were classes of things - single-sample delay processing or Karplus-Strong plucked string synthesis being two examples - that you really couldn’t do at all. The gen~ environment operates on single samples, so you can start to investigate some new possibilities.
- There are procedural programming structures that textual coding languages use that are either difficult or impossible to do in Max - if/then/else conditional statements, or while and for loops. The gen~ environment gives you a way to include them by using the Gen codebox operator (I’ll have more to say about this in an upcoming installment of this series). The codebox operator may also be of interest to Max users who actually enjoy writing code or who are interested in porting other people’s examples of textual code (e.g. musicdsp.org) to the GenExpr language that Gen uses internally.
- And finally, you can take the contents of your gen~ object and export those contents as C++ code for reuse anywhere where C++ dsp code is useful. In addition to just producing the code, there are audio processing devices out there that let you directly export your gen~ code to run on their devices. The OWL pedal and the MOD devices MOD Duo are two examples - and there are more of these on the way.
The Reduction of Anxiety
If you’re interested in any of the five things I’ve listed above, then you’re officially a potential gen~ user. So let’s move on to the next bit: Overcoming gen~ anxiety.
Over the course of several years, I’ve come to see a particular kind of problem that working in the Gen environment presents: When your beginner self adds a gen~ object to your patch and double-clicks on it to open it, you find yourself in a window that looks like a Max patcher window, but.. it's not. It's got a different-looking toolbar. You’re not sure how to get help, or how to discover what the objects in a gen~ patch do, and even if you figure out things are different, it's hard to know how they're different. The sum total of those differences can seem overwhelming upon first encounter.
Over the next few weeks, we are going to look at some things I’ve found help new users make sense of the new gen~ world. They’re small things - often simpler than the smallest of example patches - that will assist you in your transition to having fun with gen~.
Sigmund Freud used to describe the purpose of psychotherapy as "the conversion of hysterical misery into common unhappiness." I think that anyone who wants to teach beginners has a kind of common goal - converting hysterical anxiety to common uncertainty. Uncertainty over solving a specific problem is much simpler to deal with than being generally bewildered by the environment in which you find yourself. Here begins an ongoing list of entries from my official gen~ Anxiety Top Ten.
The gen~ Patcher Window and gen~ help
This week, let’s start with the obvious. When you double-click to open a gen~ patcher window, you’ll see something that looks like a Max patcher window, but is a little different. Never fear - as a beginner, there are really a couple of things you need to care about.
The first one’s obvious: the locking/unlocking the patcher window is just like Max - a lock in the lower left-hand corner of the patcher window.
The upper toolbar reflects the fact that the operators available to you don’t include any UI objects (gen~ patchers don’t have ‘em), and the right-hand toolbar will also look familiar, with the exception of the C (Code) icon - a part of the gen~ patcher window that will become a close friend. The patcher window differences from Max are minimal and easy to get used to - locking/unlocking your patch and using the Code window are all you’ll really need to know, for now.
One way in which the Gen patching environment is a little different has to do with its discoverability. In an unlocked gen~ patcher window, option-clicking (Macintosh) or alt-clicking (Windows) on any operator will display a reference-like description of the object in a scrolling pop-up window. Since gen~ operators tend to be more low-level than their Max relatives, text files can be clear and concise. Unlike Max help files, we treat examples as separate items in the Gen environment.
Note: To open a full listing of all general objects in the standard Max Documentation Browser, click on the information icon (that little circle with the “i” in it) in the pop-up window. Your selection will appear as the top line of the displayed listing.
Hovering over any inlet or outlet of a gen~ operator will display a Max assistance bubble with information about the inlet or outlet.
When you work with in a gen~ patcher window, you’ll notice that a new icon is displayed on the patcher window’s right border – the Code tab. Clicking on the Code tab’s icon will display the actual code that Gen operators use (called GenExpr) to produce the machine code compiled as you work.
Clicking on any operator in your gen~ patch will highlight the code associated with that operator. As you patch, you can watch the code change in real time as your changes are recompiled in the background. This window is really useful for things like discovering what the default state of an operator is, and in working with the codebox operator. The Reference icon in a gen~ patcher window behaves similarly to the Reference icon in a Max patcher window: Displaying this window and clicking on an operator displays information about inlets and outlets and attributes associated with an operator.
That’s how you can navigate and figure things out in the gen~ patching environment.
Generally speaking (cough), the Gen environment consists of a smaller set of objects than you’re accustomed to working with in the MSP environment. The operators in the set you’ll work with are inspired by Max/MSP objects, and they’ll often have the same name as their MSP counterparts. In general, the easiest way to think of the gen~ environment is that most low-level MSP object equivalents exist, and the gen~ operators will have more streamlined functionality. The helpfiles in the gen~ environment are textual rather than oriented toward a variety of uses (when it comes to working with buffers, things are a little different, and we’ll talk about that in detail in a later tutorial) - if you don’t find what you’re looking for in that list of Gen operators The gen~ examples folder contains many examples of how the Gen operator set can be used to create patchers that closely resemble the higher-level functionality of other MSP objects. In coming installments, we'll be looking at strategies you can use to extend the usefulness of gen~ operators in simple but useful ways.
In Part 2, we'll work on your gen~ anxieties by starting to take a look at some of the similarities and differences in the Max and Gen patching environments. Until next time, open the gen~ examples folder and have a look around!