ï~~Proceedings of the International Computer Music Conference (ICMC 2009), Montreal, Canada
August 16-21, 2009
objects or connections, sending messages to objects, etc. A
number of issues have emerged so far in the development
of FrameWorks 3D and which are discussed below, with
outlines of solutions found in Section 4.
3.1. Sample Accurate Timing
To meet commercial standards, audio events must occur
with sample accurate synchronization. To achieve this in
Max/MSP, audio signals can be used for control of timecritical events. However, Max/MSP's 32-bit floating-point
sample values limit the length of accurate sample counts to
around six and a half minutes at 44.1KHz sampling rate,
insufficient for sequencer applications.
3.2. Bi-directional Communication
To effectively manipulate the audio engine, two-way
communication between the engine and Java is necessary.
For example, Java code will trigger a Max patch to execute
audio processing, monitor the progress of the task and
execute subsequent tasks on completion. While Java code
can directly message Max objects, in general Max objects
have no such access to objects in the JVM, and can only
pass messages or signals to an mxj- object's inlets.
3.3. Multiple Threads
Communication with the engine is complicated by the fact
that both Java and Max contain multiple concurrent
threads. Max has one audio thread and up to two event
threads, depending on the overdrive setting. Java can
spawn new threads as needed, while Swing (Java's
lightweight GUI API) has an event dispatch thread and a
timer thread, and Java3D has multiple threads. This can
lead to deadlocking and resource conflicts (e.g. a thread
trying to use an object whilst another is still instanciating
it) and careful programming is needed to avoid these.
3.4. Off-line rendering
In addition to setting up real-time audio playback in the
engine, FrameWorks 3D requires off-line rendering for
framework updates, where audio data must be recalculated
as fast as possible without audio output. Another use of
off-line rendering is for faster-than-real-time bounce to
disk. Max is generally focussed on real-time operation.
3.5. Processing
Various off-line processes are required for relations and
will need to be added to over time and plug-ins are the
standard design pattern for this. Most audio plug-in
formats are designed for real-time operation, but can also
function off-line. FrameWorks 3D could use Max/MSP
hosted VST plug-ins directly, but this would place
limitations on the types of processes that can be used.
3.6. User-Interface
In order for Java to take over the user-interface, it is
necessary to conceal the underlying Max patches and Max
menus. Unlike Pure Data, Max does not have a headless
mode (no GUI) and indeed, FrameWorks 3D needs Max's
user interface objects for plug-in editor windows.
4. IMPLEMENTATION
FrameWorks 3D has been designed to fully separate the
audio engine from the data model and GUI, so that this can
be cleanly re-implemented for other API's (e.g. Pure Data,
Java Sound, Stk/RtAudio). A Java interface AMSEngine
specifies the required methods, while a MaxMSPEngine
class provides the implementation. A separate pair of
interfaces TransformManager and TransformPlugin
defines the plug-in architecture. MaxMSPEngine then
implements TransformManager, and uses a nested class
MaxMSPTransformPlugin to realise the plug-in interface.
4.1. Clocks and timing
A limited set of "hi-res" external objects for Max/MSP has
been developed by Joshua Kit Clayton, which use signal
pairs to achieve 48-bit precision, providing accurate
sample counts to over 200 years [10]. However, not all
aspects of these objects are "hi-res" (e.g. there is no "hires" setting of the initial value for the hr.count- object)
which limits the precision in some areas of control.
The timing clock for playback and rendering uses
hr.count-, a "hi-res" signal counter incrementing by one
each sample. Two instances of the clock patch are used,
one for global time, which reflects the current position in
the framework, the other for local time which is used when
the global time shouldn't be changed, e.g. for isolated
playback of individual clips, or calculation of clip data.
The outputs from the counters are picked up directly by
clip patches and also fed into the mxj- object to update
GUI elements in Java (figure 2).
Figure 2. The connections to mxj~ in FrameWorks 3D.
4.2. Clips and Communication
Clips use Max's buffer~ objects to either load an audio file
or receive audio from a relation. Playback is controlled by
the "high-res" clock, using hr.index~ to read samples from
the buffer~ and write to the output. Comparison and
arithmetic operators are used to limit playback to the start
time, buffer offset and duration of the clip. Additional
436