1--- 2title: 'StrudelCycles: live coding algorithmic patterns on the web' 3date: '2022-03-22' 4url2cite: all-links 5--- 6 7# Introduction 8 9This paper introduces Strudel, an alternative implementation of the TidalCycles live coding system, using the JavaScript programming language. 10 11# Background 12 13TidalCycles (or *Tidal* for short) has been developed since around 2009, as a system for live coding algorithmic patterns, particularly in music [@tidalcycles]. Tidal is embedded in the pure functional *Haskell* programming language, taking advantage of its terse syntax and advanced type system. Over the past decade, Tidal has undergone a number of re-writes, developing a functional reactive representation of pattern, where patterns may be combined and transformed in a wide variety of ways [@alternate-timelines]. Over this time is has gained diverse ideas from other patterned forms, including from computer music [@spiegel], Indian classical music [@bel], textiles [@fabricating], improvised percussion [@hession], and Ancient Greek lyric [@cyclic-patterns]. 14 15Most recently, attention has turned to transferring Tidal's ideas to other, less 'pure' languages; firstly, to the Python programming language as *TidalVortex* [@tidalvortex] (*Vortex* for short), and now to JavaScript as StrudelCycles (*Strudel* for short), the topic of the present paper. For general background on the motivations for porting Tidal to a multi-paradigm programming language, please see the TidalVortex paper [@tidalvortex]. The motivations for porting it to JavaScript are similar, with a particular slanting on accessibility - of course, a web browser based application does not require any installation. As with Vortex though, it is important to point out that this is a creative, free/open source project, and as such, an primary motivation will always be developer's curiosity, and market-driven perspectives on development choices may even be demotivational. 16 17General motivations / related work. 18Reference vortex paper and summarise its background. 19 20The reimplementation of TidalCycles in Python (cite TidalVortex) showed that it is possible to translate pure functional reactive programming ideas to a multi paradigm language. It proved to be a stepping stone to move to other multi-paradigm languages, like JavaScript. A significant part of of the Python codebase could be quickly ported to JavaScript by syntactical adjustments. 21 22# Introducing Strudel 23 24* Motivating musical example 25 26# Tidal patterns 27 28(should we explain shortly what tidal patterns do in general here?) 29 30The essence of TidalCycles are Patterns. Patterns are abstract entities that represent flows of time, supporting both continuous changes (like signals) and discrete events (like notes). 31Taking a time span as its input, a Pattern can output a set of events that happen within that time span. 32It depends on the structure of the Pattern where the events are placed. 33From now on, this process of generating events from a time span will be called **querying**. 34Example: 35 36```js 37const pattern = sequence(c3, [e3, g3]); 38const events = pattern.query(0, 1); 39console.log(events.map(e => e.show())) 40``` 41 42In this example, we create a pattern using the `sequence` function and **query** it for the timespan from `0` to `1`. 43Those numbers represent units of time called **cycles**. The length of one cycle defaults to one second, but could be any number of seconds. 44The console output looks like this: 45 46```js 47(0 -> 1/2 c3) 48(1/2 -> 3/4 e3) 49(3/2 -> 1 g3) 50``` 51 52In this output, each line represents one event. The two fractions represent the begin and end time of the event, followed by its value. 53In this case, the events are placed in sequential order, where c3 takes the first half, and e3 and g3 together take the second half. 54This temporal placement is the result of the `sequence` function, which divides its arguments equally over one cycle. 55If an argument is an array, the same rule applies to that part of the sequence. In our example e3 and g3 are divided equally over the second half of the whole sequence. 56 57# Mini Notation 58 59In this example, the Pattern is created using the `mini` function, which parses Tidal's Mini Notation. 60The Mini Notation is a Domain Specific Language (DSL) that allows expressing rhythms in a short mannger. 61 62* Some comparisons of -Strudel with -Vortex and -Cycles code? 63 64(the following examples are from vortex paper, with added js versions) 65 66## 1 67 68```haskell 69sound "bd ~ [sd cp]" 70``` 71 72```python 73sound("bd", silence, ["sd", "cp"]) 74``` 75 76```javascript 77sound("bd ~ [sd cp]") 78``` 79 80without mini notation: 81 82```haskell 83sound $ cat 84 [pure "bd", silence, 85 cat(pure "sd", pure "cp")] 86``` 87 88```javascript 89sound('bd', silence, cat('sd', 'cp')) 90``` 91 92## 2 93 94```haskell 95sound "bd ~ <sd cp>" 96``` 97 98```python 99sound("bd", silence, slowcat("sd", "cp")) 100``` 101 102```javascript 103sound("bd ~ <sd cp>") 104// sound('bd', silence, slowcat('sd', 'cp')) 105``` 106 107## 3 108 109```haskell 110sound "bd {cp sd, lt mt ht}" 111``` 112 113```python 114sound("bd", pm(["cp", "sd"], ["lt", "mt", "ht"])) 115``` 116 117```js 118? 119``` 120 121## 4 122 123```haskell 124sound "bd {cp sd, [lt mt,bd bd bd] ht}" 125``` 126 127```python 128 sound("bd", pm(["cp", "sd"], 129 [pr(["lt", "mt"], 130 ["bd", "bd", "bd"] 131 ), 132 "ht" ])) 133``` 134 135```js 136?? 137``` 138 139## 5 140 141```haskell 142sound "bd sd cp" # speed "1 2" 143``` 144 145```python 146sound("bd", "sd", "cp") >> speed (1, 2) 147``` 148 149```javascript 150sound("bd sd cp").speed("1 2") 151``` 152 153(operator overloading like in vortex?) 154 155## 6 156 157```haskell 158rev $ sound "bd sd" 159``` 160 161```python 162rev(sound("bd", "sd")) 163sound("bd", "sd").rev() 164``` 165 166```javascript 167rev(sound("bd sd")) 168sound("bd sd").rev() 169``` 170 171## 7 172 173```haskell 174jux rev $ every 3 (fast 2) $ sound "bd sd" 175``` 176 177```python 178jux(rev, every(3, fast(2), sound("bd", "sd"))) 179sound("bd","sd").every(3, fast(2)).jux(rev) 180``` 181 182```js 183jux(rev, every(3, fast(2), sound("bd sd"))) 184sound("bd sd").every(3, fast(2)).jux(rev) 185``` 186 187(partial application) 188 189## 8 190 191```haskell 192n ("1 2 3" + "4 5") # sound "drum" 193``` 194 195```python 196n (sequence(1,2,3) + sequence(4,5)) >> sound "drum" 197``` 198 199```js 200n("1 2 3".add("4 5")).sound("drum") 201n("5 [6 7] 8").sound("drum") 202``` 203 204(operator overloading?) 205 206## 9 207 208```haskell 209speed("1 2 3" + sine) 210``` 211 212```python 213speed(sequence(1,2,3) + sine) 214``` 215 216```js 217speed("1 2 3".add(sine)) 218"c3*4".add(sine.mul(12).slow(8)).pianoroll() 219``` 220 221## 10 222 223* Mininotation 224 225# Strudel/web specifics 226 227Some discussion about whether strudel is really a port of TidalCycles, or whether javascript affordances mean it's going its own way.. 228 229* Recursive Scheduling: "calling itself in the future" 230* Optimizing Syntax for minimal keystrokes / readability: "AST Hacking" via shift-ast 231pseudo variables 232 * Handling mininotation - double quoted and template strings to mini calls 233 * Operator overloading 234* Fixing inconsistencies (e.g. with stut/echo) 235adding source locations 236* Dynamic HUD: Highlighting + drawing 237* Translation of Tidal concepts to Javascript - different constraints, affordances, aesthetics 238* Dynamic Harmonic Programming? 239* emulating musician thought patterns 240* microtonal features? 241webserial 242 243## User Code Transpilation 244 245(compare user input vs shifted output) 246 247### double quotes -> mini calls 248 249```javascript 250"c3 e3" // or `c3 e3` 251``` 252 253```javascript 254mini("c3 e3") 255``` 256 257### operator overloading 258 259```javascript 260cat(c3, e3) * 4 261``` 262 263```javascript 264reify(cat("c3","e3")).fast(4) 265``` 266 267(reify is redundant here, the shapeshifter could have an additional check...) 268 269(TBD: ability to multiply mini notation strings) 270 271### pseudo variables 272 273```javascript 274cat(c3, r, e3) 275``` 276 277```javascript 278cat("c3",silence,"e3") 279``` 280 281### locations 282 283```javascript 284cat(c3, e3) 285``` 286 287```javascript 288cat( 289 reify("c3").withLocation([1,4,4],[1,6,6]), 290 reify("e3").withLocation([1,8,8],[1,10,10]) 291) 292``` 293 294```javascript 295mini("c3 e3") 296``` 297 298with locations: 299 300```javascript 301// "c3 e3" 302mini("c3 e3").withMiniLocation([1,0,0],[1,7,7]) 303``` 304 305(talk about mini adding locations of mini notation parser) 306 307### top level await 308 309```javascript 310const p = (await piano()).toDestination() 311cat(c3).tone(p) 312``` 313 314```javascript 315(async()=>{ 316 const p = (await piano()).toDestination(); 317 return cat("c3").tone(p); 318})() 319``` 320 321# Musical examples 322 323... 324 325# Ongoing work/future aims 326 327* WASM Sound Backend 328* OSC -> Supercollider 329* mininotation as the 'regex' of metre 330 331That @roberts2016 are excellent, I reference their work at least twice per sentence [@roberts2016, p. 3]. 332 333```javascript 334"1 2 3" 335``` 336 337# References 338 339[@roberts2016]: https://www.tandfonline.com/doi/abs/10.1080/14794713.2016.1227602?journalCode=rpdm20 340[@alternate-timelines]: https://zenodo.org/record/5788732 341[@tidal.pegjs]: https://www.semanticscholar.org/paper/Bringing-the-TidalCycles-Mini-Notation-to-the-Roberts/74965efadd572ae3f40d14c633a5c8581c1b9f42 342[@tidalvortex]: https://zenodo.org/record/6456380 343[@ogborn17]: https://www.semanticscholar.org/paper/Estuary%3A-Browser-based-Collaborative-Projectional-Ogborn-Beverley/c6b5d34575d6230dfd8751ca4af8e5f6e44d916b 344[@tidalcycles]: https://dl.acm.org/doi/10.1145/2633638.2633647 345[@hession]: https://www.scopus.com/record/display.uri?eid=2-s2.0-84907386880&origin=inward&txGid=03307e26fba02a27bdc68bda462016f6266316467_Extending_Instruments_with_Live_Algorithms_in_a_Percussion_Code_Duo 346[@spiegel]: https://www.academia.edu/664807/Manipulations_of_musical_patterns 347[@bel]: https://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.517.7129 348[@algorithmicpattern]: https://zenodo.org/record/4299661 349[@fabricating]: https://zenodo.org/record/2155745 350[@cyclic-patterns]: https://zenodo.org/record/1548969 351 352- gibber 353- krill 354- glicol