This tutorial looks at how to generate timed events in Max using MSP audio signals as the synchronization source. When designing timing-based systems in Max, we're used to using metro, clocker, delay, and other Max objects that run in the Max scheduler to generate events automatically. However, when working with MSP, it's often beneficial to be able to synchronize events directly off of an MSP signal. This technique not only allows for more precise control of event timing (so-called sample accurate sequencing), but also allows us to use a number of MSP objects that allow for the synchronization of multiple event streams based on a single clock signal. Our first tutorial looks at a few of these objects and how they work.
Providing a synchronization clock signal
The MSP object driving the behavior in our tutorial patcher is called sync~, and outputs the same kind of signal as a phasor~ object, i.e. a linear signal ramp going from to at a steady rate. Unlike the phasor~ object, however, the object understands its speed not in Hertz, but in beats-per-minute (BPM), a standard definition of musical tempo used in most audio sequencing applications. Clicking the button object at the top of the patcher sends messages to the sync~ object, which simulates a tap tempo system used in many sequencers. By clicking the button at a steady rate, the sync~ object adjusts its speed to send out a single ramp for every beat (interval) between the messages. The BPM of our messages is calculated and sent out the second outlet of the sync~ object, which we then use to set a number box that we can change to set the BPM manually.
The output of the sync~ object is a signal ramp, just like the output of the phasor~ object. As such, we can use it as an envelope generator directly, to control the volume of an audio signal going to the dac~ (in this case, a rand~ noise generator). While this is certainly useful in certain applications, the main advantage of using a signal to provide event synchronization is in our ability to time-scale the signal and then generate events from it.
Many rates at once
The rate~ object allows us to time-scale the ramp signals generated by sync~ and phasor~ objects. The argument to the object (or a new value provided in the right inlet) sets the scaling factor, e.g. a rate~ object with a factor of will generate a ramp that takes twice as long to repeat as the input signal. A rate~ of , by comparison, will go two times as fast as the input. Using this system, we can have multiple areas of signal logic in our MSP patcher running at different multiples of the original synchronization signal yet staying perfectly in time.
Generating Max events from a synchronization signal
Two things are going on here of note. The first is that the 'click' is happening not at the speed we've set in the sync~ object, but at four times that speed. This is the doing of the rate~ object in patcher area , which is set to a value of . This means that our effective musical timing for one 'beat' in our patcher is subdivided into four in this part of the MSP signal chain, allowing us to trigger faster events.
The 'click' we hear is generated by sending a button object to generate an envelope from the line~ object, fading in and out the noise~ quickly to make a sharp ticking sound. This logic is familiar to use from previous tutorials; the big question here is, how is the button object being triggered?message (from the
The MSP delta~ object takes a signal input and outputs a signal, the numbers of which report how much the incoming signal has changed from sample to sample:
In the case of a ramp signal, the delta~ object reports a more-or-less constant positive value as the signal rises; when the ramp resets to , however, the delta~ object reports a sudden, high, negative value that represents the sudden drop in the ramp. This momentary negative signal value can be detected by using a logical operator on the signal to test whether it goes negative. The <~ object in the patcher does this, by outputting a signal value of when the input signal matches the condition specified by the object's argument, and a otherwise. In the present case, the output of <~ will be a whenever the input signal is less than , i.e. only when the ramp coming out of the rate~ object resets, causing the delta~ object to output a negative value.
The edge~ object is an MSP object that takes input signals and uses them to trigger Max messages. It does this by looking at transition states from to (left outlet) or to (right outlet). When the rate~ object resets its ramp, the left outlet of the edge~ object generates a in response to the logical to (false to true) transition coming out of the <~ object. This can trigger any Max event, just as if it were fired from a metro object or triggered by clicking a button manually.
Audio-rate sequencing using fixed timing intervals
The repeating melody specified by our multislider objects is being triggered by a sample-accurate sequencing object called techno~. The techno~ object maintains a certain number of steps of data points based on its parameter (set in our tutorial patcher with the message ). Each step can have a pitch and amplitude associated with it, which it then puts out as signals from its outlets. These signals contain all the information necessary to directly drive MSP oscillators and amplifiers (in this case the rect~ and *~ objects).
Sequences are loaded into the techno~ object by sending and messages with the step number and value as their arguments. The listfunnel objects in our tutorial patcher create the appropriate messages for this purpose, by taking the sixteen-member lists from the multislider objects and translating them into sixteen individual, numbered messages. By a similar token, other attributes of the sequence process can be set, either for each step individually or for the entire sequence.
The techno~ object. The values control the trajectory for the envelope coming out of the middle outlet of the techno~ object as it rises at the beginning of a note. A value of causes the notes to snap on instantaneously; a value of causes the tones in the sequence to take the entire beat to fade in from their previous value. The values work on a similar principle, only with regards to the end (or 'release' stage) of the note's envelope. A of 1.0 allows the notes to blend together; a value of ensures that each note falls to silence between steps of the sequencer. These two values interact to create dynamic envelope shapes. the messages control the amount of portamento (or gliding) applied to the signal controlling the sequence's pitch. Curve values of will cause the pitches to 'snap' from note to note in the sequence. As we raise the value, more and more of the beat will be taken up by an interpolating pitch ramp, causing the sound to slide around in frequency., , and messages, like the and messages, allow us to fine-tune the behavior of the internal sequencer of the
Audio-rate sequencing of arbitrary data
The seq~ object works as an audio-rate sequencer of arbitrary numeric events. The signal it receives in its input serves as a synchronization clock for the object, allowing us to feed it with a signal ramp from a rate~ object set to eight measures. When seq~ receives a message, it listens to Max messages coming into the object and timestamps them based on the input signal. When seq~ is in 'play' mode (through a message), it uses the input signal to look up events based on their timestamp, and outputs them in the correct order. Note that, unlike the techno~ object, the seq~ object outputs Max events, not signal values, and so it can be used to store arbitrary data.
MSP has a variety of tools for audio-rate sequencing. The sync~ and rate~ objects can be used to create simple timing ramps and regular intervals using beats-per-minute values to determine tempo. The delta~ and edge~ objects are useful in generating Max events from an MSP ramp signal. The techno~ object allows for sample-accurate sequencing of a finite number of steps for a single audio oscillator/amplifier pair; for more flexible sequencing, the seq~ object allows for audio-rate timestamping of arbitrary Max events which can be saved, edited, and replayed as sequences of instructions.
|sync~||Synchronize MSP with an external source|
|rate~||Time-scale the output of a phasor~|
|delta~||Signal of sample differences|
|edge~||Detect logical signal transitions|
|techno~||Signal-driven step sequencer|
|seq~||Signal-driven event sequencer|