Syntə RSS repo @m 🎶 say hi!
back

26/02/2025

Rethinking Syntə Syntax

Ok, the title is a bit misleading. As it turns out, we can use the existing features of the language to extend it and with some simple steps that get us quite far.

One thing that has always struck me about the TidalCycles/Strudel ecosystem is the immediacy of the code. With not much at all you can get going quickly, making at least something happen. Which is great. Does Syntə have that same immediacy? Let’s find out!

First

First1, let’s start by saying that the goals of Syntə are distinct from TidalCyles & friends - we do not aim to emulate nor reproduce those languages.
For the sake of simplicity we’ll focus on Strudel alone. From an outside perspective I’d say that immediacy, accessibility (portability) and collaboration are the big successes of that project. Whereas in Syntə nothing really at all has been done on those fronts. That’s partly because other goals have taken precedence, such as performance (in the sense of both how much you can do with it at any one time, and also performing in front of an audience). But I would say the real differences lie in the deeper structure of how programs are written, both syntactically and in terms of what the language provides out-of-the box.

In Strudel you can start straight away with notes, chords, and scales - which is very gratifying. Whereas Syntə provides no such niceties and has no concept of a sequence, note or even envelope. Strange, huh?
What it does provide is access to the most simple building blocks that make everything else. Which may seem very noble, but isn’t much good in an adrenaline fuelled stage environment.

Recently,

I’ve been thinking about how to make the language more immediate. Mainly for the selfish purpose of making life much easier for me when performing and my brain has effectively melted under pressure :)
Well, I should stop doing that, but could we help out by easing the process of writing code?

Using Strudel as a reference point

A really simple Strudel pattern is:

$: s("bd sn")

What would that look like in Syntə?

/b 1,0 lt 0.5 bd out m /b 1,0.5 lt 0.5 sn + m mix

Well, that looks quite verbose in comparison and a lot less friendly. But there is some low hanging fruit here.
(side note: you can place commas to differentiate the operator/operand pairs, but that’s not essential)
The repeated lt 0.5 doesn’t seem to be doing much. The 0.5 in particular is fairly arbitrary, and neither convey much functional information. We can define a function to wrap this away:

[ /s, /b @,@1, lt 0.5, ]

(commas included this time, note - function arguments always require commas but no spaces)

Do we need to stop there?

No. We don’t need to include both sounds in a single listing, so we can also skip the need to sum (add) them together. Our code now looks like this:

/s 1,0 bd mix
/s 1,0.5 sn mix

That’s much better. And now the samples are automatically mixed separately, resulting in a better balance. The mix now stands out a bit, anything we can do about that? Let’s define another function that is really just an alias:

[ ; mix ]

Now we have:

/s 1,0 bd ;
/s 1,0.5 sn ;

I’m not sure how pretty that looks, but it’s succinct and will be familiar to those who come from C-like languages (which are many). Although, it kinda disguises what mix is doing - setting the level before sending to output to be combined with other listings - which could be misleading. And also one has to remember the space in between the previous operation and the semicolon, something that is not a feature in any language that I know of.

Cheating

We’ve actually cheated a bit here, because the above listings rely on there being a time-base phasor already extant.
Namely,

in 120/4bpm osc .out sync

But no problem, we could wrap as: [ cpm, in @ / 4 osc .out sync ] in a cheeky nod to Strudel. Thus we can precede our listings once with cpm 120bpm.

Movin’ on

Let’s move onto something a bit less trivial. From the Strudel docs here’s a simple house beat:

s("bd*4, [~ sn]*2, [~ hh*4]")

After the steps above, now in Syntə we have:

/s 4,0 bd 1 ;
/s 2,0.5 sn 35ms ;
/s 4,0.5 hh 35ms ;

Oh yes, I forgot - more misinformation! The above examples won’t work because bd, sn and hh require an argument (I added that for a bit of flexibility when I made those functions.) And bear in mind that the innards of them may change over time if I rip them out and replace to create a fresh toolkit. In fact, a lot of the language could change under your feet, although to be fair it’s been very stable to date.
I’ve added the arguments in the above example, apols for any confusion.

We can go further and add a bit of movement to the hi-hat like so:

/b 1,0.75 lt 1/4 range 35ms,350ms out t
/s 4,0.5 hh t ;

For those who are unfamiliar - which is like basically everyone on the planet 🤭 - we should say a quick bit about functions. Everything in Syntə is a series of operations, but some things are functions. Like osc for example. This means it is a series of operations wrapped up and given a name. Functions can have up to three arguments (parameters). They are made by typing [ name-of-new-function, ... some operators here... use the @ to show where the first argument will be used ... @1 etc ]. For illustration, here is how you would define osc:
[ osc, out ^freq, + a, mod 1, out a] - but don’t worry too much about what that all means, it’s not necessary to know 😊

Instructive

So that has been instructive. We’ve not changed the language at all (except by extending it) and have retained everything that makes it unique. We’ve kept the ‘de-colonised’ nature of not relying on any western2 preconceptions of what pitch, note or harmony are. (Not that any of those are particularly relevant to the examples above.)
But by using Strudel as a reference point it’s made it easier to reason about what simplicity is and what we can do about it. A nice combination of flattery and schismogenesis, if you like :)

This is only the start of the journey, but we’ve made good progress in just a couple of simple steps. Yay.

What’s next?

One thing I’ve been meaning to do3 for a while is change the /b function to accept an input directly from the necklace. What does that mean? Well, currently /b starts with in @ which means it ignores what is passed down the chain of operations. This is because it’s usually written at the beginning of a listing anyway and saves having to type eg. in 3 before it.
We could add an alternative which does accept input, making things simpler for modulating the ‘divide down’ parameter (first argument) - something like:

/b 1,0.5 lt 0.25 range 4,8 /m 0 bd 1 ;

Other things to consider include: could we use braces and parenthesis’ to change the order of operations and improve readability?

Tune in another time to find out…


Addendum

What have we done here? Did we really need to think about another language?
What we’ve done is: cast across to something from another person’s head. That helps us take us out of our own heads. We haven’t needed to copy, and tbh I’m not very impressed with the beat we made. But we’ve made some small and important steps to make live coding easier.

We could have equally tried an étude (a term I learnt recently from trampbunny) or something else. Anything to freshen up our state of mind and gain a new perspective 🙂


  1. I’ve found that tode has been quite influential on my blog writing style, seen here in the repetition of ‘first’. A big one is the use of horizontal rules to break up text, seen above this very footnote ↩︎

  2. There is a really interesting discussion of how the notion of ‘western’ is oppositional (defined in relation to something else - an ’east’ - and may even derive from the days of the dominant Byzantine (Eastern Roman) empire) in this podcast here: Byzantium & friends (which, incidentally, has a great intro theme.) Unfortunately I can’t find which episode, but it’s one of the more recent ones. ↩︎

  3. Bear in mind that any or all of these additional functions may or may not be pushed to the repo for a while. But that doesn’t prevent you from implementing them yourself 😀 ↩︎


 updated on: 2 / 3 / 2025

↑ top