LFO Tutorial, Part 1

From Cycling '74 Wiki
(Difference between revisions)
Jump to: navigation, search
(Using the LFOur Patch)
(Using the LFOur Patch)
Line 111: Line 111:
* There are four outputs (named ''nvA'' - ''nvD'') that correspond to the note values for LFOs A, B, C, and D. The messages sent correspond to what you see on the control panels for each of the four LFOs (e.g. the output is sent to an '''r nvA''' object would be ''1n'').
<img>" alt="" width="176" height="72" /> <br />
* An output named ''wavelist'' continually outputs the current value of the scaled integer values (in the range 0 - 127) shown in the moving window display.

Revision as of 15:59, 10 February 2013

Download the patches used in this tutorial


The Zen of the Silent Patch

Just as there are always several ways to do any given thing in Max, so there are several different ways to end the sentence, "One of the cool new things in Max is...."

One of those things that piqued my interest is the ability to specify time in Max in ways that make so-called "musical" sense; in addition to creating metronomes that send out a bang every 100 milliseconds, you can now work with lots of new and interesting ways to specify time: ISO 8601-format time, samples, "ticks" and note values. There's a long list of objects you can work with (you can find that list here, both older Max objects as well as some new objects that help you take advantage of them (timepoint, when, and combine). While lots of people are interested in using the Max transport object to arrange and trigger events in time, I'm personally a lot more interested in the ability to synchronize processes in Max using time values that resemble musical note values to create control structures that can be easily time synced.

This may be because I have a deep and abiding love for some of the interesting and esoteric control voltage uses of the LFO (Low Frequency Oscillator) in traditional analog synthesis. I'm thinking of analog modules like this - a cool set of LFOs that can be combined to achieve interesting effects (Anybody want to sell me a beat-up old AKS Sythi on the cheap? <SFX: crickets> No? And you wonder why I patch...). The great thing about Max is that you can produce the Max equivalent of these great general-purpose modules, and use them in any way you want. In fact, I'll often create patches like this and then spend the next few weeks hooking them up to all the patches I've got sitting around to see what they can do.

This tutorial is about making one of those kinds of modules - a quartet of synchronized LFOs whose outputs I can sample individually for several kinds of data (triggers for waveform start, LFO outputs that I can sample at variably synchronized rates, and a nifty summed waveform I can use for more exotic kinds of control).

Note: The downloadable materials that accompany this tutorial contain not only the large patch I'm going to talk about making, but a number of the little steps along the way - feel free to take the pieces and tear them apart and make things that are interesting to you, in addition to following along.

Humble beginnings

Here's what I usually use to create LFOs in Max.

You might have been expecting to see a cycle~ object here instead of The phasor~ object. While you could certainly use cycle~ objects for your waveform output, I prefer to use the phasor~ - a Max object that outputs a ramp that cycles between the floating point values 0. and 1.0 at a rate you specify.

The cos~ object will take the output of a phasor~ object and produce a nice sinusoidal waveform with the standard -1.0 to 1.0 output range. The nice thing about using a phasor~ is that I can also easily produce a sawtooth LFO output by adding a pair of objects that change the range of the phasor~ object's output. (For extra credit, you might think about how you could generate a triangle wave using a phasor~ as a source. Yes, I know - you could just slap a triangle~ object below the phasor~ in the patch, but I'm encouraging you to think about signal math. If that seems too easy for you, how would you produce a square wave?

Now that we've got two waveforms, what kinds of useful information can we extract for our use? Since the waveform's output is happening at audio rate, we'll need to sample its output. Personally, I prefer to use the snapshot~ object, which samples a waveform output at whatever millisecond interval I provide as an argument. I'll probably need to do some linear mapping of the resulting numerical output into a more useful range of numbers, but I'll get to that in a minute. I'd also be interested in sending a bang message every time my waveform began its cycle. The example above shows how you can do this using two simple Max objects – a >=~ (greater than/equal to comparison signal object) followed by the handy edge~ object that detects zero to non-zero signal transitions (and vice-versa, too). Beginning Max users might wish to meditate on this pair of objects in the course of their quest for enlightenment.


The rate~ object takes a phasor~ as an input source, and produces the same kind of output (0. - 1.0) time-scaled by the number specified as an argument or sent to the object's right inlet. In the previous Max 4.x world, this was the only reliable way to synchronize any two LFOs. While there's a new way to do that now (shown on the right-hand side of the patch below), the rate~ object will still be really useful, as you'll soon see.

As I mentioned earlier, Max gives you ways to specify time in Max which use terminology that is more explicitly "musical” in addition to the old school metronomes that send out a bang every 100 milliseconds, you can now work with different “kinds” of time: ISO 8601-format time, samples, and the time format we'll be using in this tutorial - note values. Since I'm interested in the ability to synchronize processes in Max using time values that resemble musical note values, I’ll use note values – whole notes, half notes, etc. – to set the rate of my LFO. Here's a simple example:

This patch contains the familiar phasor~ object, but instead of using an argument to specify a frequency for the ramp, I've used different arguments to each phasor~ object (1n and (2n), and I've also added an attribute called (lock), set to a value of 1 (on). The arguments 1n) and 2n) refer to note values - in this case, a whole note and a half note (you can find a complete listing of these note numbers here).


But what are the phasor~ objects locked to?

A Transport of Joy

In Max, a central timekeeping object called transport is used to handle metrical timing. The transport object not only keeps track of time, but broadcasts information to any Max objects in your patch that are "listening" or expecting timing information. When we use a note value argument with the phasor~ object, we're telling the object that it will need to listen for timing instructions.

While you can add transport objects to your patch (and even have different transport objects running at different rates controlling different sets of Max objects in a single patch), Max 5 includes a handy Global Transport - a default source of timing information that is ready any time you launch Max. You can find the global transport by choosing GlobalTransport from the Max Extras menu

The Global Transport has an on/off switch (the button to the right of the word Activate", a flashing LED indicator, displays bar/beat/unit timing and temp, and a display that shows the current "position" of the transport since you've started it.



  • Click on the ezdac~ object;
  • Click on the Global Transport's activate button.

Once the Global Transport is running, you'll see a pair of synchronized waveforms, and you can use the umenu objects to change their relative rates on the fly.

Now that we've got a great way to product perfectly synchronized LFO waveforms, let's go back to our earlier LFO examples and add some additional functionality. Of course, since our locked phasor~ objects are producing beautifully choreographed ramp outputs, they'll also be outputting beautiful sine waves when we use the cos~ object. And while we don't really need the rate~ object to synchronize the phasor~ objects' outputs any more, it's still useful. Suppose we want to produce a nicely synchronized waveform that repeats at a period that's greater than a dotted whole note (1nd, the largest time increment we can specify using note values)? Easy - we can use our old friend the rate~ object to scale the output of the locked phasor~ objects to longer time periods.

And while we're at it, it would also be nice to be able to invert the waveform phase outputs, too. That's an easy one - just multiply the signal by a value of -1.0. The following example patch adds all of these features, and a set of switches that let us configure our output

It's hard to stare at any number of simultaneously synchronized LFOs and not feel the urge to sum those waveforms to produce lovely new shapes, if only for the pleasure of watching them. It's easy enough to do - you just scale the output of each waveform by the reciprocal of the number of waveforms you want to sum (1/2 or .5, 1/3 or .33, etc.) and then add them together.

And for one final touch, I think I'd like to be able to sample the LFO waveform output at a rate which is independent of the waveform itself, but still synced to the "global" rate of the Global transport. In this example patch, I'm sampling the waveform output with a snapshot~ object, and using the scale object to map the waveform's output data range from -1.0 - 1.0 to a more MIDI-friendly range. That data stream is then sent to the right inlet of an int object, whose current value will be output any time a bang is sent to the left inlet of the int object. The source of that bang comes from another Max object that can take advantage of the new timing values - the metro object. I've used a note value argument to set the rate at which the metro object sends bangs rather than the more common number argument (which specifies milliseconds), so the metronome is now also outputting its bangs at a rate derived from the Global Transport.

Putting It All Together

All of these little component level solutions are used in the giant example patch called LFOur.maxpat - which, as its title implies, contains FOur different and independent LFOs. Although the patch is pretty large, it contains all the little techniques you've seen so far.


Max 5 makes it really easy to create user interfaces using The Presentation Mode. You can find a good tutorial on it here, and Andrew Benson has written a great tutorial on creating interfaces, as well. Working in Max 5, I now find that using the Presentation Layer to prototype interface designs accounts for a lot of my patching time these days; the patch that you see when you launch the LFOur patch is the presentation layer arrangement I decided on. Since I've set this patch to open up in Presentation mode and show you the user interface, you’ll need to do two things:







Using the LFOur Patch

Of course, this patch doesn't make any noise at all, although it is interesting to play with and restfully instructive to watch. LFOur is useful because of a key idea in Max: data spaces are global; any time you have a send object sending data to a destination named "suitcase", any receive object in any Max patch you have open and running with a receive object that specifies "suitcase" as its source will receive and output the message. So I run my LFOur patch alongside whatever Max patch I want to use it with, and as long as I've added receive objects with arguments that correspond to the names of the send objects in the LFOur patch, I've got data to work with. In addition, I've added a few receive objects that will let you control some functions of the LFOur patch from your patch.Here's a listing of the data that my LFOur patch makes available when it is running:




  • There are four outputs (sampA - sampD) that correspond to the most recently sampled waveform output value (in the range 0-127) driven by the notevalue sampling rate. These values are displayed above the display on the far right.

  • There are four outputs (named bangA - bangD), each of which triggers at the start of the waveform's output. Each bang is displayed above the third output display.



Next time, we'll create a simple patch that uses the LFOur patch to make some noise.

Other LFO Tutorials