chuck-max - the ChucK engine embedded in a Max/MSP external

February 25, 2026 · View on GitHub

chuck~ help

This cross-platform project combines the power of ChucK audio programming with the flexibility of Max/MSP. It includes a custom Max/MSP object, chuck~, that runs version 1.5.5.3-dev (chai) of the ChucK engine for real-time sound synthesis and audio processing.

Quick Start

For the impatient: Download the pre-compiled chuck-max packages from Releases and check out the cheatsheet.

Overview

chuck-max is a cross-platform open-source Max package that embeds the ChucK audio programming language engine in a Max/MSP external (chuck~). This powerful integration allows you to:

  • Generate and process audio by running ChucK files and evaluating code with real-time control of parameters.
  • Layer multiple sounds from a single instance by running multiple ChucK files concurrently
  • Modify audio processes on-the-fly using ChucK messages via Max messages.
  • Interact with Max via MIDI and OSC protocols

Key Features

  • Complete ChucK Examples: Includes a full set of current ChucK examples
  • Rich ChucK plugin (Chugin) Ecosystem: Includes default CCRMA chugins as well as (for macOS):
    • WarpBuf - Time-stretching and pitch-shifting.
    • Faust - LLVM-based DSP platform.
    • FluidSynth - Software synthesizer with SoundFont support.
  • Extra chugins: include experimental plugins:
    • AbletonLink - syncronization using ableton link
    • AudioUnit - audio unit plugin support (macOS only)
    • CLAP - clap plugin support
    • VST3 - vst3 plugin support
  • Max Integration: Comprehensive Max patchers for testing and demonstration
  • Community Contributions: User-contributed patchers and code examples

Build Guide

The base chuck-max system consists of a Max package with the chuck~ external, the default set of CCRMA chugins and extensive examples, tests and Max patchers.

To get up and running, type the following while in the Max Packages directory.

git clone --recursive https://github.com/shakfu/chuck-max.git
cd chuck-max

Building on Windows

Building the base system on Windows requires Visual Studio Community Edition or higher and cmake to be available on your system.

If make.exe is available in your PATH via something like w64devkit, then make will build the base system on Windows. Otherwise, type the following:

mkdir build
cd build
cmake ..
cmake --build . --config Release
cmake --install . --config Release

Note that the advanced chugins --Faust.chug, WarpBuf.chug and FluidSynth.chug -- are not yet implemented on Windows.

Building on MacOS

Building chuck-max on MacOS requires the following:

  1. Xcode from the App store or Xcode Command Line Tools via xcode-select –install

  2. The Homebrew package system1.

Base MacOS Build

To build the base system, install the following dependencies using Homebrew as follows:

brew install cmake bison flex

If you've cloned the chuck-max package outside of $HOME/Documents/Max [8 | 9]/Packages, then make setup will create a symlink of the folder in the Packages directory and make it available to Max.

Now it should be possible to build the base system with either of the following two options:

  • make or make native: builds the external using your machine's native architecture which is arm64 for Apple Silicon Macs and x86_64 for Intel Macs. This is the default build option.

  • make universal: build the external as a universal binary making it compatible with both Mac architectural variants. This is useful if you want share the external with others in a custom Max package or standalone.

Full MacOS Build

A few advanced chugins, Faust.chug, WarpBuf.chug and FluidSynth.chug are not included in the Base system by default, these are:

  1. The Faust chugin incorporates the full llvm-based faust engine and DSP platform, making it exceptionally powerful and larger in size compared to other chugins, approximately 45 MB when stripped down. It necessitates at least two output channels to function correctly and utilizes the libsndfile library.

  2. The WarpBuf chugin enables time-stretching and independent transposition of an audio file's pitch. This functionality is achieved through the use of the rubberband, libsndfile, and libsamplerate libraries.

  3. The FluidSynth chugin is a software synthesizer based on the SoundFont 2 specifications. On MacOS, it requires libsndfile as well.

For a full MacOS build which includes the above chugins, use Homebrew again to install the following dependencies:

brew install autogen automake fluidsynth rubberband libsamplerate

This is actually an abbreviated way to install all the dependencies and sub-dependencies:

macos-adv-deps

After these are installed, type the following for a full chuck-max build2:

make brew

User Guide

  • The chuck~ object can take the following arguments:

    • [chuck~] : single channel in/out, no default chuck file
    • [chuck~ <N>] : N channel in/out, no default chuck file
    • [chuck~ <filename>] : single channel in/out with default chuck file
    • [chuck~ <N> <filename>] : N channels with default chuck file
    • [chuck~ <N> @tap <M>] : N audio channels + M tap outlets for reading global UGens

It's recommended to choose 2 channels for stereo audio.

If a <filename> argument is given it will be searched for according to the following rules:

  1. Assume it's an absolute path, use it if it exists.

  2. Assume that it's a partial path with the package's examples folder as a prefix. So if stk/flute.ck is given as <filename>, the absolute path of the package examples folder is prepended to it and if the resulting path exists, it is used.

  3. Assume <filename> exists in the parent patcher's directory. Test that this is the case and if it is, use it. This is useful if you want to package patchers and chuck files together.

  4. Use Max's locatefile_extended search function to search for the <filename> in the Max search path. The first successul result will be used.

Core Messages

As of the current version, chuck~ implements the core Chuck vm messages as Max messages:

ActionMax msgMax msg (alias)
Add shred from fileadd <file> [arg1 arg2 .. ]+ <filepath> [args]
Run chuck file (save last used)run <file>
Eval code as shredeval <code>
Remove shredremove <shredID>- <shredID>
Remove last shredremove last
Remove all shredsremove allremoveall
Replace shredreplace <shredID> <file>= <shredID> <file>
List running shredsstatus
Clear vmclear vmreset
Clear globalsclear globals
Reset idreset id
Timetime

It's worth reading the ChucK Language Specification's section on Concurrency and Shreds to get a sense of what the above means. The first paragraph will be quoted here since it's quite informative:

ChucK is able to run many processes concurrently (the process behave as if they are running in parallel). A ChucKian process is called a shred. To spork a shred means creating and adding a new process to the virtual machine. Shreds may be sporked from a variety of places, and may themselves spork new shreds.

Utility Messages

The core set of chuck vm messesages is also extended in chuck-max with the following utility messages:

ActionMax msg
Set file attribute (does not run)file <path>
Set full path to editor attributeeditor <path>
Prevent running shreds when dsp is offrun_needs_audio
Open file in external editoredit <path>
Probe chuginschugins
Get/set loglevel (0-10)loglevel & loglevel <n>
Get state of chuck vmvm
Launch chuck docs in a browserdocs
Clear Max consoleclear console
Set global UGen to taptap <ugen_name>
Clear tap (output silence)tap
List all VM parametersparam
Get VM parameter valueparam <name>
Set VM parameter valueparam <name> <value>
List all shredsshreds
List ready/blocked shredsshreds ready/blocked
Get shred infoshreds <id>
Query shred IDsshreds highest/last/next
Get adaptive mode statusadaptive
Set adaptive block sizeadaptive <size>

Parameter Messages

Once a shred is running you can change its parameters by sending values from Max to the chuck~ object. To this end, ChucK makes available three mechanisms: global variables, global events, and callbacks which are triggered by events. chuck~ maps these chuck language elements to corresponding Max/MSP constructs as per the following table:

ActionChucKMax msg
Change param value (untyped)global variable<name> <value>
Dump global variables to consoleglobal variableglobals
Trigger named eventglobal eventsig <name>
Trigger named event all shredsglobal eventbroadcast <name>

You change a global variable by sending a <variable-name> <value> message to a chuck~ instance where the value can be an int, float, string, array of ints or floats, etc. You can also trigger events by sending sig or signal messages, broadcast messages as per the above table.

Note: You can't use the ChucK types of dur or time in Max. Also, while in the above case, the Max msg seems untyped, it must match the type of the chuck global variable. So if you connect a Max number or flownum object to a message box, it needs to match the type of the global variable (int/float).

See help/chuck~.maxhelp and patchers in the patchers/tests directory for a demonstration of current features.

Parameter Messages using Callbacks (Advanced Usage)

In addition to the typical way of changing parameters there is also an extensive callback system which includes listening / stop-listening for events associated with callbacks, triggering them via sig and broadcast messages and also setting typed global variables via messages and symmetrically getting their values via typed callbacks:

ActionChucKMax msg
Listen to event (one shot)global eventlisten <name> or listen <name> 0
Listen to event (forever)global eventlisten <name> 1
Stop listening to eventglobal eventunlisten <name>
Trigger named callbackglobal eventsig <name>
Trigger named callback all shredsglobal eventbroadcast <name>
Get int variableglobal variableget int <name>
Get float variableglobal variableget float <name>
Get string variableglobal variableget string <name>
Get int arrayglobal variableget int[] <name>
Get float arrayglobal variableget float[] <name>
Get int array indexed valueglobal variableget int[i] <name> <index>
Get float array indexed valueglobal variableget float[i] <name> <index>
Get int associative array valueglobal variableget int[k] <name> <key>
Get float associative array valueglobal variableget float[k] <name> <key>
Set int variableglobal variableset int <name> <value>
Set float variableglobal variableset float <name> <value>
Set string variableglobal variableset string <name> <value>
Set int arrayglobal variableset int[] <name> v1, v2, ..
Set float arrayglobal variableset float[] <name> v1, v2, ..
Set int array indexed valueglobal variableset int[i] <name> <index> <value>
Set float array indexed valueglobal variableset float[i] <name> <index> <value>
Set int associative array valueglobal variableset int[k] <name> <key> <value>
Set float associative array valueglobal variableset float[k] <name> <key> <value>

Tapping Global UGens

The @tap attribute allows you to read audio samples directly from global UGens declared in your ChucK code. This enables advanced signal routing where ChucK-generated audio can be processed separately in Max.

Setup:

Create a chuck~ object with the @tap attribute specifying the number of tap outlet channels:

[chuck~ 2 @tap 2]

This creates an object with 2 audio input/output channels plus 2 additional tap outlets.

ChucK Code:

In your ChucK file, declare a global UGen and route audio to it:

// Declare a global UGen for Max to tap
global Gain gTap => blackhole;

// Route your synthesis to it
SinOsc osc => gTap;
osc => dac;  // still hear it through normal output

440 => osc.freq;
while(true) 1::second => now;

Max Usage:

After running the ChucK file, send the tap message to specify which global UGen to read:

tap gTap

The tap outlets will now output the audio from the gTap UGen. To stop tapping (output silence), send tap with no arguments.

Note: The number of tap channels must match the UGen's channel count. For stereo UGens, use @tap 2. The tap outlets appear after the main audio outlets.

VM Parameter Querying

The param message allows you to query and set ChucK VM parameters at runtime.

List all parameters:

param

This displays all available parameters grouped by type (integer, string, string list) with their current values.

Get a specific parameter:

param SAMPLE_RATE
param WORKING_DIRECTORY

Set a parameter:

param VM_ADAPTIVE 256
param WORKING_DIRECTORY /path/to/files

Available parameters:

ParameterTypeDescription
SAMPLE_RATEintAudio sample rate
INPUT_CHANNELSintNumber of input channels
OUTPUT_CHANNELSintNumber of output channels
VM_ADAPTIVEintAdaptive block size (0 = disabled)
VM_HALTintHalt VM on no shreds
CHUGIN_ENABLEintEnable chugin loading
DUMP_INSTRUCTIONSintDump VM instructions
DEPRECATE_LEVELintDeprecation warning level
VERSIONstringChucK version (read-only)
WORKING_DIRECTORYstringDefault working directory
IMPORT_PATH_SYSTEMstring listSystem chugin search paths
IMPORT_PATH_USERstring listUser chugin search paths

Shred Introspection

The shreds message provides detailed information about running shreds (ChucK's concurrent processes).

List all shreds:

shreds

This displays all shreds with their ID, name, and current state (running, ready, or blocked).

Filter by state:

shreds ready      <- list shreds ready to run
shreds blocked    <- list shreds waiting on events

Get detailed info about a specific shred:

shreds 1

This shows the shred's name, state flags, wake time, start time, and any arguments.

Query shred IDs:

shreds highest    <- highest shred ID ever assigned
shreds last       <- last shred ID assigned
shreds next       <- next shred ID to be assigned
shreds count      <- total number of running shreds

Adaptive Block Processing

The adaptive message controls ChucK's adaptive block processing mode, which can improve CPU performance for certain workloads.

Query current status:

adaptive

Enable adaptive mode:

adaptive 64       <- enable with max block size of 64 samples
adaptive 128      <- enable with max block size of 128 samples

Disable adaptive mode:

adaptive 0        <- disable adaptive mode
adaptive 1        <- also disables (size must be > 1 to enable)

When adaptive mode is enabled, the shreduler can process multiple samples at once when no shreds need to wake up, reducing per-sample overhead. The max block size limits how many samples can be processed in one batch.

Note: The optimal block size depends on your workload. Larger values may improve performance but can affect timing precision for time-sensitive operations. Start with values like 64 or 128 and adjust based on your needs.

Package Structure

The chuck-max package consists of the following folders:

chuck-max
├── examples
│    ├── ai
│    ├── analysis
│    ├── ...
│    ├── **chugins**
│    ├── ...
│    ├── **fauck**
│    ├── **faust**
│    ├── ...
│    ├── **max**
│    ├── ...
│    ├── **test**
│    ├── ...
│    └── warpbuf
├── externals
│    └── chuck~.mxo
├── help
├── media
└── patchers
    ├── abstractions
    ├── contrib
    └── tests

Start with the chuck~.maxhelp file in the help folder for an overview of the external's features. The media folder also has a pdf cheatsheet of available chuck~ methods.

The examples directory contains all chuck examples from the chuck repo, and some additional folders: chugins containing chugin binaries, fauck, containing faust.chug examples, faust, containing the faust stdlib, fluidsynth, containing fluidsynth examples and soundfonts, max, containing chuck files which are used by the max patchers, and test, chuck files used by max patcher test files.

In the patchers section, there are quite a few patchers demonstrating one feature or other in the tests folder, and the contrib folder contains excellents advanced examples of uses by chuck-max contributors.

Contributing

We welcome contributions! Please:

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Submit a pull request

Used in chuck-max:

  • ChuGins: Repository for Officially Supported ChuGins
  • ChuMP: The ChucK Manager of Packages.
  • Chai: ChucK for AI.
  • FaucK: Hybridizing the Faust and ChucK Audio Programming Languages.

Our sibling project:

Other ChucK projects:

  • ChuGL: ChucK Graphics Library.
  • WebChuck for Web-based computer music programming with ChucK.
  • ChucKDesigner: ChucK audio integration with TouchDesigner.
  • SMucK: Symbolic Music in ChucK.
  • Chunity: ChucK for Unity.
  • Chunreal: ChucK in Unreal Engine.

Future Integrations

  • With chump, the chuck package manager: most likely this will take the form of a separate external included in the chuck-max package.

  • With chugl, the chuck graphics library if possible. A chugl branch which successfully builds chugl on both macos and windows, but chugl is still reliant on being run from the executable so does not yet work on Max (but does not crash it either).

Credits

This project thanks the following:

  • Professors GE Wang and Perry Cook and all chuck and chuggin contributors for creating the amazing ChucK language and chugin ecosystem!

  • Professor Perry Cook for co-authoring Chuck and creating the Synthesis Toolkit which is integrated with chuck.

  • Professor Brad Garton for creating the original chuck~ external for Max 5. My failure to build it and run it on Max 8 motivated me to start this project.

  • David Braun, the author of the very cool and excellent DawDreamer project, for creating the excellent ChucKDesigner project which embeds chuck in a Touch Designer plugin. His project provided a super-clear blueprint on how to embed libchuck in another host or plugin system and was essential to this project.

Footnotes

  1. It is also possible to build chuck-max and some of the advanced chugins on MacOS using alternative methods. These are outlined in the alternative-build-guide).

  2. There is experimental support for building chump via make chump. See the chump-build-guide for further details about install requirements.