Alles
A many speaker distributed music synthesizer using UDP multicast over WiFi
Install / Use
/learn @shorepine/AllesREADME
Alles - the mesh synthesizer

Chat about Alles on our Discord!
Check out this video!
Alles is a many-speaker distributed mesh synthesizer that responds over WiFi. Each synth -- there can be hundreds in a mesh -- supports up to 120 additive oscillators, with filters, modulation / LFOs and ADSRs per oscillator. The mesh of speakers can be composed of any combination of our custom hardware speakers or programs running on computers. The software and hardware are open source: you can build it yourself or buy a PCB from us.
The synthesizers automatically form a mesh and listen to multicast WiFi messages. You can control the mesh from a host computer using any programming language or environments like Max or Pd.
We intended their first use as distributed / spatial version of an Alles Machine / Atari AMY additive synthesizer where each speaker represents up to 64 partials, all controlled as a group or individually. But you can just treat them as dozens of individual synthesizers and do whatever you want with them. It's pretty fun!
Want to try it today? Build your own Alles, or install the software version, and then read our getting started tutorial!
Synthesizer specs
Each individual synth is powered by the AMY synthesizer library, you can read more details there.
Using it -- hardware Alles
On first boot, each hardware speaker will create a captive wifi network called alles-synth-X where X is some ID of the synth. Join it (preferably on a mobile device), and you should get redirected to a captive wifi setup page. If not, go to http://10.10.0.1 in your browser after joining the network. Once you tell each synth what the wifi SSID and password you want it to join are, it will reboot. You only need to do that once per synth.
Using it -- software Alles
If you don't want to build or buy an Alles speaker, you can run Alles locally on your computer(s), as many as you want. As long as each copy of the software is running within the same network, they will automatically form in the mesh just like the hardware speakers. And the hardware and software speakers can be used interchangeably.
To build and run alles on a computer, simply clone this repository and
$ cd alles/main
$ make
$ ./alles
$ ./alles -h # shows all the useful commandline parameters, like changing which channel/sound card, or source IP address
Controlling the mesh
Check out our brand new Getting Started page for a tutorial!
You can control every synth on the mesh from a single host, using UDP over WiFi. You can address any synth in the mesh or all of them at once with one message, or use groups. This method can be used in music environments like Max or Pd, or by musicians or developers using languages like Python, or for plug-in developers who want to bridge Alles's full features to DAWs.
Alles's wire protocol is a series of numbers delimited by ascii characters that define all possible parameters of an oscillator. This is a design decision intended to make using Alles from any sort of environment as easy as possible, with no data structure or parsing overhead on the client. It's also readable and compact, far more expressive than MIDI and can be sent over network links, UARTs, or as arguments to functions or commands.
Alles accepts commands in ASCII, each command separated with a Z (you can group multiple messages in one, to avoid network overhead if that's your transport). Like so:
v0w4f440.0l0.9Z
See AMY's readme for the full list of synth parameters.
alles.py
Alles comes with its own full-featured client, written in Python. Feel free to adapt it or use it in your own clients. It can be seen as documentation, an API as well as a testing suite. You simply import alles and can control the entire mesh.
$ python3
>>> import alles
>>> alles.drums() # plays a drum pattern on all synths
>>> alles.drums(client=2) # just on one
To see more examples, check out our brand new Getting Started page.
Addressing individual synthesizers
By default, a message is played by all booted synthesizers. But you can address them individually or in groups using the client parameter.
The synthesizers form a mesh that self-identify who is running. They get auto-addressed client_ids starting at 0 through 255. The first synth to be booted in the mesh gets 0, then 1, and so on. If a synth is shut off or otherwise no longer sends a heartbeat signal to the mesh, the client_ids will reform so that they are always contiguous. A synth may take 10-20 seconds to join the mesh and get assigned a client_id after booting, but it will immediately receive messages sent to all synths.
The client parameter wraps around given the number of booted synthesizers to make it easy on the composer. If you have 6 booted synths, a client of 0 only reaches the first synth, 1 only reaches the 2nd synth, and a client of 7 reaches the 2nd synth (7 % 6 = 1).
Setting client to a number greater than 255 allows you to address groups. For example, a client of 257 performs the following check on each booted synthesizer: my_client_id % (client-255) == 0. This would only address every other synthesizer. A client of 259 would address every fourth synthesizer, and so on.
You can read the heartbeat messages on your host if you want to enumerate the synthesizers locally, see sync below.
Timing & latency
Alles is not designed as a low latency real-time performance instrument, where your actions have an immediate effect on the sound. Changes you make on the host will take a fixed latency -- currently set at 1000ms by default -- to get to every synth. This fixed latency ensures that messages arrive to every synth -- both ESP32 based and those running on computers -- in the mesh in time to play in perfect sync, even though Wi-Fi's transmission latency varies widely. This allows you to have millisecond-accurate timing in your performance across dozens of speakers in a large space.
Your host should send along the time parameter of the relative time when you expect the sound to play. I'd suggest using the number of milliseconds since your host started, e.g. in Python:
def millis():
d = datetime.datetime.now()
return int((datetime.datetime.utcnow() - datetime.datetime(d.year, d.month, d.day)).total_seconds()*1000)
If you're using alles.py, we do this for you!
If using Max, use the cpuclock object as the time parameter.
The first time you send a message with time the synth mesh uses it to figure out the delta between its time and your expected time. (If you never send a time parameter, you're at the mercy of WiFi jitter.) Further messages will be millisecond accurate message-to-message, but with the fixed latency. You can adapt time per client if you want to account for speed-of-sound delay.
The time parameter is not meant to schedule things far in the future on the clients. If you send a new time that is outside 20,000ms from its expected delta, the clock base will re-compute. Your host should be the main "sequencer" and keep track of performance state and future events.
Latency is adjustable, if you are comfortable with your network you can set it lower, or if using a local (127.0.0.1) connection, or directly sending messages in code, you can set it to 0.
Enumerating synths
The sync command (see alles.sync()) triggers an immediate response back from each on-line synthesizer. The response looks like _s65201i4c248y2, where s is the time on the client, i is the index it is responding to, y has battery status (for versions that support that) and c is the client id. This lets you build a map of not only each booted synthesizer, but if you send many messages with different indexes, will also let you figure the round-trip latency for each one along with the reliability.
WiFi & reliability for performances
UDP multicast is naturally 'lossy' -- there is no guarantee that a message will be received by a synth. Depending on a lot of factors, but most especially your wireless router and the presence of other devices, that reliability can sometimes go as low as 70%. For performance purposes, I highly suggest using a dedicated wireless router instead of an existing WiFi network. You'll want to be able to turn off many "quality of service" features (these prioritize a randomly chosen synth and will make sync hard to work with), and you'll want to in the best case only have synthesizers as direct WiFi clients. An easy way to do this is to set up a dedicated wireless router but not wire any internet into it. Connect your laptop or host machine to the router over a wired connection (via a USB-ethernet adapter if you need one), but keep your laptop's wifi or other internet network active. In your controlling software, you simply set the source network address to send and receive multicast packets from. alles_util.py has setup code for this. This will keep your host machi
Related Skills
node-connect
337.3kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
83.2kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
337.3kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
commit-push-pr
83.2kCommit, push, and open a PR

