[gen~]: basic operations
introduction to the Max/MSP [gen~] DSP code-writing system, delays,
soundfile munging, filters
Links
The best source of documentation for the [gen~] object is 'inside'
Max/MSP (v. 6). The Cycling '74 crew have done a good job of
putting a number of examples on-line, too. Here are a few of the
on-line [gen~] resources:
- the 'garden of earthly delays'
-- Gregory Taylor's original [gen~] audio tutorial.
- gen-patch-a-day
-- Gregory and his compatriots at Cycling '74 started coding up
example patches to help with the [gen~] learning-curve. Many
are of the [jit.gen] video coding system (and they are great
fun to see!), but there are also a few good audio [gen~] patches.
- the Cycling '74 forums (fora?)
-- discussion of things-Max/MSP/Jitter/etc. See especially the
[gen~] forum.
In addition to asking/answering questions, people have also been
posting patches; another good source of example coding.
We also implemented a few filter equations in [gen~] as part of
our "Marlon Feld" project. The website I used to design the
filters and get the appropriate equations was here:
Class Patches, Discussion and Code
Here is the archive with the class [gen~] patches we coded:
A brief description of these:
- simplemix1.maxpat
This shows how values can be sent "inside" a [gen~] patch via
an inlet [in] using the [sig~] number-converter object (all inputs to
[gen~] are "signal" inputs, i.e. audio sample streams). All this
patch does is multiply the inputs by a value, allowing you to
fade up/down the sound.
- simpledelay1.maxpat
This patch uses the 'named parameter' mechanism to set values inside
[gen~]. Each [param] object you use functions also as a named message
from "outside" [gen~]. In this patch we use it to set the delay length
(in samples). Note that the initial delay length set for [delay] sets
the maximum length of the delay-line.
- simpledelay2.maxpat
This combines both the [param] and the [in] methods for setting
data in [gen~]. It also shows how [gen~] can be used to implement
recursive DSP functionality; in this case a delay-line with feedback.
- soundblitz1.maxpat
We designed a patch to turn on/off audio coming through a [gen~] using
the [?] operator. Just for fun, we then modified the patch to allow
us to turn on/off the audio every other sample. Yay! This also
shows how the [history] operator works to delay samples in recursive
paths. We then modifed the [wrap] operator so that we could set
how many samples we "blitz" to zero ("turn off") as the signal
passes through. We decimated that sound!
- marlfilt1.maxpat
- marlfilt2.maxpat
- marlfilt3.maxpat
These three patches show the sequence we used in developing a [gen~]
version of a sound-producing algorithm that Marlon Feld sent me.
This is his description of the algorithm:
n = white-noise source
Take [n lowpassed at 300 Hz]/[n lowpassed at 2000 Hz]
Then highpass the result, square it, and normalize/clip it to keep
it under control...
...the result is a particular texture of spiky impulse noise.
marlfilt1.maxpat implements the first low-pass filter. Using
Tony Fisher's
filter design
web page, we generated the following 2nd-order Butterworth low-pass
filter equation with a cutoff set at 300 Hz:
y[n] = ( 1 * x[n- 2])
+ ( 2 * x[n- 1])
+ ( 1 * x[n- 0])
+ ( -0.9413432994 * y[n- 2])
+ ( 1.9395702074 * y[n- 1])
where x[n-0] is the current sample input to the filter, x[n-1] is the
previous (use the [history] operator!) sample input to the filter,
and x[n-2] is the sample input from two cycles past. y[n] is the
output of the filter, y[n-1] is the previous output of the filter, and
y[n-2] is the output from two cycles ago.
It worked! We then implemented the 2000 Hz low-pass filter
(marlfilt2.maxpat) using
this equation from the filter-design web site:
y[n] = ( 1 * x[n- 2])
+ ( 2 * x[n- 1])
+ ( 1 * x[n- 0])
+ ( -0.6683689946 * y[n- 2])
+ ( 1.6010923942 * y[n- 1])
(note the similarities in the equation), and we followed up with the
high-pass filter and the rest of Marlon's algorithm in
marlfilt3.maxpat, Here is the high-pass equation we used:
y[n] = ( 1 * x[n- 2])
+ ( -2 * x[n- 1])
+ ( 1 * x[n- 0])
+ ( -0.8175124034 * y[n- 2])
+ ( 1.7990964095 * y[n- 1])
and the result was indeed "a particular texture of spiky impulse noise".