Max Tutorial #10: Randomness as Control

In the previous tutorial, we used [random] to generate a random stream of notes. As you’ll recall, the possible outcomes were a function of two elements working together: a range determined by an integer into the right inlet of [random], and an offset determined by the [+] object. Because the random numbers represent the actual pitches (via MIDI note numbers) of the output, we can say that we are using randomness to generate musical material. Consequently, we would characterize this approach as “generative.”

Another way of using randomness is to “control” other parts of the patch. Instead of generating material, we use randomness to point to specific values that are already stored in other parts of the patch. One of the ways that we have previously stored values is in the sequencer patch, using the [multislider] object. We’ll start off the video by recreating the simple sequencer that we built in an earlier tutorial: using [counter] to control an eight-step sequencer where the pitches are determined by the values of [multislider]. Note that although this patch is technically simple and very similar to previous tutorials, the switch to thinking in terms of “control” functions involves some conceptual explanation (hence the length of this write-up).

We’ll recall that [counter 1 8] will always count up from 1 to 8 and then loop back to 1 again. This pattern ensures that we always move through the sequencer in exactly the same way, from step 1 to step 8. By using randomness, however, we can jump between steps unpredictably, meaning that we play the same notes as before, but in a constantly changing order. We’ll start off with a [random 8] object in place of the [counter]. However, since [random 8] gives us values between 0 and 7, we need to add a [+ 1] offset for the correct range of 1 to 8 (this is the range that [multislider] is expecting).

If we start up [metro] again, we hear a scrambled version of the original pattern that is constantly changing. Again, the notes are the same, but the order is different. We can take things a step further by customizing the “kind” of randomness we want. For example, when we think of something that sounds random, we often think of something that doesn’t repeat. The [random] object has no constraints on repetition: each random value is generated independently of the previous value, so it is perfectly possible to produce the same number twice (or, rarely, even more times) in a row. In musical terms, this means we hear the same note multiple times in a row—something we hear several times in this example.

If we want to specify random number generation without repetition, we can use a different object called [urn]. The [urn] object is similar to the [random] object, except that once it outputs a value it never outputs that value again. For [urn 8], that means that we’ll hear exactly 8 notes, and then silence. In order to continue to hear more notes, we must reset the object. Luckily, [urn] is built to make this easy.

When [urn] has gone through all of its notes, it sends a bang out its right outlet. This is a signal that [urn] needs to be reset or there will be no more output. To reset [urn], we have to send a message comprising the word “clear” to the left inlet. Therefore, to smoothly reset [urn] each time it runs through its entire range of numbers, we want to connect the right outlet with a clear message sent to the left inlet. This is one of the few exceptions to the rule that patch cables should never go “up” on screen. Here, the output of the [urn] object is actually feeding back into the input (albeit in a very specific way so as not to produce a feedback loop).

In making this feedback connection, we actually have to do two things: we have to reset the object with “clear,” but then we also have to send a bang if we want the rhythm to remain consistent. If we don’t send a bang here, we will have a silent beat each time we reset the object, since [urn] sends a bang out of the right outlet only after it has finished outputting all of its numbers from the left.

This is also a moment where the order of operations is very important. In the space of a single step of the sequencer, we must first clear the object, and then send the bang through. If the order were reversed, we would create a feedback loop in which the bang out the right outlet was continually passed into the left inlet to create a new bang out the right outlet, never actually resetting the object. For this reason, we use the trigger object [t] to force the order.

Recall that the [t] object executes from right to left: whatever we want to happen first must be to the right, and whatever last must be to the left. Therefore, we want our clear message on the right, and our bang on the left. One handy thing about the trigger object is that, in addition to passing data through (by using letters like “i” and “b”), the [t] object can also send one-word messages, like “clear.” Therefore, instead of connecting [t] to a separate message box, we can actually just type the word “clear” into [t] as shown.

The final object should be [t b clear], with both outlets connecting to the left inlet of [urn]. This ensures that each time [urn] runs through its range, it is automatically reset and a new sequence of eight random values begins again. Note that these values refer to the steps of the sequencer, meaning that they are “controlling” the sequencer, rather than generating musical material such as pitches. This will also prevent (almost) any possibility of repetition amongst the notes.