Creation of an Audio Mixing Environment Using Max/MSP
Jonathan S. Abrams
Submitted in partial fulfillment of the requirements for the
Master of Music in Music Technology
in the Department of Music and Performing Arts Professions
in the Graduate School of Education
New York University
Advisors: Kenneth J. Peacock, Robert J. Rowe
December 15, 2004
Table of Contents
I. Preface 3
II. What’s New in v1.0.3 (build 20050823) 5
III. Mixing 6
IV. Fader and Panner Linking, Fader Automation, decibel conversion 11
V. Panning and Panner Automation 28
VI. Mute, Solo, and Transport 31
VII. Monitor Dim, Metering 38
VIII. Equalization 42
XI. Results, Mix, and Conclusions 44
X. Bibliography 53
Audio mixing consoles, whether analog or digital in implementation,
whether software or hardware in use, are expected to provide the user with
certain functions. These include signal faders, signal panners, mute, solo,
metering, and monitor dimming. Beyond these basic functions, others may
include automation, dynamics, and equalization. How many instances of
these additional processes may be run simultaneously, and the quality of
these processes, is limited by programming and available digital signal
processing resources. The number of channels would be limited by the
number of inputs, DSP resources, and signal headroom within the mixer. For
digital mixers, one design consideration is what type of DSP to use, either
fixed point or floating point, and that decision will effect the quality of the
processes listed above.
Automation functions include fader and panner automation, both for
individual channels and for linked channels. Some hardware consoles and
software mixers also feature transport controls. Digital consoles have
graphic or para-graphic equalization controls on individual and master
channels. While each console design may use a different scale to represent
how much of an audio signal is panned to a side within the stereo soundfield,
all consoles use the logarithmic scale to express how much of a signal is
moving through a fader. After a signal is processed, panned, and its gain is
adjusted, it moves to a master section where it may be further processed, in
addition to its gain being further adjusted, and then is sent to the studio
monitors via an output. Exceptional console designs have sufficient
headroom to avoid clipping internally, though any console may have its final
Channel 8 and the master section of the mixer built in Max/MSP.
What’s New in v1.0.3 (build 20050823)
Preferences are now in a floating window that cannot be zoomed, grown in
size, or closed. Apple+, toggles the presence of the preferences window (as
it does in many Mac OS X applications).
Meter~ is now in a bpatcher. In prior versions, it was in the main patch. It
now has the -3dBFS, -6dBFS, -10dBFS, -12dBFS, -14dBFS, -16dBFS, and
-18dBFS points on its scale marked. It updates its display every 10mS.
There is now a numerical readout in dBFS of the signal level directly below
the meter~ object which updates every 1mS.
Levelmeter~ has been added to the metering section for each channel.
The following preference settings are new to this version:
Continuous, 3 Second, or Inifinite Peak Reading - Choose how often
levelmeter~ and meter~ have their numerical peak readouts updated.
fast (no ballistics), VU, DIN 45 406 (IEC PPM type IIb), BBC (IEC
PPM type IIa), Nordic (IEC PPM type I), EBU Digital - Choose the
ballistics for levelmeter~.
-20dBFS, -18dBFS, -16dBFS (TASCAM), -14dBFS, -12dBFS - Choose
the zero reference point for levelmeter~.
The Pre-Fader or Post-Fader Metering preference is now in the new
Version 1.0.3 (build 20050823) has been tested on a B&W G3/500 using Mac
OS X v10.3.9 with 768MB RAM.
Attenuating and mixing are two of the three basic functions of a
console (Pohlmann 636). With most modern mixers, the summing bus is set
to operate at unity gain. For every doubling of the number of channels, if
the audio in all of the channels is non-coherent, the output level increases by
3 dB. If the channels are coherent (the exact same signal), the output level
increases by 6 dB for every doubling of the number of channels (DWP 2).
The gain structure of the mixer should be configured so that it is not
possible to clip prior to the output stage.
The most popular DAW is Digidesign’s Pro Tools TDM. While there have
been several different hardware offerings from Digidesign that incorporate
their TDM process (time division multiplexing), the two most popular ones are
Pro Tools|MIX and Pro Tools|HD (of which there are two types). Advances in
DSP allow for Pro Tools|HD, the newest TDM offering from Digidesign, to
support immense mixer configurations with the proper amount of DSP
The older of the two TDM systems mentioned above, the Pro Tools|MIX
systems, has a 48 bit mix bus with 30 dB of headroom when using the 24-bit
optimized mixer, 18 dB of headroom when using the 16-bit optimized mixer,
and support for a maximum of 64 simultaneous voices (PT Ref 604, 7).
When using more than 59 voices simultaneously on a MIX system, an internal
sub-mix is necessary, and some voices are
truncated down to 24 bits (DUC Confusion). The 48 bit mixer allows MIX
based systems in their last version of Pro Tools software, v6.4.1, to use all
of the 48 bit mix bus. The 48 bit mix bus specifies 16 bits below the audio
signal, followed by 24 bits for the audio signal. This adds up to 40 bits. The
remaining 8 bits are utilized for mixing audio. When adding coherent channels
of audio, as noted above, there is a +6 dB increase for every doubling of the
channels. This worst case scenario brings the number of utilized bits in the
mix bus to 46 (see chart below). Bits 47 and 48 are utilized for applying as
much as +12 dB of gain above unity.
Bit Allocation when Summing Coherent Audio Channels (PT TDM MIX)
Increase in Number of BitsIncrease of Level in dBChannels
The first incarnation of Pro Tools|HD, which uses an HD Core card and
additional HD Process cards, has a maximum of 128 voices and a 48 bit mix
bus with 48 dB of headroom (PT Ref 604). When using more than 68 voices
simultaneously on a HD system at 44.1 kHz, an internal sub-mix is necessary
(PT Ref 601).
The current incarnation of Pro Tools|HD (called HD Accel), which uses
an HD core card and additional HD Accel cards (as opposed to HD Process
cards) has a maximum of 192 voices and a 48 bit mix bus with 48 dB of
headroom (PT Ref 604). When using more than 124 voices simultaneously on
a HD Accel system at 44.1 kHz, an internal sub-mix is necessary (PT Ref
The Digidesign TDM systems use Motorola DSPs that execute fixed-
point arithmetic (Integer processing) using a 56 bit accumulator (DUC
Impossible). MSP performs calculations with 32-bit floating point arithmetic
(so do Digidesign LE systems as of this writing, but the point is not to
compare systems here). James Moorer, formerly of Sonic Solutions, has
said “‘most integer arithmetic units use very wide accumulators, such as 48
to 56 bits, whereas 32-bit floating-point arithmetic units generally have only
24 or 32 bits of mantissa precision in the accumulator. This can lead to
serious signal degradation, especially with low-frequency filters’”, which can
be around 4 bits (Masciarotte 92). Double-precision mathematics can be
used to maintain a higher level of quality, but at the cost of 4 to 5 times
more DSP overhead (Tomarakos 221). Double-precision means using twice
as many bits as the I/O path of the processing. In Digidesign’s TDM systems,
for example, the plug-in I/O is 24-bit, so a double-precision plug-in uses 48-
bits for its calculations (DUC Confusion).
In floating-point mathematical systems, the exponent functions as a
scaler. Floating-point systems are using what we write on paper as scientific
notation (Roads 932). Since the exponent can be used to scale from small to
large numbers, floating point systems are one way designers can work
around dynamic range problems. A 32-bit floating point system has a
dynamic range of 1,670 dB because of this scaling capability (Roads 356,
932). Conversely, “a 32-bit DSP that has native fixed-point support...can
support signals up to 196 dB (Tomarakos 221). Floating-point based
systems do not create numerical overflow (a number larger than what the
system can handle) or have out-of-range samples, but fixed-point systems
are easier to debug and design (Roads 933). The IEEE Standard 754-1985
specifies the format for a 32-bit floating point number as SXXXXXXX
XMMMMMMM MMMMMMMM MMMMMMMM where S is the sign bit, X is the
exponent, and M is the mantissa. The MSB of a normalized mantissa is
always 1, and is not stored, resulting in the floating point number actually
having a 24-bit mantissa (Castine).
Capabilities of Available Mixers
Audio engineers have come to expect mixing consoles to have certain
functions, regardless of their size or cost. As size and cost increase, other
features or expansion of basic capabilities are built into the design. On the
next page is a chart of the features and functions in a sampling of mixing
consoles. Based on the chart, it is clear that above everything else, there
needs to be four bands of EQ on each channel in the mixer patch to meet
User interface for linking channels and engaging inverse functions.
Fader and Panner Linking, Fader Automation
Consoles such as Yamaha’s O2R digital mixer allow the operator to pair
faders and panners together, or link them. This is useful when working with
two input signals that the operator wishes to control simultaneously with one
control. To accomplish this in MSP, controls need to be paired (or linked)
together and the value of the selected control needs to be sent to the input
of the control it is linked with. The change in value of one control is then
sent to the other control resulting in a simultaneous change.
The two sets of controls in the group have a master/slave
relationship. The master control is adjusted and its corresponding value is
transmitted to the input of the slave control. Without this master/slave
relationship, the two controls would be transmitting changes to each other
and an infinite loop would exist. To allow for master/slave relationships to
be established for linked controls, the output of each fader control is used
to control a graphic gate and a standard gate. The odd channel panner
control goes straight to a standard gate, and the even panner control goes
though a graphic gate and a standard gate. The movement of a control by
the user changes the state of these gates so that it becomes the master
control, while setting up the gates so that when the same control on the
other channel is manipulated, it immediately becomes the master control for
Graphic gates, inlets, and associated control messages for establishing
Aside from the link ubutton in the main patch, the code for making
the groups possible is in a subpatch titled group. The subpatch has inlets
for link enable/disable, odd panner and even panner selection, fader value,
panner value, and inverse relationship. It has two message boxes for both
one and zero messages as part of the panner selection control, as well as
eight gates for preventing infinite loops (establishing master/slave
relationships), four graphic gates for routing either the same value or the
inverse value to the other channel in the group, and abs and subtraction
objects for the inverse relationship function. Two graphic gates, each with a
zero message connected to the one output state, are used to control fader
selection when the channels are linked. There are outlets for fader and
panner values for both channels in the group. There is a loadbang object
which initializes the state of the graphic gates so that the inverse function
for fader and panner relationships is not engaged until explicitly done so by
Gates for selecting between normal and inverse values, with loadbang for
initialization to normal values and toggle inlets.
When a panner control is manipulated by the user, it bangs a zero and a
one message. The one message opens the primary gate for the panner being
manipulated and the zero message closes the primary gate
for the slave panner in the group. This prevents an infinite loop from
existing where each panner would try to control the other one when they are
When a fader control is manipulated by the user, it also bangs a zero
and a one message. The zero message closes the primary gate for the slave
fader in the group. This prevents an infinite loop from existing where each
fader would try to control the other one when they are linked. The one
message is used to control graphic gates that allow for either fader to
instantly become the master of the group. The one message passes through
the graphic gate and bangs a zero message. The zero message in turn
changes the state of the graphic gate. The graphic gate now passes the one
message ahead of it to the primary gate of the fader being manipulated,
which opens the primary gate and allows the fader value to be passed
farther along in the patch. The same one message also changes the state of
the graphic gate for the slave fader in the group. This sets the stage for
the opposite fader to be manipulated and instantly become the master fader
in the group.
The even panner of the group has an additional graphic gate with one
and zero messages. This is to correct a bug where if the even panner was
the first fader in the group to be adjusted, it would not control the odd
panner in the group. When the even panner is adjusted, it passes through
the graphic gate. If the gate is open, the value passes to the even
primary gate, and the graphic gate closes by way of a zero message being
banged by fader adjustment. The next time the graphic gate receives an
input, it routes the input to a one message, which changes the state of the
graphic gate to allow for the signal to pass to the primary fader gate.
Code to correct the bug described above. The inlet is the even panner value.
For the master controls to act upon the slave controls, a group must
be established. This is done with a ubutton object labeled Link. The Link
ubutton is configured to operate as a toggle (as opposed to a button). When
it is pressed, a bang is sent from the mouse down outlet. This bang is sent
to a message object with a value of 1. This value is then transmitted to two
(2) gates, one for each channel in the group. The gates
that receive this value are secondary gates. The secondary gates receive
their inputs from a primary gate. The primary gate only sends data to the
secondary gate if the channel associated with the gate is being manipulated.
When the channel is not being manipulated directly, the fader value never
makes it through the primary gate. These primary gates,
one per channel in the group, are what prevent the link function from
creating an infinite loop where both faders would control each other
simultaneously. When the link function is disabled, a bang is sent from the
mouse up outlet. This bang is sent to a message object with a value of 0.
This value is then transmitted to the two secondary gates. If a channel is
manipulated directly, its fader value will pass through the primary gate.
Since the secondary gate is set to zero, the fader value never makes it past
the secondary gate and to the slave fader, thus providing the operator with
independent fader control.
Primary and secondary gates. The inlets, from left to right, are odd panner
and even panner values.
If the user decides that the controls in the group should move in the
opposite direction of each other, this can be enabled with the Inverse Fader
Relationship and Inverse Panner Relationship ubuttons in the main patch.
When these ubuttons are enabled, they are highlighted and they
change the state of graphic switch objects preceding the fader and panner
value outlets in the subpatch group. With the inverse function enabled, the
controller values are sent to a subtraction object and then an abs object.
The subtraction object subtracts 100 from a fader value and 90 from a
panner value. The absolute value of this calculation is then obtained and sent
to the slave control in the group. The absolute value is necessary since both
the panner and fader objects use positive values. If the master fader is at
zero, and the Inverse Fader Relationship function is enabled, 100 will be
subtracted from 0, which is negative 100. The absolute value of that is 100,
which places the slave fader at the inverse location of the master fader.
This can be used to linearly crossfade two channels either by moving the
fader manually or by using the autofade function.
Inverse function section of patch. Inverse values are only calculated if the
inverse function is engaged.
User interface for autofade function.
I have implemented an automatic fade function that is programmable
by the user to either fade in or fade out from the current fader value to a
user defined value over a user defined period of time in milliseconds. In the
main patch, this autofade function uses a message button (Start Fade),
integer value fields for destination value and duration in ms, and a delay
object set to 1 ms. In a dedicated subpatch, there are inlets for the fader’s
current value, the fader’s destination value, the fade’s duration, a start inlet
(via bang), and a pause inlet. There are three graphic gates, three bangs, a
line object, two mathematical operators (+ and *), an abs object, a clocker
object, four zero messages, two one messages, a stop message, and outlets
for the remaining fade time, the fader’s current position, and a bang
indicator when the line object’s operation is complete.
In the main patch, the user sees two integer fields for setting the
destination value of the fader and the time (in ms) that it should take to get
from the current fader position to the destination value entered. The user
then clicks the Start Fade message button and the fade executes.
When Start Fade is clicked, the first thing it does is send a message to a
subpatch named TwoStateButtonOutside, which is within a subpatch named
autocontainer. When that message gets into the subpatch, it triggers a
bang, which changes the state of a toggle object in series. The toggle object
sends a message to a comparator object that sets the state of a graphic
gate, allowing the button to either start or pause an autofade. The output
of the comparator object triggers a bang that either sets the autofade
start/pause button to the start state with a green color or the pause state
with a red color by triggering messages with color values, the start or pause
state, and a prepend object. TwoStateButtonOutside also has a second inlet,
which receives a bang when an autofade is paused or completed, that
triggers the same process described above. The TwoStateButtonOutside
patch has a loadbang message that initially sets the autofade start/pause
button to start with the color green, and sets the toggle at the top of the
patch so that when the start button is clicked, the end result is it changes
to a pause button with the color red.
Above: TwoStateButtonOutside subpatch
At this point, all of the action takes place in a patch that is not
dedicated to UI interaction, but to driving the fader. The patch that handles
this function is called autofade (and is within the subpatch autocontainer)
and it has five inlets, which are pause button, fader’s
current value, time of fade, fader destination value, and close gate. The
pause inlet receives a message when an autofade is paused, and it triggers a
zero message which goes to multiple locations. The zero message triggers a
bang signaling the stop of the fade, which also stops the clocker object (used
to track elapsed time in an autofade operation), triggers a one message
which closes a graphic gate preventing line from acting upon a fader,
triggers a zero message that closes a gate in front of line that allows the
fader destination value to be sent to the line object, and opens a gate
allowing any manual fader moves to be sent to the line object. (In some
instances of this subpatch, the gate object beyond line is set to the right
output by a combination of loadbang and a one message. This was necessary
to get around a bug that was somehow introduced that created an infinite
loop.) The zero message triggered by pausing an autofade also opens a gate
used to pass the remaining fade time to the set duration field in the main
patch, triggers a bang that then sends the remaining fade time to the set
duration field in the main patch, and opens a gate that allows any fader
moves made while the autofade is paused to be sent to the line object.
Sending fader moves to line while an autofade is paused prevents line from
jumping to the destination value when an autofade is resumed. The fader’s
current value goes through a gate that allows the fader’s current value to be
sent to line when an autofade is not in progress. The gate is closed when an
autofade is in progress, preventing an infinite loop.
A portion of the autofade subpatch that is active when the pause button is
The time of fade inlet sends the fade’s duration to the line object and
to a mathematical operator, *-1. The value of this mathematical operation
is used to calculate the remaining fade time. A mathematical operator, +,
adds the autofade’s duration, which is a negative value, to the
elapsed time of an autofade. The result of this operation is a negative
number, that when made positive by using the mathematical operator abs,
provides the correct value of how much time is remaining in an autofade. It
is necessary to calculate the remaining fade time this way because the
calculation needs to be constant, and it can only be calculated constantly if
the input to the + object is constant. That constant input is from clocker,
which is counting from zero.
The value of this calculation is sent out a gate that is opened when the
autofade operation is paused, as described previously. The fader’s
destination value is sent to a gate object that is opened when an autofade is
started, allowing the value to be sent to the line object which is responsible
for the fade. This gate is closed when an autofade is either completed,
which is signaled by a output of the line object sending a bang, or by pausing
an autofade, either of which sends a zero message to the gate object in
front of line.
The inlet named close gate within the subpatch autofade receives its
input from the start outlet of TwoStateButtonOutside, which is a bang
message that starts the autofade operation. The bang message triggers a
zero message that closes a graphic gate, preventing manual fader moves
from being sent to the line object, and opens a second graphic gate that
allows the values from the line object to be sent to the fader. The same
bang that triggers the zero message also triggers a one message that opens
a gate, allowing for the fader destination value to be sent to the line object,
and prevents the remaining fade time from being sent back to the set
duration field by closing a graphic gate. A loadbang message sets a graphic
gate so that any fader moves made when the patch is loaded are sent to line,
which provides line with the starting point for the autofade operation.
A portion of the autofade subpatch that is controlled by the start/pause
button and receives the duration and range of an autofade operation.
Linear and Decibel Value Conversion
Every mixer expresses the amount of signal moving through a fader in
decibels. This patch is no exception, yet Max/MSP prefers to work with
linear values. To drive all of the functions in the mixer patch, and still
provide the user with the expected feedback, subpatches were created to
convert from linear to decibel and decibel to linear values. These subpatches
are AtodB and dBtoA, respectively, and are pictured below. To find the linear
equivalent of a decibel value, the equation 10(x/20)*100 is used, where x is
the value in decibels. To convert a linear value to decibels, the equation
20*[log10*(x/100)] is used, where x is the linear value (Boylestad 861-2).
dBtoA subpatch AtodB subpatch
User Interface for Panning
Every console has a pan control for positioning the sound at a
particular location in the soundstage. To do this in Max/MSP, a subpatch
named panner was created. For each channel in the main patch, there is a
dial object (with a -45 offset) that acts as the panner control, a hidden abs
object, and an integer field that displays the amount of pan to either the left
or right. Along the dial object are three message boxes labeled L, C, and R.
These messages when clicked, trigger a bang message that bangs an integer
value corresponding to the value dial needs to place the sound in that
position. The C message is bang via a loadbang so that no panner adjustment
is needed to play a sound when the patch is loaded. In the subpatch named
panner there is a signal input that is connected to each output channel (left
and right), a panner value input (the value of the dial object), a mathematical
expression that converts the panner input value to radians, and a
mathematical expression for calculating the amount of signal for each
channel. The incoming signal is mono and is routed to left and right panning
paths, and leaves the subpatch as a mono signal only if
the panner control is hard left or hard right.
The range of the dial object in the main patch is -45 to 45. The abs
object, hidden from view in the main patch, converts any negative value from
the dial object to an absolute value that gets displayed in an integer object
beneath the dial. By looking at the dial, and the integer object, it can be
determined to what side and by how much a sound is panned. When the dial
object is moved left of center, it is actually outputting negative values, with
-45 indicating it has been rotated fully counterclockwise. The output of dial
goes to both a cosine and sine function.
The result of the cosine and sine functions are sent to a mathematical
equation that calculates the amount of gain per channel to achieve a pan.
These equations, written so that MAX can understand them, are expr ($f1-
$f2)*((sqrt(2))/2) for the left channel and expr ($f1+$f2)*((sqrt(2))/2) for
the right channel (Roads 460). A close look at the equations reveals that
one uses a sum and the other uses the difference of the sine and cosine
values. This results in two extremes, where one equation will produce a value
of one while the other produces a value of zero. When the value from the
dial object is zero (center), both equations produce the same result. As a
result, these equations allow for the power of the signal to be constant
throughout the soundstage, just like any other audio console. The values of
equations are sent to a *~ object and are multiplied with the incoming audio
signal, thus varying the amount of signal to each channel in the soundstage
based upon the value of the dial object in the main patch.
Panner Subpatch (below)
Just like the autofade function described earlier, autopan allows the
mixer to pan a sound from one location in the soundstage to another over a
specified amount of time in milliseconds. The user can also pause an autopan
operation and then resume it. The code from the subpatch autofade is
nearly identical for the subpatch autopan, and is located within the subpatch
autocontainer. There are two key differences in the code between the two.
An autofade operation ranges from 0 to 100. An autopan operation
ranges from -45 (left) to 45 (right). To keep the values of the panner
positive within the subpatch autopan for the line object, they must be scaled.
The inlets that receive the panner’s current value and the panner’s
destination value are followed by a + object that scales the value by 45, so
that when the panner is hard left (-45), the line object receives that as a
value of zero.
The portion of autopan that differs from autofade. Notice the two + objects
which scale the incoming panner values by 45 for use with a line object.
Mute and Solo
“Although many of the obstacles present in analog technology are
absent in a digital implementation, seemingly trivial exercises in signal
processing might require sophisticated digital circuits.” Signal selection is
also the third basic function of a console (Pohlmann 635-6). The mute and
solo functions for this mixer utilize ubuttons and a subpatch named
mute/solo. All of the functionality for these features is implemented in the
subpatch mute/solo. This subpatch includes its own subpatches,
mutesoloselectionodd and mutesoloselectioneven, for processing the
commands that allow for the mute and solo buttons to function properly.
There is also an if expression for determining if channels are linked or not
and graphic gates and zero and one messages to pass the proper commands
for the desired function. Beyond the logic section of the subpatch
mute/solo, there is a section that processes the actual mute and solo
commands on the channel. This includes subpatches named audiomuteodd,
audiomuteeven, audiosoloodd, and audiosoloeven, along with one and zero
To fully explain how all of these subpatches interact with each other
would result in a complicated and abstract text. It’s best to analyze the
commented code in the patch to see exactly how it all works. Below are the
goals of the mute and solo functions for each channel.
Functional Goals of the Mute and Solo buttons on Each Channel
•If a channel is muted, any audio file being played through that channel
should no longer be heard. If it is unmuted, the audio should be heard.
•If a channel is soloed, only the audio file being played through that
channel should be heard. If it is unsoloed, all audio that is not muted
should be heard.
•If a channel is muted, and that channel’s solo button is selected, the
mute function should be disabled and the solo function should be
•If a channel is soloed, and that channel’s mute button is selected, the
solo function should be disabled and the mute function should be
•If two channels are linked, clicking the mute button for either channel
should control the state of the mute function for both channels.
To achieve these goals, the subpatch mute/solo and all the subpatches
within were created to accomplish these tasks. Below is a simplification of
how each function outlined above is accomplished.
Simplification of Mute/Solo Logic
•If the channels are linked, pass the mute command to both channels,
otherwise, only pass it to the channel being acted upon.
•If a mute is used, determine which channel it is being used on and set its
state according to the user’s input. If the channels are linked, set the
mute state for both channels, setting gates so that the mute command
does not get sent back to the channel it originated from (prevent an
•If a mute is used on a channel that is already soloed, then disable that
channel’s solo function, then engage the mute function on that channel.
•If a solo is used, and effectively mute all other channels or enable all
channels based on the user’s input.
•If a solo is used on a channel that is already muted, then disable that
channel’s mute function, then engage the solo function on that channel.
Once the logic evaluation has been completed, the commands are then
passed on to the other portion of the subpatcher mute/solo that will actually
mute or solo the audio. Mute commands are passed on to the appropriate
audiomute patcher, where the audio signal and the output of mute~ merge
and go through a pass~ object. The pass~ object guarantees a zero output
when muted. Solo commands are passed on to the appropriate audiosolo
patcher, where the audio signal leaving the audiomute patcher and the output
of a second mute~ merge and go through a pass~ object. Audio that is
muted does not pass beyond its audiomute subpatch. Audio that is muted by
means of a solo function does not pass beyond its audiosolo subpatch. Audio
that is neither muted nor soloed passes through its audiosolo subpatch, as
does the audio of a soloed channel, where the signal then returns to the main
patch for further processing.
Audiomute subpatch Audiosolo subpatch
One portion of the subpatch mute/solo was used to allow for linked
muting and is deserving of a deeper overview. The ubuttons used for
muting have four (4) outlets and an inlet. When attempting to change the
mute state of linked channels from the even channel’s mute control, an
infinite loop was impossible to avoid using the mouse-up and mouse-down
outlets. To workaround this problem, the fourth outlet of the even mute
ubutton is used to prevent an infinite loop with linked muting. This outlet
sends a one message only if the user clicks this button (mouse-up and
mouse-down outlets echo any input to the ubutton). This one message is
used to set a graphic gate in the logic section to prevent an infinite loop, and
that same one message, after passing through togedge, is used to change
the mute state of the odd channel. The mouse-up and mouse-down outlets
of the even channel change the state of that channel’s mute in a linked
Above: Code that allows for group muting to be controlled with the mute
ubutton on an even channel in a group.
To loop the soundfiles loaded into each channel, two gates and a toggle
(labeled Loop Indicator) were used. When each soundfile stops, a bang is
generated by the sfplay~ object. The bang from sfplay~ when a soundfile is
sent via a bangWhenDonePlaying send message to a subpatch named
transportControls. In that subpatch, this bang is routed to a gate, and if the
stop button has not been activated, then the stop message from sfplay~
continues to a second gate. If the Loop Indicator toggle is engaged
(indicating that the file will loop) the bang then passes through the
second gate and to a 1 message. This 1 message is then sent out of the
subpatch transportControls via a send transport message back to the main
patch, where it is received and sent to the sfplay~ objects to start playback
once again. The pause and resume operations have no effect on the state of
the loop indicator or the loop function. The loop function is only useful if all
files being used are of equal length, since there is no timeline for the
positioning of files with shorter durations. A single send and receive object,
named transport, sends all transport controls to the sfplay~ objects.
The loop indicator toggle may also be activated and deactivated with
the keyboard shortcut Shift+Apple+L. The keyup object, in the subpatch
transportControls, outputs the numberic codes for keys pressed on the
keyboard. A + object takes these numeric codes and adds them together.
The sum of the codes are then sent to a select object. When the sum of the
keys pressed is 805 (37 for L, 512 for shift, and 256 for Apple), the select
object (set for 805) sends a bang that is routed to the transport loop toggle
and changes its state.
Transport playing .
Consoles often have a Dim control in their monitoring section. The
purpose of this control is to lower the level of the console’s main output
without having to adjust a fader or other volume control (Eargle 158). This
is done in the Max/MSP patch with a ubutton, labeled Dim, configured to act
as a toggle (as opposed to a button). When clicked, a bang is sent out of the
ubutton’s Mouse-Down outlet to a message box with a value of 0.3. This
value is then sent to the dac~ object for the stereo output channels,
effectively lowering the signal at the output to -
10dB below unity without adjusting the master fader. When the ubutton is
clicked again, a bang is sent out its Mouse-Up outlet, and that bangs the
value that the master fader is set to, resulting in the desired output level
A meter is provided for each channel in the mixer. The meters are
configured to sample the incoming signal once every 15 milliseconds. The
meter is configured to have twenty (20) LED segments, each representing 1
dB. The first 5 LEDs (-19 dBFS to -15 dBFS) are green, the next 5 LEDs (-14
dBFS to -10 dBFS) are yellow, and the next 10 LEDs (-9 dBFS to 0 dBFS) are
red. In the main patch, there are two ubuttons configured as buttons (as
opposed to toggles) with text overlays that read Pre Fader Metering and
Post Fader Metering. Clicking on these ubuttons changes the metering state
respectively. There are also send prefaderdown and send
postfaderdown objects for routing the bangs from the ubuttons to the
metering subpatches without patchcords. Toggle objects indicating pre or
post fader metering round out the objects in the main patch. The send
objects send data to corresponding receive objects in the metering
subpatches. The toggle indicators receive their states from the subpatch
metering, and the signal for the channel, both pre and post fader, is sent
to the metering subpatches.
Inside the subpatches is a loadbang, two zero messages, two one
messages, two mute~ objects, subpatches for pre and post fader signals,
and in the subpatch metering, outlets for pre and post fader toggle indicator
messages. There are also receive objects for prefaderdown and
postfaderdown. Upon loading the subpatch metering, a loadbang object
changes the Post Fader Metering toggle indicator to active. Next, the Post
Fader signal mute is disabled by banging a one message, which allows the
signal to flow out of the subpatch and to the meter in the main patch. Third,
the pre fader toggle indicator in the main patch is set to inactive. Fourth,
the pre fader mute~ object is activated by sending a zero message to it.
Without any user intervention, the metering is now set to post fader.
When a ubutton receives a Mouse-Down command, for either pre-fader
or post-fader metering, the bang is sent to the subpatch metering via either
the send prefaderdown object or send postfader down object. It is received
in the subpatch by the receive prefaderdown or receive postfaderdown
object, where it bangs a zero message for the opposite metering state and a
one message for the selected metering state. The one message enables the
toggle object indicator for the selected metering
state, while disabling the mute~ object associated with that metering state.
The zero message disables the toggle object indicator for the other
metering state while activating the mute~ object associated with that
Since the metering selection, either pre or post fader, is global, the
subpatch for channels numbered greater than 2 is slightly different. The
outlets for the toggle objects used to indicate which type of metering is
selected have been omitted from the subpatch metering2. This subpatch
is used for all channels numbered greater than 2, as there is only one
location where pre or post fader metering is indicated. For an explanation of
how mute~ works with the subpatches in regards to metering, see the usage
of it in the Mute and Solo section on page 31.
Metering User Interface and Send Objects (below)
Metering Subpatch (below)
Metering2 Subpatch (below)
The chart in chapter 2, evaluating the capabilities of available mixing
consoles, has one constant. Every console has at least 4 bands of
equalization. Indeed, “Any console must provide equalization faculties such
as lowpass and highpass filters, presence, and shelving filters of various
types” (Pohlmann 637). In order ot have a mixer patch that could be
comparable to a console in terms of functionality, a 4 band equalizer is
present on every channel. This is a graphic equalizer, and the bandwidth of
each band (Q) can be adjusted by clicking and dragging on the outer edge of
the band. The gain for the band can be adjusted by clicking within the band
and dragging up or down, for boost or cut, respectively.
The center frequency of each band can be adjusted by clicking and dragging
on the center red line that appears when the cursor is within a
Equalizers “...can be designed using a variety of techniques, such as a
cascade of biquadratic sections” (Pohlmann 637). This is how the EQ has
been implemented in this mixer. The output of the filtergraph~ object,
whose manipulation is described above, is sent to a cascade~ object. The
cascade~ object is a collection of biquad~ objects, which are two-pole two-
zero filters. By having four bands of equalization, the cascade~ object
effectively has four two-pole two-zero filters. An On/Off button, utilizing
the TwoStateButtonOutside subpatch described earlier, is used to control
whether or not the equalizer is in the signal chain.
To eliminate unnecessary computation of an equalized signal when the
equalizer is not engaged, a begin~ and selector~ object is used. Begin~ is
connected to the signal input of cascade~, which in turn is connected to the
second inlet of a selector~ object. The first inlet of selector~ is the audio
signal without being routed to the cascade~ object. The state of the On/Off
button bangs messages that select either the equalized signal or the
unequalized signal. By using the begin~ object, cascade~ doesn’t do anything
unless its output is selected to pass through selector~ by turning the
Above: The EQ subpatch.
This project culminated in the creation of an eight channel mixer to be
used for the mixing stage of a project (as opposed to tracking). The eight
channels can be linked into groups of 2, for a total of four groups. Channels
1 and 2 make one group, channels 3 and 4 make another group, etc. Each of
the eight channels can be muted individually. The mute will apply to the group
if the group function is enabled. Each channel can also be soloed. The solo
function does not apply to the group. Each channel has an independent fader
control, and when the channels are grouped, the selected channel’s fader
control will also control the other fader in the group. This control
relationship may also be inverted so that two channels that are grouped may
be crossfaded. An autofade function is
provided to allow for automated fades. The user specifies the destination
value of the fader in dB, the amount of time for the fade in ms, and then
clicks a start button to initiate the fade. The start button changes to a
pause button until the fade is complete, allowing the user to stop and
continue the fade if desired.
For each channel, a pan control is used to position the audio on each
mixer channel within the stereo soundfield. The panner has a range of 45
left to 45 right. Shortcut buttons are found along the outside of the panner
dial, allowing the user to instantly pan the signal far left, center, or far right.
Panner controls may also be linked as well, so that two channels can be
panned in either the same direction or in opposite (inverse) directions. An
autopan function is provided to allow for automated panning. The user
specifies the destination value of the panner, the amount of time for the pan
in ms, and then clicks a start button to initiate the pan. The start button
changes to a pause button until the pan is complete, allowing the user to
stop and continue the pan if desired.
A four band equalizer is provided for each channel. The user can turn
this function either on or off or each channel. It is a graphic equalizer that
allows for the size of each band, its Q value, and its boost or cut to be
adjusted while clicking and dragging within the graphic window. Metering is
provided for each channel and can be either pre or post fader. The meter in
the master section is post fader and represents the signal as it is sent to
the dac~ object. All meters range from -20dBFS to 0dBFS and update every
The transport allows for soundfiles to be started, stopped, paused,
resumed, and looped (equal length soundfiles are required for the loop
function to work properly). The master fader lacks the panpot, autopoan,
solo, and mute functions found on each individual channel. It does have two
meters, one for each stereo channel, and a dim button that allows the user
to drop the output level to a maximum of -10dBFS without adjusting the
To put the usability of the Max/MSP mixer to the test, I used an eight
track recording I had of a song titled “Iranonthesea” by the band Mori Stylez
(since defunct). The recording was done live to a Tascam DA-78, a 24 bit
DTRS recorder. The source was loaded into Pro Tools digitally, then edited
down to eight soundfiles of equal length for this one song (necessary to have
the transport loop function be effective if used). Below is a more detailed
description of the setup, taken from my original recording notes.
The plan originally was to use all eight channels on the Precision
8 microphone preamplifier and 3 channels of the Mackie 1642 microphone
preamplifiers. I had set this up using a D-sub from the Precision 8 to the
DA-78, and then ran some unbalanced lines from the 1642 into the DA-78. I
then discovered that the DA-78 only allows for one set of inputs to be used,
either balanced or unbalanced. As a result, I had to send the bassoon,
clarinet, mandolin, and guitar microphones through the 1642’s microphone
preamps. This was necessary because the four instruments are played by
two individuals, and they often switch during the songs. The Precision 8 also
lacks an input pad. This proved to be costly on the snare track, where I also
used a microphone that does not have a built in attenuator, the Neumann
KM184. The signal was not always distorting at the preamp, but at the tape
machine. It is usable, but not as pristine as I would have liked. All I could do
was move the mic back a bit (see page 52 for a microphone list and floor
The following conclusions are based on my using this constructed mixer
to mix the recorded tracks. The mix is included on the complimenting CD, as
are the individual tracks loaded from the source.
This mixer patch is designed to be used during the mixing stage of a
project (as opposed to the tracking stage). This mixer serves this particular
purpose well because sound files of equal length can be loaded, played back,
looped, stopped, paused, and resumed - much like any DAW available today.
The construction of the patch would have to be different to accommodate
The functional logic behind consoles such as Yamaha’s O2R and DAWs is
largely based upon gates (or an abstract of the concept). They are excellent
and simple objects for allowing for one object to control another while
avoiding a feedback loop that would crash (or create erratic behavior in) a
digitally controlled device. The gate also allows for individual control of a
channel or that same control to be applied to grouped channels by creating
separate logic paths that when enabled control the same parameter. The
positioning of the gate within the signal path is crucial. An improperly
positioned gate could serve its intended
purpose, but do so with other unwanted results. The transport of a DAW
can be controlled through the same object. Two gates in series will prevent a
stop command from restarting the transport if a loop function is engaged.
Pre or post fader metering on a console or DAW can be similarly controlled
with gates whose states alternate depending upon the selection.
With Max/MSP, the gate and gate~ object are not always the best
object to use for implementing a particular function. True, a gate or gate~
should prevent a signal from passing, and often they do. On some occasions,
the gate~ object can create undesired results. It also doesn’t stop
unnecessary computations from taking place, it simply stops the signal from
proceeding. There are situations where the begin~ object in concert with a
selector~ object has advantages. Not only will the selector~ object prevent
unselected inputs from passing through, but in concert with a begin~ object
it stops computations on unselected inputs. This is very useful for the
equalization function of this mixer, where calculating four bands of EQ, when
not even being used, would be an inefficient use of CPU power. In other
cases, the essence of a gate~ object is desired, but it is still not the best
choice. This was the case with the mute/solo function, where pass~ had to
be used since it guarantees an output of zero when the input is not allowed
to pass through.
While it is necessary for the faders to be logarithmic and have their
values expressed in dB, the scale of the faders is not ideal. On any console,
unity or 0dB gain on a fader is relatively close to the top of its range. In this
patch, the unity or 0dB point is towards the bottom of the fader. There is a
great deal of resolution above unity gain, going all the way to the fader
maximum of +12dB. The range beneath unity gain is not ideal. It would be
best if this were corrected to reflect traditional console and mixer
Above: A signal fader at unity gain (notice the 0 in the dB readout). The
flaw described above is obvious.
The autofade operation was inspired by t.c. electronic’s M5000, a
digital processor that had this function. The function works as desired, and
the only way to improve upon it would be to have a timeline in the mixer
where one could specify points for a fade once and always have them
repeated. Since there is no automated mixing over time in this patch, the
user always has to set the autofade and execute it with each pass. The
same may be said of the autopan operation.
Fader linking works effectively, yet the inverse fader relationship
option could use some modification. When this option is enabled, channels
may be crossfaded, but the crossover point is not ideal. For reasons
discussed in the first chapter on mixing, the best crossover point would be -
3dB (a foolproof point would be -6dB, but since crossfades are used for
differing material, it is not necessary). The crossover point when the
inverse fader relationship option is engaged is +6dB. This is the crossover
point because the faders use their linear scales for the inverse function, and
the point where each fader is at the halfway mark of its linear range is
+6dBFS. Unless the user is working with audio files that do not peak above -
6dBFS, this option may not be useful, as the output could be distorted during
a crossfade. The autopan function, even with the inverse panner relationship
option engaged, has no obvious drawbacks.
Above: Linked faders with the inverse fader relationship option engaged.
The flaw described above is obvious.
The meter~ object functions properly. It would be ideal if it supported
a higher number of individual meter segments, so the range of the meter
could be extended closer to the least significant bit. Even set at its
maximum range, as it is in this mixer, with each meter segment representing
1dB, it only extends to -20dBFS.
Above: Stereo meters with signal present. Though a Max/MSP limitation, no
signal below -20dBFS would be observed on these meters, even if present.
Some of the above limitations or drawbacks are the result of
programming, while others are simply a function of the capabilities in
Max/MSP. If the drawbacks as a result of programming were overcome,
then it would be possible to add additional functionality to the patch that
would place it on a more comparable level with digital hardware and software
based mixers. These features would include timeline based automation and
compression/limiting on each audio channel, including the master output.
This patch overcomes a few limitations (or lack of features) in digital
hardware and software based mixers that the author has seen or has heard
other users complain about. Those would include,
but not be limited to, shortcuts for hard-and-fast panner values and group
panning. Yet it would be foolish to add the missing features mentioned above
without first correcting the existing flaws. Flaws in software mixers that
don’t get fixed often never get fixed. Any software mixer with a bug for
more than one major release version is a perfect example of this.
This mixer patch serves as a functional representation of a console. It
demonstrates and emulates functions that audio mixing professionals expect
to see in any console or mixer, effectively putting digital mixing theory into
Boylestad, Robert L. Introductory Circuit Analysis. 8th ed. Upper Saddle
River: Prentice Hall. 1997.
Bullins, Strother. “Console Shopping?” MIX Aug. 2004: 42-7.
Castine, Peter. Email. 7/12/04.
Eargle, John M. Handbook of Recording Engineering. 3rd ed. New York:
Van Nostrand Reinhold, 1996.
Masciarotte, Oliver. “Computer, Do the Math!” MIX Feb. 2003: 92.
O2R Version2. Digital Console. Yamaha, 1997.
Pohlmann, Ken C. Principles of Digital Audio. 4th ed. New York: Mc-
Graw Hill, 2000.
Pro Tools. Vers. 6.4.1. Computer Software. Digidesign, 2004.
Roads, Curtis. The Computer Music Tutorial. Cambridge: MIT Press. 1996.
Tomarakos, J. and C. Duggan. “32-Bit SIMD SHARC Architecture Digital Audio
Signal Processing Applications.” J. Audio Eng. Soc. 48 (2000): 221.