Monorepo for Aesthetic.Computer
aesthetic.computer
🎸 Pedal: Audio Effect Plugin for Ableton Live#
Overview#
Create an audio effect (filter-style) M4L device where audio passes IN from Ableton's signal chain, gets processed in an AC piece, and passes OUT back to Ableton.
Key difference from existing devices: Current AC M4L devices (notepat, metronome, prompt) only output audio FROM the web page TO Ableton. This is an effect that processes incoming audio.
Technical Challenge#
The jweb~ Limitation#
Per Cycling74 documentation:
- jweb~ has signal outlets only (audio OUTPUT from web page)
- There are no signal inlets (no direct audio INPUT to web page)
- The
signalmessage mentioned in docs is for internal use, not audio input
Solution Architecture#
Since jweb~ cannot receive audio signals directly, we need to:
- Capture audio in Max using
plugin~ 2(stereo effect input) - Analyze/sample the audio and send data via messages to jweb~
- Process/visualize in the AC piece (Web Audio)
- Output via jweb~'s signal outlets →
plugout~
Audio Data Flow Options#
Option A: FFT Spectrum Data (Recommended for v1)#
plugin~ 2 → pfft~ → snapshot~ → format → executejavascript window.acPedalFFT(data)
│
└→ [delay for latency compensation] → plugout~ 2
- Send FFT magnitude/phase arrays to web page
- Web page visualizes and/or generates new audio based on spectrum
- Original audio passes through with optional delay
- Best for: Visualizers, spectrum-driven synths, reactive effects
Option B: Sample-by-Sample (High latency, limited use)#
plugin~ 2 → snapshot~ @samps 128 → pack → executejavascript window.acPedalSamples(L, R)
- Send raw sample values to web page
- Very high message overhead, significant latency
- Not recommended for real-time effects
Option C: Peak/RMS Envelope (Simple, low latency)#
plugin~ 2 → peakamp~ → snapshot~ → executejavascript window.acPedalEnvelope(peak)
- Send envelope followers (peak, RMS, etc.)
- Web audio generates sounds based on amplitude
- Best for: Envelope followers, ducking, gates
Option D: Hybrid (Audio thru + Web effects)#
plugin~ 2 ────┬────────────────────────────────────→ *~ [dry] ─┐
│ │
└→ analysis → jweb~ → [web audio] →──────────→ +~ → plugout~
│
[web-generated audio only, wet]
- Original audio passes through (dry)
- Web audio adds effects/layers (wet)
- Mix control for dry/wet blend
Recommended Implementation: Option D (Hybrid)#
For the pedal piece, we'll use Option D because:
- Audio passes through at native quality (no degradation)
- Web Audio can add processing, visualization, or triggered sounds
- Dry/wet mix gives flexibility
- Lower latency than sample-by-sample approaches
M4L Device Structure#
Max Patcher Architecture#
┌─────────────────────────────────────────────────────────────────┐
│ AC Pedal Effect │
├─────────────────────────────────────────────────────────────────┤
│ │
│ plugin~ 2 │
│ │ └────────────────────────────────────────┐ │
│ │ │ │
│ ▼ ▼ │
│ ┌──────┐ ┌──────────────────────┐ ┌─────────┐ │
│ │ FFT │──▶│ fft analysis js │──▶ │ *~ dry │ │
│ │pfft~ │ │ send to jweb │ │ level │ │
│ └──────┘ └──────────────────────┘ └────┬────┘ │
│ │ │
│ ┌────────────────────────────────────────────────┐│ │
│ │ jweb~ ││ │
│ │ ┌────────────────────────────────────────┐ ││ │
│ │ │ aesthetic.computer/pedal?daw=1 │ ││ │
│ │ │ [signal out L] [signal out R] [msgs] │ ││ │
│ │ └───────┬────────────┬───────────────────┘ ││ │
│ └──────────┼────────────┼───────────────────────┘│ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────┐ ┌─────────┐ ┌──┴──┐ │
│ │ *~ wet │ │ *~ wet │ │ +~ │ │
│ │ level │ │ level │ └──┬──┘ │
│ └────┬────┘ └────┬────┘ │ │
│ └─────────┬──┘ │ │
│ ▼ ▼ │
│ ┌──┴──┐ ┌──┴──┐ │
│ │ +~ ├───────────────────│ +~ │ │
│ └──┬──┘ └──┬──┘ │
│ │ │ │
│ ▼ ▼ │
│ plugout~ 2 │
│ │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ Controls: │ │
│ │ [live.dial dry/wet] [live.dial wet_vol] [live.dial drive] │ │
│ └────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
Key M4L Objects#
| Object | Purpose |
|---|---|
plugin~ 2 |
Receive stereo audio from Ableton |
pfft~ |
FFT analysis of input |
peakamp~ |
Amplitude envelope |
jweb~ |
Web view with audio output |
*~ |
Level/gain control |
+~ |
Mix signals |
plugout~ |
Send stereo audio back to Ableton |
live.dial |
Automatable parameters |
JavaScript Functions (window.*)#
// Called from Max with FFT data (32-128 bins typically)
window.acPedalFFT = function(magnitudes) {
// magnitudes: array of FFT bin magnitudes [0-1]
// Used for visualization and audio-reactive effects
};
// Called from Max with amplitude envelope
window.acPedalEnvelope = function(peakL, peakR, rmsL, rmsR) {
// Used for envelope-following effects
};
// Called from Max with tempo/transport (inherited from base)
window.acDawTempo = function(bpm) { ... };
window.acDawTransport = function(playing) { ... };
Web Audio Processing in pedal.mjs#
Piece Structure#
// pedal.mjs - Audio Effect Pedal for Ableton Live
let fftData = [];
let envelope = { peakL: 0, peakR: 0, rmsL: 0, rmsR: 0 };
let wetLevel = 0.5;
let drive = 1.0;
function boot({ sound, query }) {
// DAW mode detection
const dawMode = query?.daw === "1";
// Set up Web Audio processing chain
// (triggered by envelope/FFT data, outputs via jweb~)
}
function sim({ sound }) {
// Update envelope followers
// Trigger sounds based on input analysis
}
function paint({ wipe, ink, screen }) {
// Visualize FFT spectrum
// Show input level meters
// Display effect status
}
// Exported for M4L window.acPedal* functions
export function setFFT(data) { fftData = data; }
export function setEnvelope(pL, pR, rL, rR) {
envelope = { peakL: pL, peakR: pR, rmsL: rL, rmsR: rR };
}
Effect Ideas for pedal.mjs#
- Visualizer Only - Display input spectrum, pass audio through
- Envelope Follower - Trigger synth notes based on input amplitude
- Spectral Freeze - Analyze and hold FFT, generate frozen drone
- Vocoder-style - Use input spectrum to modulate synth output
- Transient Detector - Trigger drum hits on input transients
Implementation Steps#
Phase 1: Basic Effect Shell ✅ COMPLETE#
- ✅ Create
pedal.mjspiece with FFT visualization - ✅ Add
pedaldevice todevices.jsonwith"type": "effect" - ✅ Extend
build.pywith newgenerate_effect_patcher()function - ✅ Build AMXD with audio input/output chain
Phase 2: Analysis Pipeline (NEXT)#
- Add FFT analysis in Max (
pfft~→js→jweb~) - Add envelope followers (
peakamp~→snapshot~→jweb~) - Wire up
window.acPedal*functions
Phase 3: Audio Generation#
- Web Audio synth triggered by envelope
- Dry/wet mix controls
- Parameter automation
How to Test#
1. Start the local dev server#
npm run site # or npm run aesthetic
2. Build and install the pedal device#
cd ac-m4l
python3 build.py pedal --install
3. In Ableton Live#
- Find "AC 🎸 pedal" in the Audio Effects section of the browser
- Drag it onto an audio track with audio playing
- Observe the FFT visualization responding to input audio
- The dry signal passes through; the wet signal (from jweb~) is mixed in
4. Test controls#
- Tap/Space: Cycle effect modes (visualizer → envelope-synth → freeze → gate)
- Up/Down arrows: Adjust trigger threshold (for envelope-synth mode)
Files Created/Modified#
| File | Action | Description |
|---|---|---|
system/public/aesthetic.computer/disks/pedal.mjs |
✅ CREATED | AC piece for effect |
ac-m4l/devices.json |
✅ MODIFIED | Added pedal device config with "type": "effect" |
ac-m4l/build.py |
✅ MODIFIED | Added generate_effect_patcher() function |
ac-m4l/AC 🎸 pedal (localhost:8888).amxd |
✅ BUILT | Generated effect device |
ac-m4l/ac-fft-analyzer.js |
🔜 FUTURE | Max JS for FFT → jweb |
plans/pedal.md |
✅ CREATED | This planning document |
References#
- jweb~ documentation
- pfft~ documentation
- M4L Audio Effect Guidelines
- Existing AC M4L integration:
ac-m4l/build.py,ac-m4l/ABLETON-INTEGRATION-PROGRESS.md
Open Questions#
- Latency compensation: How much latency does jweb~ add? Need to delay dry signal to match.
- Sample rate matching: Browser AudioContext vs. Ableton - handled by existing
acDawSamplerate - FFT bin count: 32? 64? 128? Balance between detail and message overhead
- Message rate: How often to send FFT data? Every vector? Every N ms?
Testing Checklist#
- Audio passes through when loaded (dry signal)
- FFT visualization updates with input audio
- Wet signal (from web audio) mixes correctly
- Dry/wet control works
- No clicks/pops on parameter changes
- Works at 44.1kHz and 48kHz sample rates
- Multiple instances work simultaneously