Skip to main content

m4l-builder

PyPI version Tests Python 3.9+ License: MIT

Build Max for Live devices in Python. Write scripts, emit .amxd files straight to your Ableton User Library. No Max GUI required. Everything is version-controllable, scriptable, and reproducible. Zero runtime dependencies -- pure stdlib.

Install

pip install m4l-builder

Quick start

from m4l_builder import AudioEffect, WARM, device_output_path

device = AudioEffect("My Gain", width=150, height=110, theme=WARM)

device.add_panel("bg", [0, 0, 150, 110])
device.add_dial("gain", "Gain", [10, 6, 50, 90],
                min_val=-70.0, max_val=6.0, initial=0.0,
                unitstyle=4, annotation_name="Gain")

device.add_newobj("mul_l", "*~ 1.", numinlets=2, numoutlets=1, outlettype=["signal"])
device.add_newobj("mul_r", "*~ 1.", numinlets=2, numoutlets=1, outlettype=["signal"])
device.add_newobj("db2a", "dbtoa", numinlets=1, numoutlets=1, outlettype=[""])
device.add_newobj("pk", "pack f 20", numinlets=2, numoutlets=1, outlettype=[""])
device.add_newobj("ln", "line~", numinlets=2, numoutlets=2, outlettype=["signal", "bang"])

device.add_line("obj-plugin", 0, "mul_l", 0)   # stereo in
device.add_line("obj-plugin", 1, "mul_r", 0)
device.add_line("mul_l", 0, "obj-plugout", 0)   # stereo out
device.add_line("mul_r", 0, "obj-plugout", 1)
device.add_line("gain", 0, "db2a", 0)           # dial -> dbtoa -> smooth -> gain
device.add_line("db2a", 0, "pk", 0)
device.add_line("pk", 0, "ln", 0)
device.add_line("ln", 0, "mul_l", 1)
device.add_line("ln", 0, "mul_r", 1)

device.build(device_output_path("My Gain"))

Restart Ableton (or refresh the browser) and your device shows up in the User Library.

Key concepts

Device types

Three device types, matching what Ableton expects:

from m4l_builder import AudioEffect, Instrument, MidiEffect

fx    = AudioEffect("FX", 300, 170)      # auto-adds plugin~/plugout~
synth = Instrument("Synth", 400, 200)    # no auto I/O
midi  = MidiEffect("MIDI FX", 200, 100)  # MIDI only

AudioEffect auto-wires stereo plugin~ / plugout~ objects (IDs obj-plugin, obj-plugout). Instruments and MIDI effects leave I/O to you.

DSP blocks

All DSP functions return (boxes, lines) tuples. Compose them with add_dsp:

from m4l_builder import gain_stage, highpass_filter

boxes, lines = gain_stage("gain")
device.add_dsp(boxes, lines)

Filters: highpass, lowpass, bandpass, notch, onepole, shelves, tilt EQ, 3-band crossover, peaking EQ, allpass Dynamics: compressor, limiter, envelope follower, gate/expander, sidechain detect, multiband compressor Delay/Reverb: delay line, feedback delay, reverb network, FDN reverb, convolver Modulation: LFO (4 waveforms), tremolo, transport LFO, morphing LFO MIDI: notein/out, ctlin/out, velocity curve, transpose, arpeggiator, chord, pitch quantize, midi learn Synthesis: wavetable osc, noise, oscillator bank, ADSR, poly voices, grain cloud Spectral: spectral gate, crossover, vocoder, phase vocoder Routing: selector, send/receive (signal + message), matrix mixer, sidechain routing Utility: param smooth, tempo sync, sample and hold, bitcrusher, coll/dict/pattr storage

90+ blocks total. See docs/api.md for the full list with signatures.

Engines (jsui visualizations)

JavaScript generators for Max's jsui object. Each returns an ES5 string for mgraphics/Cairo rendering:

from m4l_builder.engines import filter_curve_js

device.add_jsui("display", [10, 30, 200, 80],
                js_code=filter_curve_js(), numinlets=3)

18 generators available: filter curves, EQ, envelopes, spectrum, waveforms, XY pad, piano roll, step grids, grain clouds, vocoder bands, and more.

Themes

Seven built-in color themes. Pass to the device constructor and all UI elements inherit colors automatically:

from m4l_builder import AudioEffect, MIDNIGHT, WARM, COOL, LIGHT, FOREST, VIOLET, SOLAR

device = AudioEffect("FX", 300, 170, theme=MIDNIGHT)

Build a theme from just an accent color:

from m4l_builder import Theme
my_theme = Theme.from_accent([0.8, 0.3, 0.1, 1.0])

Recipes

Pre-wired DSP combos for common patterns. They add objects to a device and return IDs for further wiring:

from m4l_builder import gain_controlled_stage, dry_wet_stage

ids = gain_controlled_stage(device, "out", [10, 10, 50, 70])
# ids["gain"] is the *~ you wire into your signal chain

Available: gain_controlled_stage, dry_wet_stage, tempo_synced_delay, midi_note_gate.

Layout helpers

Automatic positioning with Row, Column, and Grid context managers:

with device.row(10, 10, spacing=8, height=70) as r:
    r.add_dial("d1", "Param1", width=50)
    r.add_dial("d2", "Param2", width=50)
    r.add_dial("d3", "Param3", width=50)

Subpatchers

Nested patchers for organizing signal chains:

from m4l_builder import Subpatcher

sub = Subpatcher("processor")
sub.add_newobj("in", "inlet~", numinlets=1, numoutlets=1)
sub.add_newobj("out", "outlet~", numinlets=1, numoutlets=1)
sub.add_line("in", 0, "out", 0)
device.add_subpatcher(sub, "proc_box", [30, 100, 80, 20])

Round-trip editing with from_amxd

Read an existing .amxd back into a Device, modify it, write it out:

device = AudioEffect.from_amxd("path/to/effect.amxd")
device.add_dial("new_knob", "NewParam", [10, 10, 50, 70])
device.build("path/to/modified.amxd")

Examples

40+ examples in examples/. A few highlights:

File What it builds
simple_gain.py Minimal starter, single gain dial
stereo_delay.py L/R delay with feedback saturation
simple_compressor.py Threshold, ratio, attack/release
parametric_eq.py JSUI custom EQ curve display
poly_synth.py Polyphonic synth with wavetable
midi_arpeggiator.py MIDI arpeggiator
from_amxd_demo.py Round-trip: build, read back, modify
uv run python examples/simple_gain.py           # run one
for f in examples/*.py; do uv run python "$f"; done  # build all

Development

git clone https://github.com/alaarab/m4l-builder.git
cd m4l-builder
uv pip install -e .

# Tests
uv run pytest tests/ -v

# With coverage
uv run pytest tests/ --cov=m4l_builder --cov-report=term-missing

API reference

Full API docs at docs/api.md.

License

MIT

Metadata

Release files for m4l-builder 0.7.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for m4l-builder 0.7.0
File Size Uploaded Provenance
m4l_builder-0.7.0.tar.gz 91.5 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for m4l-builder 0.7.0
File Interpreter ABI Platform
m4l_builder-0.7.0-py3-none-any.whl Python 3 none any Details

Total release size: 197.1 kB

Release files / m4l_builder-0.7.0.tar.gz

Download URL m4l_builder-0.7.0.tar.gz
Size 91.5 kB
Tags Source
SHA-256 checksum
How to use checksums
8a48a52564b1ad72f824492c263d5cff948273eb9d78bab2ba92196b005cd43e
BLAKE2b-256 checksum
How to use checksums
157233248271f84fe1d4bba92102ee3f4734c2672febbcc3ab38b558ffa174c5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.10.7 {"installer":{"name":"uv","version":"0.10.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / m4l_builder-0.7.0-py3-none-any.whl

Download URL m4l_builder-0.7.0-py3-none-any.whl
Size 105.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
17b12258295ffbb60c2709dc7083653c9ef55dbeb1cfb51ee0547b084d03cc26
BLAKE2b-256 checksum
How to use checksums
48a79f2ebf8009916b45c8574e4022d87f0374af68853c9eb6624651d43651f9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.10.7 {"installer":{"name":"uv","version":"0.10.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Security for m4l-builder 0.7.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

0.7.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page