Comparing Strudel and Tidal
This page is dedicated to exisiting tidal users, giving an overview of all the differences between Strudel and Tidal.
Language
Strudel is written in JavaScript, while Tidal is written in Haskell.
Example
This difference is most obvious when looking at the syntax:
iter 4 $ every 3 (||+ n "10 20") $ (n "0 1 3") # s "triangle" # crush 4
One could express that pattern to Strudel like so:
iter(4, every(3, add.squeeze("10 20"), n("0 1 3").s("triangle").crush(4)))
- The
$
operator does not exist, so theiter
function has to wrap everything in parens. - Custom operators like
||+
are explicit function calls,add.squeeze
in this case - The
#
operator is replaced with a chained function call# crush 4
=>.crush(4)
Unlike Haskell, JavaScript lacks the ability to define custom infix operators, or change the meaning of existing ones.
Before you discard Strudel as an unwieldy paren monster, look at this alternative way to write the above:
n("0 1 3").every(3, add.squeeze("10 20")).iter(4).s("triangle").crush(4)
By reordering calls, the parens are much less nested.
As a general rule by thumb, you could say that everything Tidal does with $
is reversed in Strudel:
iter 4 $ every 3 (||+ n "10 20") $ (n "0 1 3")
becomes
n("0 1 3").every(3, add.squeeze("10 20")).iter(4)
Simply put, foo x $ bar x
becomes bar(x).foo(x)
.
Operators
The custom operators of tidal are normal functions in strudel:
function | tidal | strudel |
---|---|---|
add | |+ n | .add(n) |
subtract | |- n | .sub(n) |
multiply | |* n | .mul(n) |
divide | |/ n | .div(n) |
modulo | |% n | .mod(n) |
left values | |< n | .set(n) |
The above list only displays the operators taking the structure comes from the left
.
For each of those, a right
and both
variant also exists.
As this directional thinking only works with code, strudel calls these in
/ out
/ mix
:
direction | tidal | strudel |
---|---|---|
left | |+ n | .add.in(n) |
right | +| n | .add.out(n) |
both | |+| n | .add.mix(n) |
Instead of +
/ add
, you can use any of the available operators of the first list.
Function Compatibility
This issue tracks which Tidal functions are implemented in Strudel. The list might not be 100% up to date and probably also misses some functions completely.. Feel encouraged to search the source code for a function you’re looking for. If you find a function that’s not on the list, please tell!
Control Params
As seen in the example, the #
operator (shorthand for |>
) is also just a function call in strudel.
So note "c5" # s "gtr"
becomes note("c5").s('gtr')
.
This file lists all available control params. Note that not all of those work in the Webaudio Output of Strudel. If you find a tidal control that’s not on the list, please tell!
Sound
Tidal is commonly paired with Superdirt / Supercollider for sound generation. While Strudel also has a way of communicating with Superdirt, it aims to provide a standalone live coding environment that runs entirely in the browser.
Audio Effects
Many of SuperDirt’s effects have been reimplemented in Strudel, using the Web Audio API. You can find a list of available effects here.
Sampler
Strudel’s sampler supports a subset of Superdirt’s sampler. Also, samples are always loaded from a URL rather than from the disk, although that might be possible in the future.
Evaluation
The Strudel REPL does not support block based evaluation yet.
You can use labeled statements and _
to mute:
$: n("[0 .. 8]*8/9").scale("C:minor:pentatonic") _$: s("bd*4").bank('RolandTR909')
Tempo
Strudels tempo is 1 cycle per second, while tidal defaults to 0.5625
.
You can get the same tempo as tidal with:
note("c a f e").fast(.5625);
Next up: the REPL