VoidLinkAudio v0.2.0 — first public Ableton Link Audio implementation for Pd vanilla
Hi all,
I just released VoidLinkAudio v0.2.0, which includes — to my knowledge — the first public implementation of Ableton Link Audio on Pure Data vanilla.
Ableton Link Audio is the audio extension to Ableton Link, shipped with Live 12.4 (publicly released May 5, 2026). It allows audio buffers to be transmitted between Link peers over a local network, beat-synced and sample-accurate, in addition to the tempo/transport sync that Link has provided since 2016.
Demo video showing all hosts in action:
The Pd port consists of two externals:
void.linkaudio.send~ publish 2 audio inlets as a stereo channel
void.linkaudio.receive~ subscribe to a channel; output L/R audio
Both expose Link timing as audio-rate signal outlets (tempo~, phase~,
transport~) and accept tempo/transport messages that propagate to all Link peers (Live, Max, TouchDesigner, VCV Rack, openFrameworks, other Pd instances). Help patches are included.
Builds available for:
- macOS Universal (arm64 + x86_64), notarized
- Windows x64
- Linux: planned for v0.3.0
Important: most peers run at 48 kHz (Live default), so set Pd to 48 kHz
in Media > Audio settings to avoid drops.
Source code (GPL-2.0-or-later):
https://github.com/gluon/Void-LinkAudio
Pre-built binaries on GitHub Releases:
https://github.com/gluon/Void-LinkAudio/releases/tag/v0.2.0
Pay-what-you-want bundle (also free) for all hosts:
https://structurevoid.gumroad.com/l/voidlinkaudio-connectors
The project also covers Max/MSP, TouchDesigner, VCV Rack, and openFrameworks (in a separate repo: gluon/ofxAbletonLinkAudio). A VST3/AU plugin pack is in the works for DAW users.
Happy to answer questions, discuss the implementation, or hear about
any issues.
Best,
Julien Bayle
Structure Void
https://structure-void.com
send values to abstraction inside clone
You can prefix the number of the cloned synth in a message to that synth eg 2 cutoff $1 then within the cloned synth and route the cutoff value and pass it on polyphonically with all cutoff $1
clone-project.zip

send values to abstraction inside clone
Hi.
I have an issue I can`t manage to solve
I created a polyphonic synthesizer.
I have an abstraction for the actual synthesizer, which contains the filter and velocity envelopes.
I then use [clone] to load this abstraction in order to achieve polyphony.
After that, I made the [clone] instance itself into another abstraction, so I can call this polyphonic synthesizer multiple times and assign it to different tracks or step sequencers.
So far, that’s all working — let’s call this abstraction synthclone.
Now I’d like to send values like cutoff, resonance, etc., to one of these synthclone abstractions.
How would I do that?
Because it’s basically an abstraction inside an abstraction, I’m not sure how to send values to each synthclone — which in turn needs to pass these values down to its internal polyphonic synthesizer abstraction.
My solution so far: I created an inlet for the polyphonic synthesizer abstraction, and in my synthclone abstraction, I added inlets which passes values down to the polyphonic synth abstraction.
I think I also have to send the message all $1 to it in order to make it work, but that seems pretty complicated overall. Also I would probably need so many inlets for all the values I want to control, its hard to keep that in order.
I’d rather use send and receive directly in the polyphonic synth abstraction, if that’s possible.
Sorry, to basically make it short, if I create my synthclone abstraction like synthclone 4, I would need to pass the 4 to my synthabstraction inside clone. I am able to pass it to synthclone with $1 but then I can`t get this value inside the clone object
Note overlap when using poly and clone objects
Hello patchers! I have been watching a tutorial series by Really Useful Plugins where they recreate yamaha dx7 synth and repeated after them. Finishing, i ran into a problem related to polyphony.
So, the problem is when i press a note it plays all 8 voices at the same time, when i play other note, it keeps playing previous ones with the current one. This may happen due to ADSR, but i checked everything several times and still cannot solve it. I admit that the solution may be pretty obvious, but i am new to this sorry. I checked manuals and tutorials, but they weren't very useful.
Here is the zip with the patch.
dx7.zip
- Here are poly and clone themselves

- Here is dx7-poly object, which is cloned

- On previous photo the $0-oscmsgs is sent, here is where it is delivered

- ADSR object which is stolen from pd documentation examples

I hope very much for your help! thx
Clone error on every sixth note
@jamcultur You get that error message because [poly]'s first outlet counts from 1 to 6, but clone numbers the cloned abstractions from 0 to 5. To make clone number from 1 to 6, use the -s flag, e.g. [clone -s 1 kbnote 6], or you could just subtract 1 from [poly]'s first outlet.
Start abstraction in Pd sub-process with $n args set?
@oid I never use [set <n>(, but my understanding is that it modifies the state of clone's built-in round-robin allocator (which I'm not using). I'm trying to change how clone assigns the argument $1 inside each abstraction instance that clone has loaded so that I don't have to worry about which subprocess a particular clone is running in. Subprocess 0 will have clones 0-99, subprocess 1 will have clones 100 - 199.... But now (of course) that you've forced me to think about it some more, yes I could just add an offset to the value of $1 in each cloned abstraction, and set that offset with a message from the main process. That's probably clearer than dynamic patching.
Is there a shorter way to make this logic?
Looks like the patch has many duplications. For this [clone] can make sense.
While you have to get used to how to deal with [clone], later it makes changes of the patch much quicker.
With [pdcontrol] you can read the arguments.
Here is an example, where [moses] and [expr] are fed by arguments of clone.
The right outlet of [moses] is sent to the next clone-instance.

withpdcontrol.pd
withpdcontrol-openthis.pd
EDIT
Without [list store], less memory:

wpdcontrol_woliststore.pd UPDATED, fixed two bugs, now it should work
wpdcontrol_woliststore-openthis.pd
Performance of [text] objects
Hey all,
I am integrating a Pd patch with an existing sequencer/looper (Seq192) with an OSC interface, where my patch should convert my MIDI controller's button presses to OSC commands and send back MIDI signal out to lighten the controller's LEDs.
I can retrieve periodically the status and details of all clips/sequences and aggregate it into a list of parameters for each sequence. The LED colors and the actions that the next button press will trigger depend on these parameters, so I need to store them for reuse, which I like doing with [text] objects. I am then handling buttons' light status in a [clone 90] (where each instance of the clone handles one button).
This should be running on a fairly low-end laptop, so I'm wondering which of these approaches is the most CPU-efficient - if there is any significant difference at all - and I couldn't come up with a way to properly measure the performance difference:
- one
[text define $1-seq-status]object in each clone, with one single line in each. I compare the new sequence status input with[text get $1-seq-status 0]so that I update only line 0 with[text set $1-seq-status]when I know that the content has changed. - one single
[text define all-seq-status]object with 91 lines. I compare the new sequence status with
[ <button number> (
|
[text search all-seq-status 0]
|
[sel -1]
|
[text get all-seq-status]
and if it has changed, I update a button's line with
[ <new status content> (
|
| [ <line number> (
| |
[text set all-seq-status]
The order in which buttons/sequence statuses are listed in the file might change, so I can't really avoid searching at least once per button to update.
- Should I instead uses simple lists in each clone instance? As far as I could test, getting a value from a list was a bit slower than getting a value from a text, but searching in a text was much slower than both. But I don't know the impact of processing 91 lists or text at the same time...
TL;DR: Is it more efficient to [text search], [text get] and [text set] 91 times in one [text] object, or to [text get] and [text set] 1 time in each of 91 [text] objects? or in 91 [list] objects?
Since you've gone through this long post and I gave a lot of context, I am of course very open to suggestions to do this in a completely different way :D
Thanks!
Chords (polyphony) as arrays/lists
Your [clone] idea would be the way to go!
@Obineg said in Chords (polyphony) as arrays/lists:
if you code your own external at one point you always have to iterate the list into single values.
And have a look into the help-file of [clone]: Adress clone instances with the first number of a list or with next in a serial manner.
Instead you could send the whole list to all and in each instance cut-out the snipped of interest by getting the instance-# with [f $1] and cut-out with two [list split]s.
Maybe upload your non-working clone-version and we can fix it.
In your hard-coded patch only [mtof] and [phasor~] or only [phasor~] are required to duplicate, - sum all the [phasors~] into one [lop~] ect.
Maybe use [poly], if you like it.
Also, there are many examples of polyphonic synths floating around, in the patch-subforum for example.
Naming Toggles for a Huge 24/24 Patch Matrix
@high_output-5000 I think I've done stuff like this using nested [clone]s, e.g. the inner clones each represent a row for a particular column, and the outer clones represent the columns. The outer clones pass their column identifier to the inner clones. I'm just handwaving due to cocktail hour...let me know if you need more detail and I'll get on it! 

