Category Archives: max-lecturenotes

max max-lecturenotes

(max) resonators and more poly~

High feedback, short-time delay lines can be used to resonate specified frequencies in a source signal. It’s the principle behind the resonators module in Cecilia. Creating a usable Max patch that performs this function takes a few steps, but can produce some very interesting sonic results.

To follow the discussion, you need to download the parent patcher, ResonatorBank.maxpat, and the poly~ subpatcher resonatorDelay~.maxpat.

specifying delay times as a function of pitch

For usability purposes, it is easier to specify the pitch you want to resonate, and convert that pitch to a corresponding delay time. In other words, you want to find the period of the frequency. The math to do that is simple:

T = 1/f

In Max, time is specified in milliseconds by default, so you would modify the equation to:

T = 1000/f

The subpatcher (p) midiToDelayTime performs this function, expecting pitch input in the form of MIDI note. The parent patch is setup to input MIDI notes from a MIDI keyboard or use a coll object to store sets of pitches (counted and routed to the different voices of the resonator bank). The converted delay times are sent to individual voices of the poly~ resonatorDelay by use of the target message.

using poly~ to create a bank of resonators, and more

By using poly~ we can create a bank of resonator processors. The resonatorDelay~ subpatcher is just a delay line (tapin~/tapout~) with feedback and adjustable output gain. (You need to adjust output gain down significantly as you increase delay line feedback.) But the use of poly~ allows for the adjustment of one additional, extremely needed parameter: signal vector size. The signal vector size determines the number of samples in a vector that are operated on in one function, and the size divided by the sample rate determines your minimum possible delay time. Smaller vectors give shorter possible delay times, but add a heavy hit to your cpu load. You can specify a different signal vector size for a poly~ object by use of the @vs attribute. The smaller vector applies only to the poly~ object, and won’t affect your cpu load as much as if you set the small size for the entire patcher. In the example patcher, I’ve set the signal vector size to 8 samples.

To understand the difference, Max usually operates at a 64 sample vector size (viewable in the audio status window). That size gives a minimum delay time of

64/44,100 = (approx) 1.45 ms, or about F5

Moving the signal vector size to 8 samples gives a minimum delay time of

8/44,100 = (approx) 0.18 ms, or about E8

Using the small vector size only in the poly~ saves you a few % points of cpu load, which can help in a complicated, processor-intensive patcher.

final note

You will notice that audio input and delay times to the poly~ are both sent to the first inlet. This combination works because the resonatorDelay~ subpatch defines both an in~ 1 (audio input to first inlet) and in 1 (data input to first inlet). Max understands to route the inputs by data type in the subpatch. Combining data inputs in a single inlet can help you reduce the number of inlets you need for a subpatch. Many audio objects make use of this data handling ability.

max max-lecturenotes

(max) groove~ and buffer~: playing audio from RAM

We’re transitioning from synthesis to audio playback from buffers, which allows us to manipulate and process audio in live performance. The basic object for all of these functions is buffer~.

Example patcher: GrooveSimple.maxpat


buffer~ holds an audio file in RAM. The basic parameters are the buffer name, length in ms, and number of channels. The buffer name is essential so that other objects can access the contents of the buffer for playback, processing, or other info. You have to define a length, but you don’t need to over-stress about the size. I usually specify large buffers because RAM is generally abundant.

You generally input audio into a buffer~ in one of three ways: read, replace, or record. Read and replace bring up the standard Mac file dialog window and let you choose a file (unless you specify a filename along with the message). Read keeps the buffer length and number of channels as specified in the arguments. Replace resizes the buffer to fit the new file, and also changes the number of channels to match. I tend to favor using replace.


groove~ allows for ratio-based playback of audio from a buffer~, with looping and continuously variable speed control. Some things to keep in mind:

  • playback ratio has to be sent as a signal to groove~. The usual method is a float sent to sig~. Unity playback is 1. You can also reverse audio with negative ratios.
  • if no loop points are sent to groove~, the entire buffer will be looped.
  • a float sent to the left inlet sets the time of the playback head. You have to set the playback head before initial playback, as well as after reaching the end of the buffer if looping is not enabled.
max max-lecturenotes

(max) project 2: synthesis

MUST 450 (342—Computer Music II)
Project 2 | Audio/Synthesis Performance Patch
DUE: 3/24/14

ASSIGNMENT: to create an audio performance patch that utilizes several different methods of data manipulation and synthesis controlled by a MIDI keyboard/interface. You will perform the resulting composition in class during a performance session.


  1. This project will build upon the synthesis techniques and MIDI controls that we have discussed in class. Your objective should be to create a performance patch that features real-time control of 8 different parameters. You may consider building synths that will work in conjunction with the data storage objects (tables, histograms, coll, umemu, etc) and control of the basic MIDI parameters that we discussed earlier in class. You should make every effort to be creative with this project. Think about ways that Max can extend synthesis controls beyond standard programs. Draw upon your knowledge of experimental art music forms and unique beat-based compositions.
  2. You should complete a composition to perform that is ONE MINUTE in length. Some elements to consider include:
    1. What synths will you use? How will you control them in real-time? Will you use data storage objects to facilitate your performance? Will you control all of the elements your self?
    2. You should change pitch ranges, durations, velocities both within sections, and within gestures.
    3. Will you use a control interface? How can mapping your parameters to knobs and sliders increase the expressivity of your performance? How many parameters can you control at a time?
    4. Can you automate some of these processes and focus on marco-controls?
    5. Write a brief report (two pages, typed, double spaced, 12-point font, 1 inch margins) describing the sounds you created, any use of real-time control of your sounds, and significant DSP processes that you used. In your report, also briefly summarize the central organizing idea of the composition, and describe the formal structure. Make any other comments you feel are relevant.


  1. At least 8 controllable parameters. This may filter components, pitch ranges, delay times, durations, etc. You should choose a VARIETY of controllable parameters.
  2. Your project should be at least 1 minute in duration.
  3. Your project should make use of layering as means creating a complex sonic texture.
  4. You must use at least 4 separate synths (choose from addative, subtractive, chiptune, FM synthesis
  5. Your projects must use at least two separate filters (high pass, low pass, reson, biquad, delay lines,
  6. or anything else you find! Be creative! Investigate!).


  1. Your Max patch should be labeled “yourLastName_yourFirstName_AUDIO”.
  2. Your studio report should be labeled “yourLastName_AUDIO_14”.
  3. All of these materials should be placed in a folder labeled “yourLastName_AUDIO_14”.
  4. “yourLastName_FINALAUDIO_14” should be zipped into a folder.


  1. Max patch.
  2. Any accompanying audio files/video files.
  3. Your studio report, in PDF format.
  4. Submit (via a file sharing site i.e. iLocker, yousendit, dropbox) by the due date. Please DO NOT require a login in order to enable download.


  1. Creativity of patcher and performance (40 pts).
  2. Neatness and documentation via comments (and/or send/receive as appropriate) (20 pts).
  3. Meeting the 1-minute length of performance and having the required 5 parameters under patcher control/variation (10 pts).
  4. Following turn-in procedure (5 pts).

75 points total

max max-lecturenotes

(max) mapping MIDI to audio synthesis

I’ve covered some basic audio synthesis in a previous post. Now it’s time to map MIDI note and velocity information to the synthesis process.

Note and Velocity Mapping

Download EnvelopeGraphicSustainNoteOnOff.maxpat.

The bulk of the patcher is the same as the graphic envelope series. The only addition is a MIDI note input section in the upper left corner, and corresponding changes in triggering the function envelopes.

The notein object sends key velocity to a select object, looking for 0 velocities (note off velocities). These 0 velocities will be used to trigger the release stage of the envelope. MIDI note and velocity feeds stripnote, with note numbers being converted from MIDI to frequency in the mtof object. The on velocity triggers the function envelope.

The preset object has been changed very slightly, as you no longer need to store the oscillator frequency in the preset.

Velocity Sensitivity

Download EnvelopeGraphicSustainVelAmp.maxpat.

This patcher adds velocity sensitivity to the NoteOnOff mapping patcher. It takes the noteon velocity, divides it by 127. and uses that result as a scaling factor for the amplitude envelope. The scaling factor is applied to the output of the envelope line~ object.

The weakness in this patcher is that the mapping of velocity to amplitude is linear, while we perceive amplitude to loudness in an exponential way.

Better Velocity Sensitivity

Download EnvelopeGraphicSustainVeldbAmp.maxpat.

To achieve better velocity to amplitude mapping it is more appropriate to scale velocity to dB. This patcher does that, and then converts dB to amplitude (dbtoa) before applying it to the envelope line~ output.

You can experiment with the low end of the output scaling to fine tune key velocity sensitivity. After some experimentation, I’ve settled on -48 dB, which provides at least some audibility for each note, but provides sufficient high amplitude sensitivity.


max max-lecturenotes

(max) basic audio, oscillators and envelopes

Now that we’ve had a little fun with our Theremin, let’s turn to some basic synthesis with oscillators and envelope generators.

The Very Basic Setup

Download the BasicAudio.maxpat. This patcher provides a very basic adjustable synthesizer, with a saw~ object feeding into an audio multiply (*~). Changes to frequency and amplitude are made with float objects. Amplitude changes can be made with either the float feeding a message or a pack object. Both function the same way.

Adding Envelope Control

Next, we turn to the BasicSynthEnvelope.maxpat. Messages are sent to line~ in the <target time> format, meaning what value to change to over how long. Moving left to right, the first pair of messages show individual envelope line segments creating an attack and release. (Remember, to hear anything you must enter a frequency.)

The next message over, triggered by the space bar, includes an entire ADSR envelope description. The first 0. followed by a comma tells line to go to that value immediately, then target/time pairs follow:

  • 0.9 10 (reach amplitude of 0.9 over 10 ms) Attack
  • 0.25 100 (go to amp 0.25 over 100 ms) initial Decay
  • 0.25 1000 (stay on amp 0.25 over 1000 ms) Sustain level and time
  • 0. 250 (go to amp 0. over 250 ms) Release

As an organizing tip, I specify amps (target values) in floating point numbers, and time in integers. It helps me read through the list.

The final message on the right, triggered by the 1 key, is just a slow attack and release envelope.

Using the Function Editor and Presets

Download the BasicSynthEnvelopeGraphic.maxpat and explore the preset and function objects.

The preset object stores and recalls data in user interface objects like number boxes (integer and floats), function editor, toggle states, sliders and dials. You store a information by sending the message store #. Recalling a preset just involves sending a number. Dark grey circles have a preset stored at that location. The blue circle is the current preset. The patcher loads preset 1 as current.

Preset objects can store all or some of the UI objects in a patcher. I’m using the left outlet of preset to connect to inputs of objects that I want to store in a preset location.

The function editor is a graphic breakpoint editor. You add points by clicking in the window. You can drag points, add as many as you like, and delete points (shift-click). As you move a point around you see its current X and Y values. When you send a bang to function, it will output to its second outlet its contents as target/time pairs for sending to line~. The spacebar is set to send a bang to function. You can see the output of function in the message below it.

Choose preset 2 by typing a 2 on the keyboard. When you subtract 48 from the key input you get numbers that you type aligning with values output.

Hit the spacebar again to compare settings. Frequency, function, and the number object all change. The number object that feeds into prepend setdomain changes the overall length of the function. All points scale to the new length. (Y is the domain of the function editor; X is the range.)

Sustain Points

The final addition is adding sustain points in the function editor. Download BasicSynthEnvelopeGraphicSustain.maxpat. It has two changes: the function editor colors have changed to better show the sustain points, and a toggle has been added to the space bar feeding either a bang or a next message.

Cmd-click any point in function and you make that point a sustain point. You can have as many sustain points as you want in the function editor. Sending a bang to function initiates the function, stopping at the sustain point. A next message tells function to continue through the points.

max max-lecturenotes

(max) theremin fun, part 2

Continuing with the description of patchers from part 1


ThereminInProgressLCD starts to convert ThereminInProgress from mousestate control to LCD drawing control. No data is being fed to saw~, so audio is not in use for this patcher. The main focus is the LCD and sprite control within it.

On the right of the LCD are drawing commands, some of which are new. Moving from the top down, a loadmess is used to turn on idle for the LCD, which will send mouse location out the second outlet when the mouse is moved over the LCD without any buttons pressed.

Next, you find that X/Y position is being received from a send object (s idleMouse). The X/Y data feeds into the prepend object, outputting <drawsprite circle x y>. A sprite is a graphic image that draws on top of an object. in this case, it is a thick circle that follows the mouse when the LCD is in idle mode. When you press the mouse button down, the sprite stops moving and a line is drawn that follows the mouse position.

Below the prepend object you have a loadbang. It triggers a message to enablesprites (allowing for sprites to appear in the LCD), and then it records a sprite for later use. All of the sprite commands and messages are found in the LCD help patcher. The message starts recording a sprite, changes the pen size, then gives a command to paint a frameoval with a startX startY endX endY R G B values. (-12 = equals 12 pixels to left and above current mouse location to 12 pixels to the right and below current mouse location.)


ThereminInProgressLCD2 is a fully functional Theremin, that outputs mouse X/Y position when the mouse button is down, scales it to pitch and amplitude, and uses it for oscillator playback.

Some issues were initially encountered with drawing and only creating sound when the mouse button is down. In the previous patcher, the sprite would remain visible even when the mouse button was down. It would be better to not have the idle sprite display when the mouse was drawing. To accomplish this task I used the third outlet of LCD to track whether the mouse button was pressed. Pressing the mouse button (the message 1) caused a hidesprite circle message to be sent to the LCD. Releasing the mouse button (message 0) was used to trigger a clear message to the LCD. It seemed aesthetically pleasing to have the drawn line remain on screen for a very short time, so I routed the bang through a delay message.

To only have audio playing when the mouse was drawing in the LCD, I again used the mouse button state from the third outlet. After the amplitude value from mouse Y was applied to the oscillator signal, another audio multiply was added. At this point in the audio chain the signal is being multiplied by the mouse state, either 1 for down or 0 for up.

One final note is that the two meter~ objects have different settings for the number of light segments.


ThereminLCDCleaner is functionally the same as LCD2. The drawing functions have been incorporated into a patcher object, as has the oscillator selection section. A loadmess has been added to select the sawtooth wave upon loading, and a live.gain~ has been added to allow for final output volume control (separate from mouse tracking) and metering.

I will revisit the ThereminLCD when we start to talk about audio effects.

max max-lecturenotes

(max) theremin fun, part 1

To explore some basic audio functions a bit differently from the tutorials, and to explore ways to control parameters via the mouse and the lcd object, I’ve created a series of Theremin patchers:

The patchers get progressively more refined and functional, in an attempt to match the functionality of the online Theremin available through Femur Design. I’m going  the first two in this post.


ThereminFun is a first, basic attempt to use the mouse to send frequency and amplitude information to a sawtooth oscillator. It uses mousestate to report X and Y position info for the mouse, and whether the left mouse button is pressed or not. Mousestate has to be polled (sent a bang) to report mouse information, which is being handled by a metro object.

Mouse X position is being scaled to frequency. Mouse Y information is being scaled to amplitude. Screen parameters of 1024×768 are being used. You will have to adjust the scale input to match your screen resolution for best results. Since frequency relates to pitch exponentially, as does amplitude to loudness, an exponential curve factor of 1.006 has been added as the fifth argument to each scale object.

You can see the frequency and amplitude information being sent to the basic audio signal chain of the basic audio patcher. Frequency and amplitude values are being inserted into a list and sent to line~ objects for smooth changes.


ThereminInProgress takes the ThereminFun patcher and adds a selector~ object with four different oscillator waveforms. Selector~ works like an audio switch object, using control messages by number to select different inputs to pass through to the output.

The basic audio output uses a live.gain~ object to change gain and provide a meter display in one object. I like the Max For Live objects for their integration and labeling features. Live.gain~ expects amplitude settings to be communicated in dB, so amplitude scaling is changed from 0. – 1. values to decibels (-70. to -0.1). Since decibel maps linear values exponentially to amplitude, no exponential curve is needed in scale. Also, since live.gain~ has an internal ramp time (set in the inspector), a line~ object is not needed.

Likewise, we can map Mouse X location to MIDI note number to avoid the exponential curve. Using floating point output arguments for scale means that we will get a more continuous floating point MIDI note number than the standard MIDI spec. Not only are floating point MIDI note numbers ok in Max, they provides a continuous pitch scale beyond the confines of equal tempered tuning. The MIDI note number is sent to a mtof object (MIDI to frequency converter) before passing to the frequency input of all oscillators.

…to be continued

max max-lecturenotes

(max) a most basic audio patcher

To get started with audio processing, I’m first posting a most basic audio patcher: BasicAudio.maxpat

(I know that I started with the Theremin patcher, but let’s start with the most simple patcher.)

Basic Audio Patcher

The patcher is a simple sawtooth oscillator (saw~) with changeable frequency via a float object. The amplitude is controlled by a *~ object (audio multiply).

The BasicAudio.maxpat shows all the essential elements of audio synthesis/processing in Max. Audio signals travel on “bumble bee” patch cords. You need a dac~ or ezdac~ object to not only hear audio, but to turn on/off audio processing. Changing values to the frequency input of the oscillator (saw~) and the amplitude both are sent via a line~ object. And meter~ and levelmeter~ objects are used to display signal levels.


One key debugging feature for audio patchers is the probing feature. In the debug menu, turn probing on. With probing on, you can hover your mouse over an audio patch cord and see the current signal level displayed as a popup meter. Since the probe is reading amplitude values at the beginning of every signal vector, it will fluctuate some. Still, it is a very useful tool for seeing if signal is present without having to add meter~ objects everywhere.

max max-lecturenotes

(max) line~, meter~, and levelmeter~

Three objects worthy of a special mention right from the start are line~, meter~, and levelmeter~.

If you have any sound experience at all you know to keep track of your visual indicators (meters) to make sure sound isn’t clipping at some point in the signal chain. In MaxMSP you have the meter~ and levelmeter~ objects to show audio levels. Meter~ can be arranged to be either horizontal or vertical, and sized according to visual need. You should insert meters into your patchers at all points that could output an original and/or a modified audio signal. This technique is like using number boxes for display purposes. Meter~ can be set to show more segments to give a more finely tuned display. Levelmeter~ is a bit more sensitive and finely tuned by default, but it is also a little more processor/graphics intensive.

The line~ object will create a smooth ramp to a specified value over a specified time (generally in ms). You will use the line~ object to create amplitude envelopes and frequency envelopes, and to smooth control-rate changes being used as arguments to audio-rate objects. For example, if you use a float object to type in a frequency change to an oscillator (saw~, cycle~, etc.), you need an audio rate ramp to smoothly change between the previous and new values.

Line~ expects <targetValue> <time> pairs. Multiple pairs can be sent as one message list and line~ will execute all the pairs at the proper time. A value followed by a comma tells line~ to immediately change to that value.

Line~ is often used to create a smooth ramp between amplitude multiplier values being sent to the *~object. I often use a floating point number box feeding a message object with the contents <$1 10>. The floating point number replaces the $1 and causes the list to be output to line~. The tutorial (MSP tutorial number 2) uses a pack object with arguments <0. 100>. The amplitude replaces the 0. and outputs the list. Either way is fine. Note that a message box doesn’t require you to format your argument according to data type. Pack does, however, want the argument to match the incoming message type. If the message and argument do not match, the message will be changed to the argument format. For example, if you type an integer as an argument to pack but send it a floating point number.

max max-lecturenotes

(max) audio basics in max

Before I dive into the Theremin patcher, it’s good to review basics of digital audio in Max. For that, I’m going to use a previous post to give the overview.

MSP and Audio Rate Communication