What I've been working on: Tzopilotl

I just made this repo public.

https://lfnoise.github.io/tzpl

I have been developing an audio programming language, DSP compiler, audio engine and GUI app called Tzopilotl (Nahuatl word for “vulture”).

AI disclosure: I have definitely used Claude Code for much of the implementation work on the language. The internals of the virtual machine were begun by me, the synthdef-compiler and the audio engine were completely written by me and functional before passing off additional feature work to Claude. All language design decisions, and feature specifications were by me and in detail.

The language is statically typed, with APL-like auto-mapping of arrays and lists over functions. It has a real time memory allocator and a garbage collector with sub-millisecond pause times and minimum mutator utilization scheduling. It has stackless coroutines, actors, async/await, function overloading, templates, type constraints, existential types, a module system, a foreign function interface, and a C/C++ embedding API.

The synthdef compiler allows you to write signal flow graphs for synth definitions in the language and have them compiled to optimized C++, and then to loadable plug-ins for the audio engine. Supports multi-channel and multi-rate signals. Optimizations include constant folding, common subexpression elimination, expression rewriting, rate hoisting, loop fusion, and SIMD code generation.

The audio engine supports real time graph editing of Tzopilotl plug-ins, with optional crossfading of connections, multiple independent audio rendering threads, sample accurate scheduling of events, polyphonic voice management, built-in safety limiter on master output.

The GUI application supports a text editor, a Jupyter-notebook-like document editor with undo history, and an audio node graph editor. Supports OSC and NATS.

There are the beginnings of a standard library and libraries for music composition and live coding.

It is still early. The system is still in heavy development and still has gaps in the implementation and may have serious bugs, though there is a large suite of test files attempting to cover most every feature.

19 Likes

Spotted this in the audio demos – “one ID, multiple notes” looks even easier than the SC server way!

Nice to see that the idea of JIT-compiled server plugins from sc3d5 finally came around :grin:

hjh

Congrats James, this looks really interesting! Now we can finally defer people who demand a static typed and JIT compiled SC4 to your new project :slight_smile:
Looking at the language it seems to fix almost everything that SC suffers from or lacks (modules, yay!). I am looking most forward to pattern matching and async/await!

I found tzpl/.claude/skills/write-tzpl/SKILL.md at main · lfnoise/tzpl · GitHub one of the most interesting documents to figure out how this language is like, e.g.

and the bitwise operator overloading example.

I’d be really interested in your decisions, influences and motivation around the syntax since. SAPF had a really neat approach which I wasn’t familiar with and I am eager to explore the syntax and quirks of tzpl and I can’t pinpoint its influences, there are definitely some Rust things in it (e.g. Option.Some, Future) but also some stack based / “whitespace operator” approach seems to origin from SAPF?
Also tzpl and sapf do not follow the smalltalk approach of SC: Is this decision driven by performance or did you want to have a new approach on things or did your experience as a programmer/musician lead you to abandon the smalltalk/object based approach?

One thing you could consider this early on: Use LGPL for the any standard library. This creates less friction for composers who want to publish their work through a publisher. At least GPL adds a barrier and complexities within SC which a LGPL allows to de-couple, while preserving the internals through GPL (IIRC OCaml and Mercury follow this pattern?). But your project, your rules, though now would be a time to decide on this before other people start to contribute and it becomes almost impossible to change this.

Additionally I would be really interested in your experience with using AI since you are most likely capable of doing all this by hand as well: For me it seems that writing by hand is plainly “more fun” since you get an excuse to dig into interesting stuff, and you get a sense of accomplishment, which I personally don’t get when I let the AI code, but one is 10x slower, which and you run into frustrations ofc, but frustration tolerance is also a skill to master^^
Additionally I feel that AI introduces feature creep due to its fast pacing - features which took time to shape before AI were motivated by using things over and over and one ran into an obstacle and it was worth the effort to nail this down. But such an obstacle also served IMO as a productive gap for the users since it acts as a limitation people want to work around and allows the person to dig into things. Though I am unsure how “digging into things” and usage will change due to AI in general. Would be really interested on your take on this.

Once again thanks, but as a honest feedback: the logo looks like a crossover of the VROCK radio station logo in GTA and some winamp logo in a “fire” color palette :wink:

Cool!

Are you bdfl’ing this?

I liked SAPF’s left to right style. I also borrowed the Io programming language’s getting rid of the dot ‘.’ in method call syntax. My Pyrite language for MAX was not object oriented, but it did allow you to move the first argument of a function to the left so that f(x, y) can become x.f(y). Getting rid of the dot, it becomes x f(y). Auto-mapping comes originally from APL, but the @ operator that I am using, also in SAPF, comes from the Fscript language and a paper on it.

Rust gets a lot of its ideas from OCaml. I also borrowed from OCaml and Rust, and also Swift, Python, Haskell, F#, SAPF, SuperCollider, and others.

I have moved away from object orientation because I think I can get more expressiveness and performance, in less space from a statically typed language. OO dispatch is a pervasive tax on both performance, runtime safety. Dynamic types cost space in every object. Tzopilotl is faster than the Lua and LuaJIT(with the JIT turned off) interpreters. These are among the fastest interpreted languages. Having static types also solves some problems with the auto-mapping feature that SAPF had.

My problem with doing things by hand is that I have a lot of lot of ideas and not so much time. The AI can do in an evening what could have taken months. If you find it not suitable you can throw it away without much loss. But if you would have to spend weeks developing something it and you’re not sure it will be the right thing, then you may not do it, and will not be able to get the experience of learning what the realization of that development could teach you.

I changed the logo.

4 Likes

Hi Denis,

great discussion! Would you mind to elaborate a bit on your following
statement? Why would LPGL make it easier to publish compositions?

One thing you could consider this early on: Use LGPL for the any standard library. This creates less friction for composers who want to publish their work through a publisher. At least GPL adds a barrier and complexities within SC which a LGPL allows to de-couple, while preserving the internals through GPL (IIRC OCaml and Mercury follow this pattern?).

Thanks!
P

Hi, this is great, I have been for wishing static types in SuperCollider, because I am used to them from other languages and they make programing easier once a codebase gets a bit bigger. From glancing the documentation it seems there is everything I need to do the kind of livecoding I like doing in SC, plus a bunch of other stuff which looks very interesting.
I am using linux however, I tried building on Debian 13, but the last cmake command stopped with errors. I opened an issue on github: Building from source on debian 13 failed · Issue #11 · lfnoise/tzpl · GitHub
It would be great to try Tzopilotl, if you have some time please take a look at the errors and let me know if I did something wrong or if I can provide more info.

Cheers

My understanding is that it’s Mac-only for now, with Linux and Windows support to come at a later time.

hjh

There is a section with instruction on how to build from source on Ubuntu in the documentation: Getting Started — Tzopilotl

This should be fixed now, but please follow up if you have other failures.

1 Like

Thank you very much, will try again next week.

any macOS users hitting this ? and have advice

load err=[siloLoad: compile error]

have done the xcode-select --install

using form the app and synthdefs work just fine

just compiled on fedora linux, thanks for sharing! I had to add include directives for INT_MAX and usleep(), everything else appears to work fine.

Post an issue on Github, and be specific about what you are doing that causes this.

1 Like