-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathindex.html
More file actions
1437 lines (1437 loc) · 134 KB
/
index.html
File metadata and controls
1437 lines (1437 loc) · 134 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html>
<html>
<head>
<title>LiMuT</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta charset="UTF-8">
<style>
body {
font-family: helvetica, arial;
background: #202830;
color: #d0d0d0;
text-shadow: -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, 1px 1px 0 #000;
scrollbar-width: thin;
scrollbar-color: #b0b0b080 #50505080;
}
.fullscreen {
position: fixed;
top:0%;
left:0%;
width:100%;
height:100%;
z-index: -1;
}
.fixed-top {
position: sticky;
top: 0;
left: 0;
z-index: 999;
width: 100%;
}
.widget {
color: #ddd;
border: 2px solid #222;
border-radius: 6px;
margin: 2px;
padding: 2px;
font-size: 1.1em;
}
.widget p {
margin: 0px;
}
.widget h3 {
margin: 0px;
}
.code {
height: 400px;
margin-bottom: 8px;
max-width: 100%;
font-size: 1.2em;
}
code {
color: #d0d0ff;
}
textarea {
font-family: courier, mono, monospace;
font-size: 1.5em;
color: #e0e0e0;
width: 100%;
max-width: 100%;
background: transparent;
border-radius: 4px;
border-style: solid;
border-color: #60606080;
text-shadow: -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, 1px 1px 0 #000;
caret-color: #80b0ff;
}
textarea::selection {
background: #4060d0;
color: #000000;
text-shadow: none;
}
textarea#console {
font-size: 1em;
color: #808080;
}
button {
width:1.5em;
height:1.5em;
background: #80808080;
font-size: 1.3em;
border-radius: 4px;
border-style: solid;
border-color: #d0d0d080;
padding: 0;
}
span {
font-weight: bold;
}
span.beat-readout {
padding-left: 24px;
font-weight: normal;
font-family: courier, mono, monospace;
white-space: pre;
}
.info {
width: 100%;
max-width: 100%;
}
.closed {
display: none;
}
pre {
width: 100%;
max-width: 100%;
overflow-x: auto;
}
#accordion-examples pre {
margin: 8px 2px 16px 2px;
padding: 4px;
border: 2px #222 solid;
}
.sub {
margin-top: -10px;
margin-left: 20px;
}
.subsub {
margin-top: -10px;
margin-left: 30px;
}
.meter {
display: inline-block;
width: 1em;
height: 1em;
background-color: #808080;
}
.vu-meter-base {
display: inline-block;
width: 4em;
height: 0.8em;
padding: 2px;
border: 2px #808080 solid;
background: linear-gradient(to right, #040, #440 3em, #400 4em);
}
.vu-meter {
display: block;
width: 100%;
height: 50%;
background-color: black;
}
.clock {
font-family: courier, mono, monospace;
font-size: 0.9em;
text-align: right;
}
.info h4 {
cursor: pointer;
}
a {
color: #cde;
}
a:visited {
color: #99b;
}
.accordion::before {
content: "▶";
}
.accordion.opened::before {
content: "◢";
}
.warn {
background-color: #400;
color: #d44;
padding: 4px;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
align-items: center;
}
.warn p {
margin:0px;
padding:0px;
}
h5 {
font-size: 1.05em;
}
:fullscreen { display: flex; flex-flow: column; }
:fullscreen > * > h3 { font-size: 1em; }
:fullscreen > .code { flex: 1; max-height: calc(100% + 100px); }
:fullscreen > .info { display: none; }
:fullscreen > .warn { display: none; }
</style>
<link rel="stylesheet" href="codemirror/codemirror.css">
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-M1EBQVY3B4"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('set', { 'restricted_data_processing':true });
gtag('config', 'G-M1EBQVY3B4', { 'allow_google_signals':false,'allow_ad_personalization_signals':false });
</script>
<!-- End Google Analytics -->
<script src="codemirror/codemirror.js"></script>
<script src="codemirror/mode.js"></script>
<script src="codemirror/comment.js"></script>
<script src="codemirror/matchbrackets.js"></script>
</head>
<body>
<canvas id="canvas" class="fullscreen" style="width:100%; height:100%; background: #000f; display:none"></canvas>
<div class="widget">
<div style="display:flex; flex-wrap: wrap;">
<h3>Limut live coding</h3>
<div style="margin-top:2px; margin-left: auto; margin-right: 8px;">
<span id="clock" class="clock"> </span>
</div>
</div>
<p style="display: flex; flex-flow: row nowrap;">
Level:
<span class="vu-meter-base"><span id="vu-meter-l" class="vu-meter"></span><span id="vu-meter-r" class="vu-meter"></span></span>
<input id="main-amp-slider" type="range" min="0" max="200" oninput="mainAmpChange(parseFloat(this.value)/100)" style="flex:auto; margin-left:12px;" />
</p>
<p>
Beat: <span class="beat-readout" id="beat-readout"></span>
<span class="beat-readout">:</span>
<span class="beat-readout" id="beat1-readout"></span>
<span class="beat-readout" id="beat2-readout"></span>
<span class="beat-readout" id="beat3-readout"></span>
</p>
<p id="sliders">
<template id="slider-template">
<p style="display: flex; flex-flow: row nowrap;">
<span class="slider-name"></span>
<input class="slider" type="range" min="0" max="1000" style="flex:auto;"/>
</p>
</template>
</p>
</div>
<div class="widget fixed-top" style="display:flex; flex-wrap: wrap;">
<div style="margin-right:8px;">
<button onclick="go()" title="Run the code Ctrl-Enter">▶</button>
<button onclick="stop()" title="Stop all players Ctrl-.">◼️</button>
<button onclick="comment()" title="Toggle comment for line Ctrl-/">//</button>
<button onclick="fullscreen()" title="Toggle fullscreen">⛶</button>
</div>
<div style="margin-top:8px;">
Audio: <span id="beat-latency-readout" class="meter"> </span>
Visual: <span id="visual-readout" class="meter"> </span>
Limiter: <span id="compressor-readout" class="meter"> </span>
</div>
</div>
<div id="code-codemirror" class="widget code" style="display:none;"></div>
<textarea id="console" class="widget" rows="5"></textarea>
</div>
<div class="info">
<h4 onclick="toggleAccordion('accordion-examples')" class="accordion"> Examples</h4>
<div id="accordion-examples" class="closed">
<p>Copy and paste an example into the editor window, then hit the play ▶ button:</p>
<pre>d1 play x-o-</pre>
<pre>p1 dsaw 0534, add=(0,2,4), dur=4</pre>
<pre>Ba dbass 0, dur=1/4, add=[0:2]r*2, lpf={[3:12]r*100,q:8}, att=0</pre>
<pre>d dsaw 4[32]<10>___.., phaser=1/3, envelope=simple, rel=this.dur*2, amp=3, room={2,mix:1/4}</pre>
<pre>ARP dsaw 02479742, dur=1/4, lpf={100*[3,30]l6.8,q:8}, Oct=(3,5), echo=3/8, att=0
Bass prophet -2210, dur=4, Oct=(2,3), amp=1.7</pre>
<pre>set bpm=125
set * swing=61
p play [X-]-(X*)<---[--^]>, high=4, pan=[-1/4:1/4]r
s tri 00[...0][.0..], dur=1, sus=1/6, att=0.05, room, oct=3, fold, phaser=1/16, amp=2/3, pan=[-1/2:1/2]l4@f+[-1/4:1/4]r, add=(0,2,4,6)
b dbass ...[02]...[0246], room=0.1, lpf={this.freq*[3:12]l11@f,q:15}, pan=[-1/4:1/4]r</pre>
<pre>d play x.h[.x]x[x.]h., room={0.1,mix:1/3}, amp=3/2
set chords=[0,2,4,3]t[16,8,4,4]
be bell 0[.......2], dur=8, add=chords
gl glock 024797.., dur=1/4, add=chords</pre>
<pre>Perc play lstig, dur=[1,3,2], amp=[1/6:1/2]l16, echo=1/8, pan=[-1:1]r
Amb ambi 0[21]., dur=4, release=8, room=2, pan=(-1,1)
Bass dbass 0, dur=8, att=2, rel=4, lpf=100*[3,30]l16@f</pre>
<pre>set Prog=[2,5,4,0]t8
Ba piano 0__2, add=prog, amp=4, Oct=2
Ch piano 0, dur=8, Sus=12, add=(prog+(0,2,4))%7, amp=2, Oct=3
Le piano 0_.[.0]2343, amp=3, add=prog, Oct=4</pre>
<pre>set scale=minor
Ba dbass 0.4[21], dur=4, amp=2, room=1.2, att=0.01, lpf=this.freq*[30,24,4]e1, phaser=1/8
Kd play V[.V]V., dur=2, room=1.1, echo=1/16, amp=2
Sn play .(xO), dur=2, room=1.1, echo=1/16</pre>
<pre>set bpm=120
set * swing=58
set scale=minor
k play Xv, room=1/4, amp=3/2
h play s-, dur=1/4, amp=1/2
ba saw 020.00.0.040.00., dur=1/4, oct=2, sus=1/6, amp=2, lpf={this.freq*[[4:25]l7,2]e,q:15}, room={1,mix:1/5}</pre>
<pre>set bpm=65
pad dsaw (024)(025)(035)(026), envelope=pad, dur=4, lpf=[600:3000]s21, oct=3, amp=[1.2:2.0]s70
padf ethereal follow pad, oct=4
pi ping 0, dur=[3,3,2]/20, amp=[0.5:1.2]n*[2:0]s96, oct=[3,4,5,6]t1/4, add=[0,5,3,4]t4+[0,[1:3]n32,4,[6:10]n37]r, sus=2, addc=[-.15:.15]n</pre>
<pre>v kal 0, tunnel, scroll={x:time/8}, monochrome, fore=rainbow, mid=white
b dbass [(04v).], dur=8, noisify=1/8, drive=2/8, fold=1, phaser=1/8, room=2, add=[2,3,1,0]t8, addc=wow, pan=[-1/2:1/2]r, chorus=2, att=1/2, rel=5</pre>
<pre>set bpm=145
set scale=minor
v streetlight 0
kd play (xv):, lpf=1000
hh play -, dur=1/4, amp=[0.2:1.2]n
kk play ::[::][::][::]::., lpf=[600:900]l40, rate=[0.8:1.2]n
ba dbass 0, dur=1/4, att=0, lpf=[1000:100]e, hpf=[0:500]n
pi ping [010], add=[-5:5]l18/4, amp=[0:[0:1]t96]n, echo=1/2, oct=6, scale=minorpentatonic
pad dsaw (-303), dur=16, envelope=pad, amp=[0:3/2]s64@f, room=0.5, lpf=[1000:3000]s32@f, oct=3, addc=[2,2,0,0]s[62,4,62,0]@f</pre>
<pre>set bpm=90
n noise 00, dur=[9,7], envelope=simple, bpf=523*[[1:5]e,[1:1/5]e]*[1:[1.1,1.25]]n1, amp=3/2, att=[2,1/4], rel=[9,7], pan=[-1,1]l8@f
p dsaw 0., dur=[3,1,5,3,3,4], addc=[1:3]r+[2,0]e, envelope=simple, att=0.1, rel=[0.4:0.6]r, oct=6, pan=[-1:1]n8, amp=[0.3:1.1]n8, room=1
</pre>
<pre>s supersaw 0, dur=[1/4:1]l8, scale=penta, add=[-10:10]r1/2, room=2, lpf={[300,3000,300]e,q:11}, amp=2, phaser=1/4
</pre>
<pre>v kal 0, mirror={100,fan:[7:12]s32@f/10}, zoom=3, mid=random, contrast
</pre>
<pre>ld dsaw 0^.70-7.70, dur=1/4, scale=minor, add=[0,2,4]r+[0,2,3,0]t4, lpf={this.freq*[3/2,2,3,5]t4,q:25}, room, delay=(0,[1/4,1/2,3/4,5/4]r), echo=7/8, addc=wow
</pre>
<pre>v kal 1, buffer=vb1, contrast=3, blend=max, zoom=2, scroll=1
vb1 buffer 0, feedback={zoom:1.01,ripple:1/32,contrast:0.005}
</pre>
<pre>
include 'preset/house.limut'
set bpm=127
b tb303 `0a2u2b0d 0u0a2d3 00u0a0d 0da4ua5a6u`, cutoff=[1/4:1]n3, resonance=0.8, accent=1
</pre>
<p>More examples: <a href="https://github.com/sdclibbery/limut/blob/master/examples.limut" target="_blank">https://github.com/sdclibbery/limut/blob/master/examples.limut</a></p>
</div>
<h4 onclick="toggleAccordion('accordion-glossary')" class="accordion"> Glossary</h4>
<div id="accordion-glossary" class="closed">
<p>Chord: multiple simultaneous events</p>
<p>Command: One programming instruction to tell limut what to do</p>
<p>Event: One event to be played; either an audio note/sample or a visual display</p>
<p>Expression: Code that evaluates to a value</p>
<p>Global Var: A variable; something whose value can be set by a command, and then read in an expression</p>
<p>Indicator: Visual display on the limut screen to help with composition or production</p>
<p>Map: Value containing multiple values indexed by keys</p>
<p>Modifier: Additional data thats changes the value of an expression, eg by modifying the current time it sees, or by providing a random seed</p>
<p>Param: A named parameter expression that controls the output produced by a synth</p>
<p>Pattern: A sequence defining the notes or control values to be played by a synth</p>
<p>Player: An player uses a synth to play events in a pattern, controlled by params</p>
<p>Subparam: An additional parameter provided extra info on how a param should control the output of a synth</p>
<p>Synth: An audio or visual synthesizer that can produce sound output or visual display.</p>
<p>Timevar: An expression whose value varies over time</p>
<p>Value: A primitive value to control synths</p>
</div>
<h4 onclick="toggleAccordion('accordion-indicators')" class="accordion"> Indicators</h4>
<div id="accordion-indicators" class="closed">
<p><b>Level</b> VU meter for current output signal level. Use this when adjusting the output level, using either <code>set main amp</code> or the level slider, so it is just touching the red at its loudest. Only one active channel is shown if the mix is fully mono.</p>
<p><b>Beat</b> Current audio system beat count, followed by beat counts out of 12, 16 and 32 beats (useful for synchronising changes to various size musical bars and progressions)</p>
<p><b>Audio</b> Audio lag; green when the browser audio system is keeping up; turns red when the system is struggling, which may lead to audio glitching</p>
<p><b>Visual</b> Visual lag; green when the framerate is keeping up to 60 fps; turns red when the system is struggling, which may lead to visual glitching</p>
<p><b>Limiter</b> Audio limiter: turns red when the internal Limut limiter is active, implying the combined audio sources are too loud. Note this limiter is before the <code>main amp</code> control and vu meter, it makes sure the levels from individual synths do not go so loud as to distort. So if it is lighting up, lower the <code>amp</code> on individual synths, and if necessary, raise the <code>main amp</code> level to compensate.</p>
</div>
<h4 onclick="toggleAccordion('accordion-console')" class="accordion"> Console</h4>
<div id="accordion-console" class="closed">
<p>The console is the text window below the main code editing area. Use the console to see information, warnings and command output. Type a command and press enter to execute it.</p>
<p><code>list</code> List all player base types, including presets, grouped by player base type and the include file that defined the preset</p>
<p><code>list audio</code> List all player base types, filtered to those where the base type contains the given string</p>
</div>
<h4 onclick="toggleAccordion('accordion-syntax-principles')" class="accordion"> Syntax Principles for Expressions</h4>
<div id="accordion-syntax-principles" class="closed">
<p><code>()</code> Round brackets define chords in both patterns and expressions; that is, mutltiple events or values at the same time. Chord indexers and aggregators can be used to extract various values from chords.</p>
<p><code>[]</code> Square brackets define sequences in both patterns and expressions; that is, multiple events or values one after another over time (sequences/timevars)</p>
<p><code><></code> Angle brackets define higher level sequences in patterns; that is, a sequence where the next event is selected when the entire pattern repeats next.</p>
<p><code>{}</code> Curly brackets in an expression supply extra information to a param (subparams), value (modifiers) or function call (arguments)</p>
<p><code>@</code> Defines the interval for an expression; that is, how often the expression should be evaluated within the event. Note, the interval applies directly to the nearest value. So for example, with <code>this.foo@e</code> the per-event <code>@e</code> interval will apply to the <code>foo</code> only. To force the overall <code>this.foo</code> lookup to be evaluated per event, you could use <code>(this.foo)@e</code>.</p>
</div>
<h4 onclick="toggleAccordion('accordion-basic-syntax')" class="accordion"> Basic Syntax</h4>
<div id="accordion-basic-syntax" class="closed">
<p>Limut is case insensitive; <code>piano</code>, <code>Piano</code>, and <code>PIANO</code> are all treated the same; <code>[1:4]t4</code> is the same as <code>[1:4]T4</code> etc.</p>
<h5>Comments</h5>
<p>Anything after <code>//</code> on a line is ignored</p>
<p>Anything within a <code>/* ... */</code> comments is ignored</p>
<h5>Commands</h5>
<p>A command defines a player or preset, or sets player overrides, or sets global variables, or includes a limut source file. Commands may span multiple lines; a new command is started whenever the beginning of a command is recognised at the start of a new line. So any line that begins with <code>set </code> keyword for setting vars or overrides, or with the <code>id type pattern</code> syntax for defining a player, will begin a new command.</p>
<p>Example:
<pre>
include 'preset/synthwave.limut' // Command that includes a limut source file from a URL
preset mysynth ping, amp=3 // Command that creates a preset synth based on the 'ping' synth, but overriding the amp value
set bpm=130 // Command that sets the global bpm (beats per minute) var to 130bpm.
kick play x., amp=2, // Start of a command that defines the player called 'kick', of type `play`, with an amp (volume) of 2
drive=1/2 // Continuation of the kick player definition, setting its drive param to 1/2
set kick drive=0 // New command defining an override for the kick player, setting its drive param to zero. Overrides like this take precedence over params set on the player itself.
</pre>
</p>
<h5>Defining a player</h5>
<p>Basic structure: <code>id synth pattern, params</code></p>
<p>A player command begins when something matching <code>id synth pattern</code> begins a new line. The params may follow on subsequent lines.</p>
<p><code>id</code> Identifier for the player, so it can be referred to from other players etc. Must contain only alphanumeric characters from the basic Latin alphabet or underscore, and must not start with a digit. No player can be named <code>set</code> or <code>preset</code> as those are reserved keywords.</p>
<p><code>synth</code> Name of the audio or visual synth to use; eg <code>piano</code></p>
<p><code>pattern</code> Pattern of notes to play. Specifies the notes or sounds to play, and when to play them</p>
<p><code>params</code> Comma separated list of params (eg <code>amp=1/2</code>) that affect how the player plays; see 'Value Syntax' and 'Params' sections below</p>
<h5>Overriding player params:</h5>
<p>Basic structure: <code>set id params</code></p>
<p>A set overrides command begins when <code>set </code> begins a new line. The id and params may follow on subsequent lines.</p>
<p><code>id</code> Player identifier; the override params will be apllied to this player. Can also be a list of multiple players to apply the params to; eg <code>set (kd,sd) amp=0</code>. Can include wildcards, so <code>set p* ...</code> will apply the overrides to every player whose name starts with 'p'. <code>set * ...</code> will apply to all players. <code>set !p ...</code> will apply to all players _except_ 'p'.</p>
<p><code>params</code> Comma separated list of params (eg <code>amp=1/2</code>) that affect how the player plays; see 'Value Syntax' and 'Params' sections below</p>
<p class='sub'><code>modification overrides</code> params can be defined using operators to modify existing values rather than override them; eg <code>add+=2</code> will increase the add parameter by an additional 2 on top of what it was already set to.</p>
<h5>Setting global vars:</h5>
<p>Basic structure: <code>set var = value</code></p>
<p>A set global var command begins when <code>set </code> begins a new line. The var and value may follow on subsequent lines.</p>
<p><code>var</code> variable to set; either a predefined var (see 'Predefined Vars' section below) or a user defined var which can be referenced from params on any player(s)</p>
<p><code>value</code> expression value to set; see 'Value Syntax'</p>
<h5>Creating a synth preset:</h5>
<p>Basic structure: <code>preset name synth, params</code></p>
<p>A preset global var command begins when <code>preset </code> begins a new line. The params may follow on subsequent lines.</p>
<p><code>name</code> The name for the preset. The preset can be used by players by referring to this name as the player type. Must contain only alphanumeric characters from the basic Latin alphabet or underscore, and must not start with a digit.</p>
<p><code>synth</code> The existing synth (or preset) to base this preset on</p>
<p><code>params</code> Series of param overrides to apply for players that use this preset</p>
<h5>Including a limut source file:</h5>
<p>Basic structure: <code>include 'url'</code></p>
<p>Include a limut source file. The file will be downloaded from the given URL and then executed as limut code. The file will only be downloaded once, but will be executed every time the code is updated.</p>
<p><code>url</code> The URL of the limut source file to include. Must be in single quotes as a limut string. Include standard limut libraries from eg <code>'preset/synthwave.limut'</code>. Include limut source from anywhere on the web (CORS permitting) using the full URL; eg <code>'https://sdclibbery.github.io/limut/preset/synthwave.limut'</code></p>
</div>
<h4 onclick="toggleAccordion('accordion-pattern-syntax')" class="accordion"> Patterns</h4>
<div id="accordion-pattern-syntax" class="closed">
<p><code>x-o-</code> Sequence of events, each with duration given by the player's <code>dur</code> param, for use with <code>play</code></p>
<p><code>0123</code> Sequence of events, each with duration given by the player's <code>dur</code> param, for use with tonal synths. Numbers are scale degrees</p>
<p><code>`01 23`</code> Pattern literal; inside backticks, pattern elements can be separated by whitespace which will be ignored. Backticks force the contents to be treated as a literal, so for example <code>`01 loop 1`</code> is treated as the literal <code>01loop1</code> and the loop operator is ignored.</p>
<p><code>0-1-2-3</code> Negative scale degrees allow tones below the synth root pitch</p>
<p><code>x.</code> Use a dot for a rest</p>
<p><code>0#</code> # following numeric event makes it sharp</p>
<p><code>0b</code> b following numeric event makes it flat</p>
<p><code>0=</code> = following numeric event extends the duration by 50%</p>
<p><code>0!</code> ! following numeric event shortens the duration by 33%</p>
<p><code>0^</code> ^ following numeric event makes it 50% louder</p>
<p><code>0v</code> v following numeric event makes it 33% quieter</p>
<p><code>0a</code> Other characters following numeric event become params; for example <code>t tri 01g23, glide=this.g/2</code></p>
<p><code>x^</code> ^ following non-numeric event makes it 50% louder (for use with play synth)</p>
<p><code>0_[_1]</code> Continuation: use underscore to extend the previous note duration. Currently continuations are not valid within chords <code>()</code> or supersequences <code><></code></p>
<p><code>0[123]</code> Subsequence: square brackets to fit multiple events into one <code>dur</code> (triplet shown)</p>
<p><code>0(135)</code> Chord: Round brackets to play multiple events together</p>
<p><code>0<12></code> Supersequence: angle brackets to play events in sequence as the pattern repeats. Eg <code>0<12></code> is exactly equivalent to <code>0102</code></p>
<p><code>01 loop 2</code> Restrict the number of times the pattern can loop. In the example, the pattern <code>01</code> will play twice and then stop. The player will not reset until it gets recreated or changed. So if a player with a loop pattern has finished its repeats, it will not start playing again until it is commented out/in, or playback stopped and restarted, or the pattern string is changed and updated.</p>
<p><code>0123 crop 2</code> Crop a pattern to a given number of steps. For example, <code>0123 crop 2</code> is equivalent to <code>01</code>. Crop will repeat the pattern if necessary, eg <code>01 crop 5</code> is equivalent to <code>01010</code></p>
<p><code>1 + 2</code> Concatenate two patterns; the first pattern plays then the second. For example, <code>12 + 34</code> is the same as <code>1234</code></p>
<p><code>1 * 2</code> Repeat a pattern; the first pattern plays a given number of times. For example, <code>12 * 2</code> is the same as <code>1212</code></p>
<p><code>now 01</code> Play the pattern starting on the next beat, rather than as if it had been playing from beat 0. In the example, the pattern <code>0123</code> will play starting from the <code>0</code> whatever beat the player is started on.</p>
<p><code>follow p1</code> Use <code>follow</code> to follow another player (named 'p1' in the example) pattern</p>
<p><code>gamepad</code> Use <code>gamepad</code> to generate notes from a gamepad controller rather than a pattern. The gamepad buttons will be mapped to note degrees in some arbitrary way.</p>
<p class='sub'><code>gamepad 1</code> use input from gamepad 1 (default is 0)</p>
<p class='sub'><code>gamepad lt:vel</code> Use the left trigger (assumed to be analogue) to control the given param (vel for velocity of the gamepad notes). When the <code>lt:</code> arg is used, the left trigger will not play a note itself.</p>
<p class='sub'><code>gamepad rt:echo</code> Use the right trigger (assumed to be analogue) to control the given param (echo in the example). When the <code>rt:</code> arg is used, the right trigger will not play a note itself.</p>
<p class='sub'><code>gamepad nodpad</code> On some controllers the dpad can be in the way of the sticks. Using 'nodpad' will disable the dpad input.</p>
<p><code>midi</code> Use <code>midi</code> to generate notes from a midi controller rather than a pattern. By default the player will be set to a chromatic scale and the note value and oct will be such as to map the keyboard note played to the same note played in limut. <code>this.vel</code> will include the note velocity, from 0 to 1.</p>
<p class='sub'><code>midi 9</code> use input from midi channel 9 (default is 0)</p>
<p class='sub'><code>midi 9 1</code> use input from midi channel 9 on port (device) 1 (default is 0)</p>
<p class='sub'><code>midi perc 9 0</code> use input from midi channel 9 port 0 and treat it as percussion, so instead of mapping to a chromatic note scale value, map to limut percussion samples. For example, midi note 36 (Bass drum 1) maps to 'X' (Heavy kick)</p>
</div>
<h4 onclick="toggleAccordion('accordion-value-syntax')" class="accordion"> Values</h4>
<div id="accordion-value-syntax" class="closed">
<p>Basic structure <code>value{modifiers}@interval</code></p>
<p>Note: the order of interval and modifier can be swapped if desired. For example, <code>[]r@f{seed:1}</code> is the same as <code>[]r{seed:1}@f</code>.</p>
<p><code>value</code> Actual value (which may include subparameters); see below</p>
<p><code>{modifiers}</code> Map of modifiers and/or arguments. Modifiers may modify the time passed to the value expression, or the value it returns, or provide additional data for a parameter. For example, <code>[1,2,3]t1{0:0,per:8}</code> will give a sequence that repeats every 8 beats, forced to the value 0 at the start of each repeat. In other words, the repeating sequence: 0,2,3,1,2,3,1,2. See "Modifiers" below.</p>
<p><code>@interval</code> Intervals specify how often the value should be evaluated, for example once per event (then the same value through the event), or continuously varying. See "Intervals" below.</p>
<h5>Values:</h5>
<p><code>1</code> Single, constant numeric value</p>
<p><code>0dB</code> Numeric values can be expressed in dB. These are immediately (at parse time) converted to gain numbers, so 0dB is a gain of 1, +20dB is a gain of 10 etc. Values can be specified in dB for any numeric values, however it may not make sense in all cases. <code>amp=6dB</code> is basically equivalent to <code>amp=2</code>; it doubles the output level of a player. But while <code>scroll=6dB</code> is still the same as <code>scroll=2</code>, it doesn't make much sense to write it way (especially since it is impossible to express negative numbers with dB: Eg <code>-20dB</code> is the same as <code>1/2</code>. Note that because dB is a relative scale, it must be multiplied. Eg to add +3dB to an amp, multiplication must still be used: <code>amp*=3db</code></p>
<p><code>1#</code> <code>1b</code> For use with the audio <code>add</code> param, sharpen or flatten the value. This is parsed into <code>{1,#:1}</code> or <code>{1,b:1}</code></p>
<p><code>100ms</code> Single, constant numeric value with time units. Time units are valid for any param which has a default time unit. In general time units will be automatically converted between beats and seconds (using the current bpm), and also between time and frequency; so <code>lpf=0.001s</code> is equivalent to <code>lpf=1000</code> because the default units for lpf is Hz.</p>
<p class='sub'><code>1s</code> Time in seconds</p>
<p class='sub'><code>1000ms</code> Time in milliseconds</p>
<p class='sub'><code>1Hz</code> Frequency in Hertz (cycles per second). Also <code>1cps</code> is the same as <code>1Hz</code> and <code>1kHz</code> is <code>1000Hz</code>.</p>
<p class='sub'><code>1cpm</code> Frequency in cycles per minute</p>
<p class='sub'><code>1b</code> Time in beats</p>
<p class='sub'><code>1cpb</code> Frequency in cycles per beat. Also <code>1kcpb</code> is <code>1000cpb</code></p>
<p><code></code> No value: for a param, missing a value is the same as setting the param to <code>1</code>. Eg <code>monochrome</code> is the same as <code>monochrome=1</code></p>
<p><code>(1,2)</code> A chord. Multiple values, all played together at the same time</p>
<p><code>[1,2]</code> Sequence of values, one after another, one per event in the pattern, ignoring rests. For single length patterns only, all values will be expanded, so <code>p ping 0, add=[0,1,2]</code> will cycle through all three values.</p>
<p><code>[]</code> Equivalent to [0,1].</p>
<p><code>[1,2]t3</code> Timed sequence, each value lasts for 3 beats. Duration must be a const number, cannot be an expression. Default time unit: beats.</p>
<p><code>[]t</code> Equivalent to [0,1]t.</p>
<p><code>[1:12,2:4]t</code> Timed sequence with variable timing per value. Durations can be expressions. Default time unit: beats.</p>
<p><code>[0:3]t1</code> Timed sequence, expanded. The example is equivalent to <code>[0,1,2,3]t1</code></p>
<p><code>[1,2]l3</code> Timed linear interpolated sequence, each value takes 3 beats to change into the next. Default time unit: beats.</p>
<p><code>[]l</code> Equivalent to [0,1]l.</p>
<p><code>[1:12,2:4]l</code> Timed linear interpolated sequence with variable timing per value. Durations can be expressions. Default time unit: beats.</p>
<p><code>[1,2]s3</code> Timed smooth interpolated sequence, each value takes 3 beats to change into the next, using an 's' shaped ease in/out curve. Duration must be a const number, cannot be an expression. Default time unit: beats.</p>
<p><code>[]s</code> Equivalent to [0,1]s.</p>
<p><code>[1:12,2:4]s</code> Timed smooth interpolated sequence with variable timing per value. Durations can be expressions. Default time unit: beats.</p>
<p><code>[1,2]e</code> Timed interpolated sequence, each value is evenly spaced from beginning to end of the current event</p>
<p><code>[1,2]e1</code> Timed interpolated sequence starting at the beginning of the event, each value takes 1 beat to change to the next. Duration must be a const number, cannot be an expression. Default time unit: beats.</p>
<p><code>[0:!300ms,1:_[1/4b:1/2b]r,0]e</code> Timed piecewise sequence starting at the beginning of the event. In this case it would provide an envelope for the event, with an exponential attack lasting 300ms, followed by a const sustain lasting between 1/4 and 1/2 a beat at random. Default time unit: beats.</p>
<p><code>[1:!200ms,0]e@s</code> []e@s is the same as []e, except when used for an audioparam (eg amp or lpf), it will create segments instead of regular updates. This will provide more accurate and consistent timing (for example, for pluck envelopes). However, it will block other per frame expressions, and also time modifiers, from working correctly.</p>
<p><code>[]r</code> Select a different value every time, chosen randomly between 0 and 1</p>
<p><code>[1,4,7]r</code> Select a different value every time, chosen randomly from the numbers 1, 4 and 7</p>
<p><code>[:9]r</code> Select a different random float every time, between 0 and 9</p>
<p><code>[0:9]r</code> Select a different random float every time, between 0 and 9. Note if this will be rounded to to an integer (eg for oct, add or sample params), then the upper limit is exclusive. eg <code>oct=[2:3]r</code> will give a float value between 2 and 2.9999...., so since oct rounds down to the nearest integer, it will always get <code>oct=2</code></p>
<p><code>[0,1:7]r</code> Select a different random float every time, either 0 or 1. The 1 is 7 times more likely than the 0.</p>
<p><code>[1,2]r4</code> Select a different value and hold for 4 beats, chosen randomly from the numbers 1, 2. The hold time must be a const number, it cannot be an expression. Default unit: beats.</p>
<p><code>[1:3]r{seed:1,per:4}</code> Select a different determninistic random float every time, between 1 and 3; <code>seed</code> determines the random sequence; the sequence repeats every <code>per</code> beats. <code>seed</code> is also in beats, so adding 1 to seed pushes the sequence by 1 beat.</p>
<p><code>[]n</code> Smoothly varying noise, moving between 0 and 1</p>
<p><code>[1:2]n</code> Smoothly varying noise, moving between 1 and 2</p>
<p><code>[1:2]n4</code> Smoothly varying noise, moving between 1 and 2, taking 4 beats to progress from one value to another. The timing must be a const number, it cannot be an expression. Default time unit: beats.</p>
<p><code>[]n{seed:1,per:4}</code> Smoothly varying deterministic noise, moving between 0 and 1; <code>seed</code> and <code>per</code> work the same as for <code>[]r</code></p>
<p><code>[ v1:i1t1, v2:i2t2, ... ]{p,repeat:0}</code> Piecewise series. Allows interpolating between a set of values, specifying the interpolation and 'travel' between each pair of values, and allowing a custom parameter to control the interpolation. For example, <code>[0:_1,1:\]{time*2}</code> is controlled by double-speed time, starts at 0, stays constant at zero for 1 unit of double-speed time, then jumps to 1 and linearly falls back down to 0 for 1 unit of double-speed time.</p>
<p class='sub'><code>v1 etc</code> Expressions giving the values to interpolate between</p>
<p class='sub'><code>i1 etc</code> Interpolation operator</p>
<p class='subsub'><code>:/ :\</code> Linear interpolation operators; both do the same, but the two can be used to indicate direction</p>
<p class='subsub'><code>:_</code> Const interpolation operator: stay at original value right to end of step</p>
<p class='subsub'><code>:_</code> Step interpolation operator: immediately jump to new value from start of step</p>
<p class='subsub'><code>:~</code> Smoothed interpolation operator: bezier ease in/out s-shaped smooth transition through step</p>
<p class='subsub'><code>:!</code> Exponential interpolation operator: exponential growth/decay to target</p>
<p class='subsub'><code>:^4:</code> Power interpolation operator: power curve interpolation. In this example, the interpolation is raised to power 4, so it will move slowly to start with the quickly reach the target. <code>:^1/4:</code> would quickly move toward the target, then slow down.</p>
<p class='sub'><code>t1 etc</code> The amount of parameter p travel between this value and the next; note the sequence wraps round. Default time unit: beats.</p>
<p class='sub'><code>p</code> Parameter expression giving the current point of travel through the piecewise series</p>
<p class='sub'><code>repeat</code> Optional repeat parameter. Leave out for a repeating pattern, set to zero to disable repeat and clamp the value when the parameter is less than zero or greater than the full length of the piecewise.</p>
<p><code>+</code> Add values together; eg <code>[2,3]+4</code> is equivalent to <code>[6,7]</code></p>
<p><code>-</code> Subtract values; eg <code>[2,3]-1</code> is equivalent to <code>[1,2]</code></p>
<p><code>-</code> Unary minus operator; eg <code>-[1,2]</code> is equivalent to <code>[-1,-2]</code></p>
<p><code>/</code> Divide values; eg <code>[1,2,3]/2</code></p>
<p><code>*</code> Multiply values; eg <code>[1,2,3]*1000</code></p>
<p><code>%</code> Take remainder; eg <code>(0,4,7,9)%7</code> is equivalent to <code>(0,4,0,2)</code></p>
<p><code>^</code> Raise to the power; eg <code>2^3</code> is 8. Imaginary results return 0; eg <code>-1^1/2</code> returns 0.</p>
<p><code>|</code> Concatenate chords; eg <code>1|2</code> is the same as <code>(1,2)</code>, and <code>(1,2)|(3,4)</code> is <code>(1,2,3,4)</code></p>
<p><code>??</code> "If then" operator. Check a condition in the left operand for truthiness, and return either the value in the right operand, or nothing. Eg <code>this.foo??5</code> will return nothing if <code>this.foo</code> is (eg) <code>0</code>, or <code>5</code> if <code>this.foo</code> is (eg) <code>1</code>. This operator short circuits, so if the right operand is not returned, it will not be evaluated.</p>
<p><code>?:</code> "Or else" operator. If the left operand is nothing, return the right hand operand. Otherwise, return the left operand. Eg <code>this.foo?:5</code> will give the value of <code>this.foo</code> if present, or <code>5</code> if not. Note this can be used with the above <code>??</code> operator as a ternary conditional expression; eg <code>this.foo>1 ?? 2 ?: 3</code> - if <code>this.foo</code> is greater than 1, then the expression will evaluate to 2, otherwise it will evaluate to 3. This operator short circuits, so if the right operand is not returned, it will not be evaluated.</p>
<p><code>.</code> Lookup values in a player (with a param name), a chord (with an index or aggregator) or a map (with a field name). See Lookup Examples section below.</p>
<p><code>==</code> Compare values for equality. Returns 1 if equal, 0 if not.</p>
<p><code>!=</code> Compare values for inequality. Returns 0 if equal, 1 if not.</p>
<p><code><</code> Check if the left operand is less than the right. Returns 1 if left is less, 0 if not.</p>
<p><code>></code> Check if the left operand is greater than the right. Returns 1 if left is greater, 0 if not.</p>
<p><code><=</code> Check if the left operand is less than or equal to the right. Returns 1 if left is less or equal, 0 if not.</p>
<p><code>>=</code> Check if the left operand is greater than or equal to the right. Returns 1 if left is greater or equal, 0 if not.</p>
<p><code>{x:0,y:1}</code> Map, containing keys and values</p>
<p><code>{2,y:1}</code> Map, containing keys and values, with a main value of 2. The main value is the same as if no map was used; eg <code>chop={2,wave:'tri'}</code> is the same as <code>chop=2</code>, but also supplies an additional 'wave' subparameter.</p>
<p><code>{r:1,g:0,b:0,a:1}</code> RGBA colour; component range is 0 - 1.</p>
<p><code>{h:1,s:1,v:1,a:1}</code> HSV + alpha colour; component range is 0 - 1, including hue. Note RGB components can also be specified as overrides; eg <code>{h:1,b:1,a:1}</code> will be magenta not red.</p>
<p><code>{labh:1,c:1,l:1,a:1}</code> LabLCH + alpha colour; component range is 0 - 1, including hue. Note RGB components can also be specified as overrides; eg <code>{labh:1,b:1,a:1}</code> will be magenta not red.</p>
<p><code>#0369</code> Hex colour value which becomes the colour map <code>{r:0,g:0.2,b:0.4,a:0.6}</code></p>
<p><code>#036</code> Hex colour value which becomes the colour map <code>{r:0,g:0.2,b:0.4,a:1}</code></p>
<p><code>#00336699</code> Hex colour value which becomes the colour map <code>{r:0,g:0.2,b:0.4,a:0.6}</code></p>
<p><code>#003366</code> Hex colour value which becomes the colour map <code>{r:0,g:0.2,b:0.4,a:1}</code></p>
<p><code>'abc'</code> String value. Strings must be defined on a single line; multiline strings are not supported. However, line breaks can be inserted with <code>\n</code></p>
<p><code>foo</code> Lookup a global var named <code>foo</code>. If there is no var, predefined var, or var function named foo, then the string <code>'foo'</code> will be returned instead. If there is a var named foo, but no arguments are provided, then the string <code>'foo'</code> will be returned instead.</p>
<p><code>foo{x:2}</code> Lookup a global var named <code>foo</code>, and call it as a function passing in named parameters.</p>
<h5>Modifiers:</h5>
<p><code>{time:time}</code> Provide an expression to give the modified time value. For example <code>value{time:time*2+8}</code> will run time at double speed, with an offset of 8.</p>
<p><code>{per:8}</code> Repeat a sequence <code>[1,2,3]t1{per:8}</code> will give a sequence that repeats every 8 beats.</p>
<p><code>{per:8,0:7,2:3}</code> Force the value to evaluate to 7 at the start of each repeat, and 3 on the second beat of every repeat. Note this only works if <code>per</code> is used to make a repeating sequence. Default time units: beats.</p>
<p><code>{step:2}</code> Advance time in discrete steps only <code>[1,4]l4{step:1/2}@f</code> will give a sequence that changes value only every 1/2 beat. Default units: beats.</p>
<h5>Intervals:</h5>
<p><code>@e</code> Use <code>@e</code> to evaluate this value once per event</p>
<p><code>@f</code> Use <code>@f</code> to evaluate once per frame (60 times a second). For example <code>lpf=[300:3000]l8@f</code> will update the lpf cutoff frequency continuously, while <code>lpf=[300:3000]l8</code> will be evaluated only once for each event played.</p>
<p><code>@s</code> Use <code>@s</code> to evaluate per segment for audio param control. This is more accurate for audio envelopes. For example, <code>amp=[1:!200ms,0]e@f</code> will evaluate 60 times per second which may give an inconsistent and sloppy envelope. But <code>amp=[1:!200ms,0]e@s</code> will create a single exponential audioparam segment giving a more accurate result</p>
<h5>Lookup examples</h5>
<p><code>p1.amp</code> Lookup the value of param <code>amp</code> from player <code>p1</code>. Returns a chord of values from all currently playing events.</p>
<p><code>p1.amp.0</code> Lookup the value of param <code>amp</code> from player <code>p1</code>, and if it contains a chord, extract the first element only from it.</p>
<p><code>p1.pulse.max</code> Lookup the value of the <code>pulse</code> from player <code>p1</code>, and if it contains a chord, extract the largest element only from it. The pulse param gives a smoothed approximate envelope shaped value between 0 and 1 for each event.</p>
<p><code>this.value</code> Get param <code>value</code> from the current event. Returns a single value (not generally a chord) from the event the expression is being evaluated on.</p>
<p><code>([0,1]t1@f).accum</code> Smoothly accumulate 1 every other beat</p>
<p><code>{foo:2}.foo</code> Returns a field in a map (returns 2 in this example)</p>
<p><code>(3,1,2).0</code> Returns the nth element in a chord (returns 3 in the example)</p>
<p><code>(3,1,2).3</code> Returns the nth element in a chord, wrapping around (returns 3 in the example)</p>
<p><code>(3,1,2).(0,2)</code> Returns multiple elements in a chord (returns (3,2) in the example)</p>
<p><code>(3,1,2).first</code> Returns the first element in a chord (returns 3 in the example)</p>
<p><code>(3,1,2).last</code> Returns the last element in a chord (returns 2 in the example)</p>
<p><code>(3,1,2).rand</code> Returns a random element from a chord (returns 1, 2 or 3 at random in this example)</p>
<p><code>(3,1,2).min</code> Returns the smallest element in a chord (returns 1 in the example)</p>
<p><code>(3,1,2).max</code> Returns the largest element in a chord (returns 3 in the example)</p>
<p><code>(3,1,2).count</code> Returns the number of elements in a chord (returns 3 in the example)</p>
<p><code>(3,1,2).sum</code> Returns the sum of all elements in a chord (returns 6 in the example)</p>
<p><code>(3,1,2).avg</code> Returns the mean average of all elements in a chord (returns 2 in the example)</p>
</div>
<h4 onclick="toggleAccordion('accordion-user-functions')" class="accordion"> User Defined Functions</h4>
<div id="accordion-user-functions" class="closed">
<p>Basic structure: <code>{args} -> body</code></p>
<p>User defined functions (also called lambdas) let you build reusable expressions. The <code>{args}</code> declares the parameters, and the expression after <code>-></code> is the function body. Functions are values like any other, so they are usually stored in a global var with <code>set</code> and then called by name.</p>
<h5>Defining a function</h5>
<p><code>set double = {value} -> value*2</code> Define a function called <code>double</code> with one argument called <code>value</code>, which returns the argument doubled.</p>
<p><code>set square = {x} -> x^2</code> Argument names can be anything; they are referenced by name inside the body.</p>
<p><code>set add = {x,y} -> x+y</code> Multiple arguments are separated by commas.</p>
<p><code>set hello = {} -> 'hi'</code> A function with no arguments still needs the empty <code>{}</code> on the left.</p>
<p><code>set lpf = {freq, q:5} -> biquad{'lowpass', freq:freq, q:q}</code> Arguments can have default values using <code>name:default</code>. If the caller does not supply that argument, the default is used. Arguments without a default are required.</p>
<h5>Calling a function</h5>
<p><code>double{3}</code> Call with a single positional argument. Returns 6.</p>
<p><code>add{3,4}</code> Call with multiple positional arguments. Returns 7.</p>
<p><code>add{x:3,y:4}</code> Call with named arguments. Order does not matter; <code>add{y:4,x:3}</code> gives the same result.</p>
<p><code>add{3,y:4}</code> Positional and named arguments can be mixed.</p>
<p><code>hello{}</code> No-argument calls can optionally include the {}</p>
<p><code>hello</code> A user function can still be called without an arg list.</p>
<h5>Positional argument names</h5>
<p>Positional arguments are looked up by the names <code>value</code>, <code>value1</code>, <code>value2</code> etc, in order. So <code>{value,value1} -> value*value1</code> can be called as <code>foo{3,4}</code> to get 12. This means that the first argument name <code>value</code> is special: if you declare <code>{value} -> ...</code> then the first positional arg fills <code>value</code>, and you can also pass it by name as <code>foo{value:3}</code>.</p>
<p>A consequence is that a function with a first argument named <code>value</code> can be called very concisely. This is how many library functions (for example <code>mix2</code>, <code>echo</code>, and the shapers in <code>lib/nodes.limut</code>) accept their main argument positionally without the caller writing any name.</p>
<h5>Inline (anonymous) functions</h5>
<p><code>({x} -> x^2){3}</code> A function can be called immediately without storing it in a var, by wrapping the definition in round brackets and applying arguments. Returns 9.</p>
<p><code>convolver{{x} -> (1-x)^3, length:1s}</code> Anonymous functions are often passed directly as arguments to other functions (for example to node functions such as <code>convolver</code> and <code>shaper</code>) to provide a shape or envelope.</p>
<h5>Scope and global vars</h5>
<p>Inside a function body, argument names take priority over global vars with the same name. So in <code>{foo} -> foo</code>, the <code>foo</code> in the body refers to the argument, not to any global var called <code>foo</code>.</p>
<p><code>global.foo</code> Use the <code>global.</code> prefix inside a function body to force a lookup of the global var, bypassing any argument of the same name. For example <code>{foo} -> global.foo</code> ignores the passed argument and returns the global <code>foo</code>.</p>
<p>Global vars that are not shadowed by an argument are visible inside the body as normal. So <code>set gain = 2</code> followed by <code>set amp = {x} -> x*gain</code> will multiply <code>x</code> by whatever <code>gain</code> is when <code>amp</code> is called.</p>
<h5>What a function can return</h5>
<p>The body is a normal expression, so it can return anything an expression can produce: numbers, chords, timevars, maps, strings, or audio node chains. For example <code>{freq} -> osc{'sine', freq:freq}</code> returns an audio node; <code>{} -> []r@f</code> returns a per-frame random value. Interval markers (<code>@e</code>, <code>@f</code>, <code>@s</code>) inside the body carry through to the caller as expected.</p>
<p>Passing a timevar as an argument works naturally: <code>double{[4,5]t1@f}</code> evaluates the timevar on each frame and doubles each value.</p>
<h5>Examples</h5>
<p><code>set clamp = {x, lo:0, hi:1} -> min{max{x,lo},hi}</code> Define, then call as <code>clamp{0.7}</code>, <code>clamp{1.5, hi:2}</code>, etc.</p>
<p><code>set mix2 = {chain} -> mix{chain, 1/2}</code> A thin wrapper around a node function (as used in <code>lib/nodes.limut</code>).</p>
<p><code>set echo = {time:1/8b, feedback:0.7, max} -> delay{time, feedback:feedback, max:max??max?:time*2}</code> A library effect built from the <code>delay</code> node function (as used in <code>lib/effects.limut</code>).</p>
</div>
<h4 onclick="toggleAccordion('accordion-audio-synths')" class="accordion"> Audio Synths</h4>
<div id="accordion-audio-synths" class="closed">
<p><code>! / stop / none</code> </p>
<p><code>play</code> Play samples. Use letters, symbols and digits 1-4 in the pattern to choose the sample (see below for full list). Note duration defaults to 1/2.</p>
<p><code>perc</code> Play sampled percussion. Similar to the play synth, and uses the same pattern values and samples, but defaults to 1/4 beat duration, and each player has a choke group.</p>
<p><code>pitchedperc</code> Synthesised pitched percussion for kick drums, snare, toms etc. Note that as this synth is not sample based, it only accepts digits in the player pattern, unlike the play synth. The sound is made up of click, hit, body and rattle components. The synth has a number of unique params:</p>
<p class='sub'><code>click={1}</code> The click is the initial impact sound. The main param is the loudness of the click. The default values are shown.</p>
<p class='sub'><code>hit={0,sample:'^',index:1,rate:3/2}</code> The hit is a sample to be played with the initial impact sound. The main param is the loudness of the hit. Sample, index and rate control the sample playback (similar to the play synth). The default values are shown.</p>
<p class='sub'><code>body={1,att:5ms,dec:400ms,freq:55hz,boost:150hz,pitchatt:0ms,pitchdec:50ms,wave:'sine',saturation:0}</code> The body is the resonant, pitched body of the sound. The main param is the loudness of the body. units is the time units for the various envelope attack and decay values. att is the attack time. dec is the decay time. freq is the base frequency in Hz, boost is the initial frequency boost in Hz. pitchatt is the attack time for the pitch sweep. pitchdec is the decay time for the pitch sweep. wave is the waveform to use. saturation is the gain for a tanh saturator applied to the body oscillator. The default values are shown. Default time units for envelopes: seconds.</p>
<p class='sub'><code>body2={0,att:5ms,dec:400ms,freq:55hz,boost:150hz,pitchatt:0ms,pitchdec:50ms,wave:'sine',saturation:0}</code> Second body tone. May be useful for snares and toms etc.</p>
<p class='sub'><code>rattle={1,att:0ms,dec:30ms,rate:1,filter:'lowpass',freq:55hz,boost:205hz,pitchatt:0ms,pitchdec:50ms,q:18}</code> The rattle is a noisy component of the sound. The main param is the loudness of the rattle. units is the time units for the various envelope attack and decay values. att is the attack time. dec is the decay time. Rate is the sample playback rate of the noise sample; adjusting this can provide some additional filtering. freq is the base filter frequency in Hz, boost is the initial filter frequency boost in Hz, pitchatt is the attack time for the filter sweep. pitchdec is the decay time for the filter sweep. Q sets the filter resonance. The default values are shown. . Default time units for envelopes: seconds.</p>
<p><code>bd</code> Preset based on pitchedperc. Provides a basic synthesized kick drum. Note that as this synth is not sample based, it only accepts digits in the player pattern, unlike the play synth. Use sus or dec params to control the duration of the kick. Uses some unique params:</p>
<p class='sub'><code>accent=0</code> Positive values accent the kick making it louder and stronger. Negative values diminish the kick. Default value is derived from the player pattern value and 'add' param.</p>
<p class='sub'><code>tone=0</code> Tone control for the kick. Larger values will open the filters.</p>
<p class='sub'><code>tune=55</code> Base frequency for the kick in Hz. Usually this should be between about 45 and 65 Hz. The pitch{} function can be used to calculate specific frequencies for tuning the kick to the current key; for example <code>tune=pitch{0,oct:2}</code></p>
<p><code>io808</code> TR-808 simulation based on <a href="https://github.com/vincentriemer/io-808">IO-808</a>. Eg <code>p io808 0.9, type='bd'</code> plays a pattern with two bass drum hits, one unaccented then one with maximum accent. Event duration is 1/4 beat (16th note) to correspond to 808 sequencer.</p>
<p class='sub'><code>type='bd'</code> type of 808 sound: 'bd', 'sd', 'oh', 'ch', 'cb', 'cp', 'ma', 'ht', 'mt', 'lt', 'hc', 'mc', 'lc', 'cl', 'rs', 'cy'. The value from the pattern determines the level of accent placed on each event.</p>
<p class='sub'><code>level=1</code> Output level. Used on all types.</p>
<p class='sub'><code>tone=1/2</code> Tone control; used on bd, sd, and cy.</p>
<p class='sub'><code>decay=1/2</code> Decay time; used on bd, cy, and oh.</p>
<p class='sub'><code>snappy=1/2</code> Snappy control for sd.</p>
<p class='sub'><code>tuning=1/2</code> Tuning control for toms and congas ht, mt, lt, hc, mc, and lc.</p>
<p><code>impulse</code> Play an atonal impulse; that is a single pulse of millisecond duration.</p>
<p><code>sample</code> Pitched sample player. Use the 'sample' param, and then use it as a pitched synth. Use the <code>start</code> param to specify the playback start time within the original sample in seconds. Note: if the <code>rate</code> param is set, then this sets the sample playback rate and overrides the <code>value</code> and <code>add</code> params, which are ignored.</p>
<p><code>saw</code> Sawtooth wave preset</p>
<p><code>sine</code> Sine wave preset</p>
<p><code>square</code> Square wave preset</p>
<p><code>tri</code> Triangle wave preset</p>
<p><code>pulse</code> Pulse wave preset</p>
<p><code>wave</code> Synthesizer using a waveform specified by the <code>wave</code> param. Possible values <code>saw, square, sine, triangle, pulse</code></p>
<p><code>dwave</code> Synthesizer preset using multiple detuned waveforms specified by the <code>wave</code> param. Possible values <code>saw, square, sine, triangle, pulse</code></p>
<p><code>dsaw</code> Detuned saw preset - multiple sawtooth waves slightly out of tune for a fuller sound</p>
<p><code>dsquare</code> Detuned square preset - multiple square waves slightly out of tune for a fuller sound</p>
<p><code>dsine</code> Detuned sine pad preset - multiple sine waves slightly out of tune for a fuller sound</p>
<p><code>dtri</code> Detuned tri preset - multiple triangle waves slightly out of tune for a fuller sound</p>
<p><code>dbass</code> Detuned saw bass preset - multiple sawtooth waves slightly out of tune for a fuller sound</p>
<p><code>fmbass</code> Funky FM bass preset</p>
<p><code>ping</code> Sine wave ping preset</p>
<p><code>audiosynth</code> Base type with no defined audionode graph. The play param takes an audionode graph for each note. Note the player freq param is predefined for this player type as the note pitch derived from the pattern and other usual player params (add, oct, scale etc).</p>
<p><code>swell</code> Swell pad - triangle wave</p>
<p><code>fm</code> FM base synth; allows configuration of FM operators and envelopes. Each of up to 6 operators is specified using params <code>op1</code> to <code>op6</code>:</p>
<p class='sub'><code>op1={ratio:5.19,target:3,wave:'saw',depth:0.8,att:0.01,rel:0.1}</code> ratio: frequency ratio for this operator relative to base event frequency. target: the number of the operator that this one should modulate (eg `1` to target `op1`); use 'out' to send this operator output to the synth output. wave: the waveform to use for this operator. Depth: the amount of modulation this operator should apply to the target (note this will be scaled by the note frequency). att/rel simple envelope attack and release for this operator - default time units: beats</p>
<p><code>bell</code> FM generated bell preset</p>
<p><code>glock</code> FM generated glockenspiel preset</p>
<p><code>glass</code> FM glass synth with a chiming sound preset</p>
<p><code>xylo</code> FM xylophone preset</p>
<p><code>piano</code> Sampled piano</p>
<p><code>epiano</code> DX7 FM style electric piano</p>
<p><code>lately</code> FM bass in the style of the "lately bass" </p>
<p><code>ambi</code> Ambient drone preset; multiple sines with varying detunes</p>
<p><code>ethereal</code> FM Ethereal pad preset</p>
<p><code>noise</code> Noise pad. Note pattern value is not used; white noise is produced for all values (uses AudioWorklet so may use more audio render capacity than other synth types).</p>
<p><code>prophet</code> Prophet style preset: pulse wave with lfo controlled pulse-width (uses AudioWorklet so may use more audio render capacity than other synth types)</p>
<p><code>pwm</code> Pulse width modulation synth. A pulse wave with variable pulse width, from pulse to square. Note: uses AudioWorklet so may use more audio render capacity than other synth types. Also note there may be aliasing, so you may want to apply some filtering to cut harsh high frequencies.</p>
<p><code>cutoff</code> Filter cutoff control from 0 to 1.</p>
<p><code>resonance</code> Filter resonance q.</p>
<p class='sub'><code>pwm=1/2</code> Set the pulse width from 0 to 1. The default is 1/2, a square wave (50% duty cycle). values very close to 0 and 1 will produce no sound since the actual pulse width will become vanishingly small.</p>
<p><code>supersaw</code> supersaw lead synth preset; 7 detuned saws</p>
<p><code>external</code> take audio from microphone or line in. Use the <code>track</code> param to specify the track within the stream. If the input signal appears on only one stereo channel (or you only want the signal from one stereo channel), use the <code>channel</code> param to select the channel and force it to mono.</p>
<p class='sub'><code>track=1</code> Select which audio track to use from the input.</p>
<p class='sub'><code>channel=1</code> Select a single audio channel to use from the input.</p>
<p><code>multiwave</code> Synthesizer providing multiple waveform oscillators which can have their amp and detune controlled individually and dynamically. The waves are specified using params <code>wave1</code>, <code>wave2</code> etc:</p>
<p class='sub'><code>wave1={'saw',amp:[0:1]n,detune:wow}</code> The main value is a string giving the waveform to use. amp is a per frame amplitude control. detune is a per frame detune control in semitones.</p>
<p><code>crackle</code> Crackly crackle sounds.</p>
<p><code>noisefloor</code> Provide a slowly varying noise floor.</p>
<p><code>bus</code> Audio mix bus. Plays continuously, can take a pattern but the pattern is ignored. As a result, all bus param values are evaluated per frame. Chords and []e are not valid for bus players. Audio players can use the <code>bus</code> param to choose which bus to mix into (by id). A bus player does not have pitch effects (addc, vib etc), but does have wave effects (compress, drive, fold etc). There is an implicit bus called <code>main</code> that exists at all times, and provides the final mix for all other players and buses. Overrides can be used to set params on the main bus; eg <code>set main echo=1/2</code></p>
</div>
<h4 onclick="toggleAccordion('accordion-visual-synths')" class="accordion"> Visual Synths</h4>
<div id="accordion-visual-synths" class="closed">
<p><code>! / stop / none</code> </p>
<p><code>blank</code> Blank: sets every pixel to the <code>back</code> colour.</p>
<p><code>clouds</code> Moving clouds</p>
<p><code>kal</code> Changing kaleidoscope pattern</p>
<p><code>swirl</code> Psychedelic swirl</p>
<p><code>julia</code> Julia set fractal</p>
<p><code>lines</code> Twisting lines</p>
<p><code>blob</code> Morphing 3D blob</p>
<p><code>streetlight</code> Looking up at the passing streetlights on a night drive</p>
<p><code>grid</code> Square grid</p>
<p><code>glow</code> Additive glow for lights, sparks etc</p>
<p><code>stars</code> Exploding stars for fireworks etc</p>
<p><code>bits</code> Bitwise operations giving fractal patterns</p>
<p><code>xor</code> Bitwise xor with mod, giving changing pixellated patterns</p>
<p><code>gradient</code> Simple gradient in the y direction</p>
<p><code>shadertoy</code> Display a shadertoy synth. Use the <code>id</code> param to specify which shader. Only shaders published with the 'public+api' option are available, others will give error 'Shader not found'. At present, shaders that use textures or multiple channels will also not work.</p>
<p><code>image</code> Display an online image. Use the <code>url</code> param to specify the image url. The image must be served using CORS. by default the image <code>back</code> is transparent.</p>
<p><code>webcam</code> Display video feed from the attached webcam (if present). The browser will ask permission before allowing access to the webcam. Use the <code>device</code> param to sepcify the device as an index into the list of devices, or as part of the device label string (defaults to index 0). When a webcam synth is first used, the console will log the available devices and their indexes and labels. Use the <code>width</code> and <code>height</code> params to specify your ideal camera resolution (defaults to 640x480).</p>
<p class='sub'><code>device</code> Device index or part of the device label string.</p>
<p><code>text</code> Draw and display text. Use the text param; eg <code>text='Hello'</code>. Use <code>\n</code> to split to multiple lines: <code>text='Hello\nWorld'</code>. Use subparams to control the text rendering, eg: <code>text={'Hello',font:'times',size:'144',linesize:0.7,y:1/4,x:2/3,style:'bold italic'}</code>. Text is evaluated only per event, not per frame.</p>
<p><code>buffer</code> Maintain a render target, which other synths can render into. The render target is then drawn to the screen by this synth. Use the <code>buffer</code> param on another synth to direct its output to a <code>buffer</code> synth. Use the <code>rez</code> param on the buffer synth to set the render target texture resolution scale. Use the <code>feedback</code> param to provide video feedback by rendering this buffer on top of itself every frame. The subparams will modify the feedback render.</p>
<p><code>scope</code> Display the current audio waveform</p>
<p><code>scopefft</code> Display the frequency spectrum of the current audio waveform</p>
<p><code>readout</code> Display the current value as a digital display</p>
<p><code>dmx</code> Output to a DMX universe to control lighting fixtures. Requires web serial support to function (Chromium based browsers only currently), and a USB to DMX interface (tested with Enttec OpenDMX). For example, if there are two DMX lights on DMX channels 1 and 8, that each take a master dimmer channel followed by red, green and blue channels, then <code>d dmx, channel=(1,8), set={1,rainbow}</code> will output a rainbow colour to both lights.</p>
<p class='sub'><code>channel</code> Set the base DMX channel number. DMX channels are 1-based, so this should be one or more, never zero.</p>
<p class='sub'><code>set</code> Set DMX channels to the supplied values. For example <code>set={0.1,0.2}</code> sets the first channel to 0.1 and the second channel to 0.2. The channel offsets can also be supplied explicitly, eg <code>set={0:0.1, 1:0.2}</code></p>
<p class='sub'><code>lights</code> Add values into DMX channel(s). Can be used in the same player or another to add value(s) to whatever is already set.</p>
<p class='sub'><code>addl</code> Add values into DMX channel(s).</p>
<p class='sub'><code>mul</code> Multiply values into DMX channel(s).</p>
<p class='sub'><code>min</code> Take the minimum of the supplied value(s) with the current DMX channel value(s).</p>
<p class='sub'><code>max</code> Take the maximum of the supplied value(s) with the current DMX channel value(s).</p>
</div>
<h4 onclick="toggleAccordion('accordion-event-params')" class="accordion"> Common Event Params</h4>
<div id="accordion-event-params" class="closed">
<p><code>dur</code> Pattern step duration. Timevars, random vars and index vars can be used to give variation in duration. Chords cannot be used with the dur param. Default time units: beats.</p>
<p><code>delay</code> Event start time offset. Default time units: beats</p>
<p class='sub'><code>delay={1/2,add:2}</code> subparams on delay will be used to override the event values. In the example given, the <code>add</code> param of the delayed event will be set to 2, but any params can be overridden this way. This is most useful with chords of delay values, as it allows individual delayed events to change their properties.</p>
<p><code>stutter</code> Split each event into multiple events spaced evenly within the same time period. Eg with <code>stutter=2</code>, an event starting at time 0 with a duration of 1 will be split into two events of duration 1/2, starting at 0 and 1/2. Stutter of 0 or 1 has no effect and is the default. Stutter is rounded down to the nearest integer value.</p>
<p class='sub'><code>stutter={2,dur:1/4}</code> the <code>dur</code> subparam forces the time between stutter events rather than dividing the original event's duration evenly. Default time units: beats, eg <code>stutter={2,dur:1/4s}</code> for quarter-second spacing.</p>
<p class='sub'>Any other subparam can be supplied and will be applied to the extra stutter events only — the first event keeps its original params. Eg <code>stutter={2,amp:1/4}</code> plays the first note at normal amp and the second at <code>amp=1/4</code>, useful for echo-like tails.</p>
<p><code>swing</code> Amount to swing alternating 1/4 beats, as a Linn LM-1 style percentage from <code>50</code> (no swing) to <code>66</code> (perfect triplet swing) to <code>75</code> (maximum dotted note swing). You can set swing for all players at once using (eg) <code>set * swing=60</code></p>
<p class='sub'><code>swing={66,period:1/2}</code> The period to apply the swing. Defaults to 1/4 of a beat (suitable for house music).</p>
<p><code>amp</code> Player amplitude control. For audio players, this defaults to the event <code>vel</code> so that velocity controls the player volume.</p>
<p><code>sus</code> Sustain time. Note the 'sustain' in an ADSR envelope sets the sustain level, however this param sets the sustain time. The default is time required after attack and decay to take the note to the end of the duration. Default time units: beats.</p>
<p><code>rate</code> Playback rate for 'play' samples, animation rate for visuals</p>
<p><code>voice</code> READ ONLY param. This param is set to the voice index of an individual event within a chord. So for example: <code>p ping 0, add=(0,2)</code>. Here, there are two events within the chord, with <code>add</code> values of 0 and 2. The <code>voice</code> values for these events will be 0 and 1, since the <code>voice</code> increments. This can be used to change other values based on the voice index within the chord.</p>
<p><code>time</code> READ ONLY param. The current time in beats this event has been playing for.</p>
<p><code>idx</code> READ ONLY param. The pattern index of this event. The pattern index counts through the pattern, then resets when the pattern repeats.</p>
<p><code>exists</code> READ ONLY param. One if the player is defined, even if its not currently playing any event.</p>
<p><code>playing</code> READ ONLY param. One if the player exists and is currently playing one or more events.</p>
<p><code>pulse</code> READ ONLY param. A value that rises and falls as a note plays on the player. If multiple notes are playing, the value will be a chord. The value is pre-multiplied by the note velocity (the <code>vel</code> param).</p>
<p><code>player</code> READ ONLY param. The name of the player currently playing. For a follow player, will be the name of the follow player (not the player it's following).</p>
</div>
<h4 onclick="toggleAccordion('accordion-audio-params')" class="accordion"> Audio Params</h4>
<div id="accordion-audio-params" class="closed">
<p><code>vel</code> Event velocity. Default is 3/4. By default velocity controls the event amp (volume) and usually the cutoff or brightness of the sound (where applicable). <code>vel</code> is set per event by the gamepad or midi player, but can also be set or overridden by player params.</p>
<p><code>add</code> Amount to add onto event scale degree, in degrees. Evaluated per event only.</p>
<p class='sub'><code>add={0,#:1}</code> Sharpen the scale degree (add a given number of semitones)</p>
<p class='sub'><code>add={0,b:1}</code> Flatten the scale degree (subtract a given number of semitones)</p>
<p><code>addc</code> Amount to add onto event pitch, in semitones. Evaluated per frame, and accepts fractional values, so <code>addc=[0:12]e</code> will slide the note from the starting pitch smoothly up a whole octave over the course of the note.</p>
<p><code>oct</code> Octave; middle C is in octave 4</p>
<p><code>envelope</code> Specify the envelope type to use: <code>'full'</code> (ADSR), <code>'simple'</code> (ADR), <code>'organ'</code> (ASR full volume while on like an organ), <code>'pad'</code> (uses a cosine roll on/off so consecutive notes maintain constant volume), <code>'linpad'</code> (uses a linear roll on/off, a better crossfade when the source is identical (including phase) between events), <code>'percussion'</code> (R - instant attack). Or, specify an envelope directly as an expression, for example <code>envelope=[1:!300ms,0]e@s</code></p>
<p><code>att</code> Attack time. Default time units: beats.</p>
<p><code>dec</code> Decay time. Default time units: beats.</p>
<p><code>sus</code> Sustain time. Note the 'sustain' in an ADSR envelope sets the sustain level, however this param sets the sustain time. The default is time required after attack and decay to take the note to the end of the duration. Default time units: beats.</p>
<p class='sub'><code>sus={level:1/6}</code> Set the amplitude level for sustain. Note the 'sustain' in an ADSR envelope is the level, so it is this value not the main 'sus' value (which is actually the sustain time). Default: 0.8.</p>
<p><code>rel</code> Release time. Default time units: beats.</p>
<p><code>wave</code> For audio synths that use a waveform, specify which waveform to use, from this list:
<code>sine</code>,
<code>square</code>,
<code>sawtooth</code> (can also use <code>saw</code> for convenience),
<code>triangle</code> (can also use <code>tri</code> for convenience),
<code>pulse</code>,
<code>ah</code>,
<code>bah</code>,
<code>bass</code>,
<code>'bass-amp360'</code>,
<code>'bass-fuzz'</code>,
<code>'bass-fuzz-2'</code>,
<code>'bass-sub-dub'</code>,
<code>'bass-sub-dub-2'</code>,
<code>brass</code>,
<code>'brit-blues'</code>,
<code>'brit-blues-driven'</code>,
<code>buzzy</code>,
<code>'buzzy-2'</code>,
<code>celeste</code>,
<code>'chorus-strings'</code>,
<code>'dissonant-1'</code>,
<code>'dissonant-2'</code>,
<code>'dissonant-piano'</code>,
<code>'dropped-saw'</code>,
<code>'dropped-square'</code>,
<code>'dyna-ep-bright'</code>,
<code>'dyna-ep-med'</code>,
<code>ee</code>,
<code>ethnic</code>,
<code>full</code>,
<code>'full-2'</code>,
<code>'guitar-fuzz'</code>,
<code>harsh</code>,
<code>'mkl-hard'</code>,
<code>noise</code>,
<code>o</code>,
<code>ooh</code>,
<code>organ</code>,
<code>'organ-2'</code>,
<code>piano</code>,
<code>'pop-ahhh'</code>,
<code>pulse</code>,
<code>'putney-wavering'</code>,
<code>tb303</code>,
<code>throaty</code>,
<code>trombone</code>,
<code>'twelve-optines'</code>,
<code>'twelve-string-guitar'</code>,
<code>'warm-saw'</code>,
<code>'warm-square'</code>,
<code>'warm-triangle'</code>,
<code>wurlitzer</code>,
<code>'wurlitzer-2'</code>
Note that values with hyphens must be enclosed in quotes. In addition, there may be a performance problem with using dynamic (per frame) pitch sweeps using these waveforms. This penalty does not apply to the basic waveforms (sine, sawtooth, triangle, square).
</p>
<p><code>detune</code> Amount of detune in semitones</p>
<p><code>lpf</code> Low pass filter frequency. Default time units: Hertz</p>
<p class='sub'><code>lpf={400,q:20}</code> Low pass filter resonance. 10 is approximately the transition where resonance starts to kick in. Default: 5.</p>
<p class='sub'><code>lpf={400,poles:4}</code> Filter poles. Default is a 2 pole filter giving 12 dB/octave. Alternatively, specify 4 for a Moog-like 4 pole filter giving 24 dB/octave.</p>
<p><code>hpf</code> High pass filter frequency. Default time units: Hertz</p>
<p class='sub'><code>hpf={400,q:20}</code> High pass filter resonance. Default: 5.</p>
<p class='sub'><code>hpf={400,poles:4}</code> Filter poles. Default is a 2 pole filter giving 12 dB/octave. Alternatively, specify 4 for a Moog-like 4 pole filter giving 24 dB/octave.</p>
<p><code>bpf</code> Band pass filter frequency. Default time units: Hertz.</p>
<p class='sub'><code>bpf={400,q:20}</code> Band pass filter resonance. Default: 1.</p>
<p class='sub'><code>bpf={400,poles:4}</code> Filter poles. Default is a 2 pole filter giving 12 dB/octave. Alternatively, specify 4 for a Moog-like 4 pole filter giving 24 dB/octave.</p>
<p><code>bpf1</code> Multiple, parallel bandpass filters are available using params <code>bpf1</code>, <code>bpf2</code> etc.</p>
<p><code>nf</code> Notch filter frequency. Default time units: Hertz</p>
<p class='sub'><code>nf={400,q:20}</code> Notch filter resonance. Default: 1.</p>
<p><code>apf1</code> All pass filter frequency. Default time units: Hertz. Multiple allpass filters can be specified with params <code>apf1</code>, <code>apf2</code> etc. They will operate in parallel so their outputs sum, allowing phase cancellation.</p>
<p class='sub'><code>apf={400,q:2}</code> Allpass filter resonance. Default: 1.</p>
<p><code>psf</code> Phaser stage filter consisting of two allpass filters in parallel. Multiple phaserstage filters can be specified with params <code>psf1</code>, <code>psf2</code> etc. The phaserstages will operate in series, allowing more complex phasers to be built up with multiple peaks and troughs in the frequency spectrum. Default units: Hertz</p>
<p class='sub'><code>psf={f1:300,f2:2300,q:0.7}</code> f1 and f2 are the frequencies in Hertz of the two allpass filters. Sweep these dynamically for the swirling phaser effect. q is filter resonance. Default: 1.</p>
<p><code>low</code> Low shelf gain. Eg <code>low=-6dB</code> will act like a gain of 1/2 for the low frequencies. Must specify the value with the <code>dB</code> unit, or use a relative gain value instead.</p>
<p class='sub'><code>low={-8db,freq:400}</code> Low shelf cutoff frequency. Default: 200Hz. Default units: Hertz</p>
<p><code>mid</code> Mid gain. Eg <code>mid=-6dB</code> will act like a gain of 1/2 for the mid frequencies. Must specify the value with the <code>dB</code> unit, or use a relative gain value instead.</p>
<p class='sub'><code>mid={-8db,freq:400}</code> Mid cutoff frequency. Default: 600Hz. Default units: Hertz</p>
<p class='sub'><code>mid={-8db,q:10}</code> Mid q defines the width of the mid frequency band; low q is wide. Default: 5</p>
<p><code>high</code> High shelf gain. Eg <code>high=-6dB</code> will act like a gain of 1/2 for the high frequencies. Must specify the value with the <code>dB</code> unit, or use a relative gain value instead.</p>
<p class='sub'><code>high={-8db,freq:400}</code> High shelf cutoff frequency. Default: 1100Hz. Default units: Hertz</p>
<p><code>chop</code> Apply a tremolo effect that chops the audio signal, eg <code>chop=2cpb</code> chops the signal twice per beat. Default time units: cycles per beat</p>
<p class='sub'><code>chop={2,wave:triangle}</code> chops twice per beat with a triangle waveform. The default waveform is sine; the options are sine, square, triangle, saw.</p>
<p class='sub'><code>chop={4,mix:1/4}</code> Mix subparam controls dry/wet mix. 0 for dry only, 1 for wet only. default: 1</p>
<p><code>ring</code> Apply ring modulation at the given frequency, eg <code>ring=32hz</code> apply ring modulation at 32Hz. Default time units: hz</p>
<p class='sub'><code>ring={32,wave:saw}</code> 32Hz ring modulation with a sawtooth waveform. The default waveform is triangle; the options are sine, square, triangle, saw.</p>
<p class='sub'><code>ring={32,mix:1/4}</code> Mix subparam controls dry/wet mix. 0 for dry only, 1 for wet only. default: 1</p>
<p><code>sample</code> With 'play' synth: number: choose which sample set to use. With 'sample' synth: string: url of online audio file to play (note: server must support cross origin requests for the file)</p>
<p class='sub'><code>sample={32,pitch:261.6}</code> Specify the original pitch of the sample (eg default is 261.6 Hz for C4). Default time units: hz</p>
<p><code>start</code> For the 'sample' synth, specify the playback start time within the sample. Default time units: seconds.</p>
<p><code>compress</code> Compression ratio, or the reduction in volume for signals above the compression threshold. A ratio of zero disables compression.</p>
<p class='sub'><code>compress={12,gain:2}</code> Input gain; gain amp to apply to the signal before compression is applied</p>
<p class='sub'><code>compress={12,threshold:-40dB}</code> Threshold at which the compression ratio kicks in. Default is <code>-50dB</code></p>
<p class='sub'><code>compress={12,knee:10dB}</code> the 'knee' is a softening of the compression curve, so that there is no sudden changeover at the threshold. A value of <code>0dB</code> disables the knee and gives a sudden changeover. Other values are the range over which the knee should apply. Default is <code>40dB</code>.</p>
<p class='sub'><code>compress={12,att:0.1}</code> Compressor attack time. The attack time is the time it takes for compression to 'kick in' once a signal crosses the threshold. Default is 0.01 (or 10ms). Default time units: seconds.</p>
<p class='sub'><code>compress={12,rel:0.2}</code> Compressor release time. The release time is the time it takes for compression to 'go away' once a signal falls back below the threshold. Default is 0.25. Default time units: seconds.</p>
<p><code>noisify</code> noisify: distort the signal into noise</p>
<p class='sub'><code>noisify={12,gain:2}</code> Input gain; gain amp to apply to the signal before noisify is applied</p>
<p class='sub'><code>noisify={1,mix:1/4}</code> Mix subparam controls dry/wet mix. 0 for dry only, 1 for wet only. default: 1</p>
<p><code>fold</code> distort the signal by boosting then folding the overdriven part of the waveform</p>
<p class='sub'><code>fold={12,gain:2}</code> Input gain; gain amp to apply to the signal before fold is applied</p>
<p class='sub'><code>fold={1,mix:1/4}</code> Mix subparam controls dry/wet mix. 0 for dry only, 1 for wet only. default: 1</p>
<p><code>clip</code> boost the signal then apply hard clipping</p>
<p class='sub'><code>clip={12,gain:2}</code> Input gain; gain amp to apply to the signal before clip is applied</p>
<p class='sub'><code>clip={1,mix:1/4}</code> Mix subparam controls dry/wet mix. 0 for dry only, 1 for wet only. default: 1</p>
<p><code>drive</code> overdrive by boosting the signal then applying soft clipping. Low values (eg 1/32, 1/16) give a gentle overdrive. Mid values (eg 1/8, 1/4) give a distortion effect. Higher values (eg 1/2, 1) give a full on fuzz.</p>
<p class='sub'><code>drive={12,gain:2}</code> Input gain; gain amp to apply to the signal before drive is applied</p>
<p class='sub'><code>drive={1,mix:1/4}</code> Mix subparam controls dry/wet mix. 0 for dry only, 1 for wet only. default: 1</p>
<p><code>bits</code> bit crush effect; value is number of bits. 1 bit is very distorted to (eg) 32 bits is relatively clean. 0 disables the effect.</p>
<p class='sub'><code>bits={12,gain:2}</code> Input gain; gain amp to apply to the signal before bits is applied</p>
<p class='sub'><code>bits={1,mix:1/4}</code> Mix subparam controls dry/wet mix. 0 for dry only, 1 for wet only. default: 1</p>
<p><code>suck</code> suck smaller amplitudes even smaller, but leave large amplitudes alone; value is a limit amplitude: when the waveform is within this limit, it is scaled down. This can provide an unusual form of distortion, or for samples with a long tail, can give a 'gated' effect.</p>
<p class='sub'><code>suck={12,gain:2}</code> Input gain; gain amp to apply to the signal before suck is applied</p>
<p class='sub'><code>suck={1,mix:1/4}</code> Mix subparam controls dry/wet mix. 0 for dry only, 1 for wet only. default: 1</p>
<p><code>root</code> override root for this player; used instead of main root for this player only. </p>
<p><code>scale</code> override scale for this player; set to one of these strings:
<code>chromatic</code>,
<code>major</code>,
<code>majorpentatonic</code>,
<code>pentatonic</code>,
<code>penta</code>,
<code>minor</code>,
<code>aeolian</code>,
<code>minorpentatonic</code>,
<code>minorpenta</code>,
<code>mixolydian</code>,
<code>melodicminor</code>,
<code>melodicmajor</code>,
<code>harmonicminor</code>,
<code>harmonicmajor</code>,
<code>dorian</code>,
<code>dorian2</code>,
<code>diminished</code>,
<code>egyptian</code>,
<code>yu</code>,
<code>zhi</code>,
<code>phrygian</code>,
<code>prometheus</code>,
<code>indian</code>,
<code>locrian</code>,
<code>locrianmajor</code>,
<code>lydian</code>,
<code>lydianminor</code>,
<code>hungarianminor</code>,
<code>romanianminor</code>,
<code>chinese</code>,
<code>wholetone</code>,
<code>halfwhole</code>,
<code>wholehalf</code>,
<code>bebopmaj</code>,
<code>bebopdorian</code>,
<code>bebopdom</code>,
<code>bebopmelmin</code>,
<code>blues</code>,
<code>minmaj</code>,
<code>susb9</code>,
<code>lydianaug</code>,
<code>lydiandom</code>,
<code>melmin5th</code>,
<code>halfdim</code>,
<code>altered</code>,
</p>
<p><code>vib</code> vibrato rate. Default time unit: cycles per beat</p>
<p class='sub'><code>vib={2,depth:1}</code> vibrato depth in semitones (default 0.4)</p>
<p class='sub'><code>vib={2,delay:1}</code> delay time before vibrato starts (default 1/2). Default time units: beats</p>
<p><code>glide</code> Glide from one note to the next (portamento). When a note plays with glide set, if there is a previous note playing on the same player in the same voice, then both notes will glide in pitch from the old note's pitch to the new. <code>glide=1/3</code> means it takes 1/3 of a beat to glide from the old note to the new. Default value is 0 (no glide). Default time units: beats.</p>
<p class='sub'><code>glide={1/3,curve:4}</code> glide curve. Zero means no curve, or a linear frequency change. Positive curve means the frequency moves quickly to the target, then slows down as it approaches. Default is 1.</p>
<p><code>pan</code> pan from -1 (left) to 1 (right). default: 0</p>
<p><code>mono</code> Force a signal to mono: the input signal appears equally in both left and right channels</p>
<p><code>choke</code> Set a choke group. Notes played with a choke group will cut off other notes that are already playing if they have the same choke group. The choke group can be a string, and can apply across multiple players.</p>
<p><code>echo</code> Echo time delay. Default time unit: beats.</p>
<p class='sub'><code>echo={1,feedback:0.8}</code> Echo feedback gain, 0 to 1, default 0.35. Higher value means the echo persists for longer.</p>
<p class='sub'><code>echo={1,max:2}</code> Echo max time delay. Only valid for bus echo. The bus echo time can be varied, but cannot be larger than this. Defaults to either 1 beat, or the initial value of the delay time, whichever is larger. Default time unit: beats.</p>
<p><code>chorus</code> Strength of lfo-delay based stereo chorus effect.</p>
<p class='sub'><code>chorus={1,mix:1/4}</code> Mix subparam controls dry/wet mix. 0 for dry only, 1 for wet only. default: 1</p>
<p><code>phaser</code> LFO frequency for phaser phase sweep effect. Default time units: cycles per beat.</p>
<p class='sub'><code>phaser={1/3,mix:1/4}</code> Mix subparam controls dry/wet mix. 0 for dry only, 1 for wet only. default: 1</p>
<p><code>flanger</code> LFO frequency for flanger effect. Default time units: cycles per beat.</p>
<p class='sub'><code>flanger={1/3,mix:1/4}</code> Mix subparam controls dry/wet mix. 0 for dry only, 1 for wet only. default: 1</p>
<p><code>room</code> freeverb room size.</p>
<p class='sub'><code>room={2,hpf:300}</code> HPF subparam Sets the cutoff frequency for a high pass filter placed before the freeverb. 0 disables the highpass filter altogether. default: 0. Default time units: hz</p>
<p class='sub'><code>room={2,mix:1/4}</code> Mix subparam controls dry/wet mix. 0 for dry only, 1 for wet only. default: 1/2</p>
<p><code>reverb</code> Convolution reverb duration. The value is a time in beats that the reverb tail will last for. Default time unit: beats.</p>
<p class='sub'><code>reverb={2,curve:3}</code> Decay curve power of the reverb tail. 1 is a linear decay, larger values make the tail decay faster. default: 5</p>
<p class='sub'><code>reverb={2,hpf:300}</code> HPF subparam Sets the cutoff frequency for a high pass filter placed before the reverb. 0 disables the highpass filter altogether. default: 0. Default time units: hz</p>
<p class='sub'><code>reverb={2,mix:1/4}</code> Mix subparam controls dry/wet mix. 0 for dry only, 1 for wet only. default: 1/2</p>
<p><code>freq</code> READ ONLY param. This param is set by all tonal synths, to the frequency in Hz of the note being played. This value can then be read for other purposes; eg <code>lpf=this.freq*2</code> will set the low pass cutoff frequency to double the note frequency.</p>
<p><code>bus</code> id of the bus that this player should mix to. If the sepcified player does not exist, this player will be silent. If the bus param is not specified, this player will be mixed to the global <code>main</code> bus.</p>
</div>
<h4 onclick="toggleAccordion('accordion-visual-params')" class="accordion"> Visual Params</h4>
<div id="accordion-visual-params" class="closed">
<p><code>add</code> Amount to add onto pattern value</p>
<p><code>zorder</code> order in which to draw visual synths; defaults to the 1/1000th of the source code line number for the player, so that visuals draw strictly in the order they appear in the source code; however, this param can be used to override this and force specific visuals to the front or rear of the draw order.</p>
<p><code>fade</code> brightness/transparent fadeout</p>
<p><code>time</code> time value to use in the shader. If this is set, the <code>rate</code> and <code>sway</code> params have no effect. Default time unit: beats.</p>
<p><code>rate</code> the rate that time should progress in the shader. If the <code>time</code> param is set, this has no effect</p>
<p><code>pulse</code> extent to which the audio signal affects the value passed to visual synths</p>
<p><code>sway</code> extent to which the audio signal affects the time passed to visual synths</p>
<p><code>loc</code> position and size. The visual coordinate system runs from (-1,-1) in the bottom left of the screen to (1,1) in the top right. x and y define the centre of the visual, and w and h are the full width and height; eg <code>{x:0,y:0,w:2,h:2}</code> covers the full screen.</p>
<p><code>window</code> display the only part of the shader image appropriate to the location of the tile on the screen. This way, a tile moved around the screen will act like a window onto the overall shader image.</p>
<p><code>scroll</code> scroll the shader; default: <code>{x:0,y:0}</code></p>
<p><code>repeat</code> repeat a section of the shader image in both directions. Value is the size of the area to be repeated.</p>
<p class='sub'><code>repeat={1/2,x:0.1,y:-0.05}</code> x/y offsets to apply to the area of the shader image being repeated.</p>
<p><code>zoom</code> zoom the shader; default: <code>{x:1,y:1}</code></p>
<p><code>rotate</code> rotate the shader; angle in full rotations so 1/2 is 180 degrees; default: <code>0</code></p>
<p><code>mirror</code> mirror the shader; number of mirror planes to apply; default: <code>0</code></p>
<p class='sub'><code>mirror={10,rotate:1/4}</code> Rotation offset (0-1) to apply to the mirror planes. Defaults to 0.</p>
<p class='sub'><code>mirror={10,fan:1}</code> fan out angle to apply to mirror segments, so each segment is taken from an incrementing portion of the original image. A fan of 1 moves each next segment by the size of one segment. Defaults to 0.</p>
<p><code>fore</code> foreground colour; eg <code>{r:0,g:1,b:0,a:1}</code> for green or <code>#fa0f</code> for orange.</p>
<p><code>mid</code> middleground colour; eg <code>{r:0,g:1,b:0,a:1}</code> for green or <code>#fa0f</code> for orange. If not specified, defaults to midway between fore and back.</p>
<p><code>back</code> background colour; eg <code>{r:0,g:1,b:0,a:1}</code> for green or <code>#00ff</code> for orange.</p>
<p><code>pixellate</code> number of pixels to pixellate to in x direction, or 0 to disable pixellation</p>
<p class='sub'><code>pixellate={10,y:20}</code> number of pixels to pixellate to in y direction, or same as x if not present.</p>
<p><code>perspective</code> perspective warp to apply to shader (negative to invert), or 0 to disable</p>
<p class='sub'><code>perspective={-1,shade:1/2}</code> amount of darkening shade to apply to the part of the image 'in the distance'.</p>
<p><code>tunnel</code> tunnel warp to apply to shader, or 0 to disable. Applies a slitscan type warp, where scrolling in the x direction will scroll the original shader through the tunnel.</p>
<p><code>ripple</code> Apply a ripple warp to the shader, to give the effect of waves of image distortion rippling out from the centre of the shader.</p>
<p class='sub'><code>ripple={1,scale:1/4}</code> scale (size) of ripples. Defaults to 1.</p>
<p><code>additive</code> add this shaders output to those beneath instead of blending</p>
<p><code>blend</code> set the blend mode which defines how this shaders output interacts with the color already present underneath. Possible values: <code>additive subtractive average multiply invert min max</code></p>
<p><code>monochrome</code> make the shader output monochrome; 0 for normal, 1 for monochrome</p>
<p><code>vignette</code> fade out the visual around the edges. The value controls the shape.</p>
<p class='sub'><code>vignette={1/2,aspect:4/3}</code> aspect ratio of vignette effect. Defaults to 1.</p>
<p class='sub'><code>vignette={1,cutoff:0.95}</code> cutoff for vignette; lower values provide a more gradual fade around the edges. Defaults to 0.9.</p>
<p><code>vhs</code> Apply a VHS tape effect, including colour modification, horizontal bars, wobble, and noise.</p>
<p><code>recol</code> recolour the shader. Set to <code>oil</code> for oil film colours, <code>hue</code> for a hue spectrum, <code>fire</code> for a flame effect, <code>sunset</code> for dusk colours, <code>neon</code> for neon megenta and cyan, <code>titanium</code> for titanium anodisation colours</p>
<p><code>contrast</code> apply a power based contrast curve. Default is zero meaning no contrast curve applied.</p>
<p><code>buffer</code> send the output of this synth to a buffer player. For example, <code>buffer=vb</code> makes this synth render to the synth with id <code>vb</code>, which must be a synth of type <code>buffer</code>. The buffer synth can then render itself to the screen to display the output.</p>
<p><code>rez</code> only for a <code>buffer</code> synth: sets the render target resolution scaling. For example, a <code>rez</code> of <code>1</code> will make a render target texture that is identical width and height to the display screen canvas. Default value is 1/2.</p>
<p><code>feedback</code> only for a <code>buffer</code> synth: use video feedback by rednering the buffer onto itself every frame. The subparams control that rendering. Any visual params can be used as <code>feedback</code> subparams. For example <code>feedback={zoom:1.01}</code> will render the feedback slightly zoomed, giving a classic video feedback effect.</p>
</div>
<h4 onclick="toggleAccordion('accordion-main-vars')" class="accordion"> Main Vars</h4>
<div id="accordion-main-vars" class="closed">
<p>Main vars can be set, but not read.</p>
<p><code>bpm</code> Beats per minute. Value resets unless set every time the code is updated.</p>
<p><code>beat.readouts</code> Set the beat counts to use for the readouts; eg <code>beat.readouts=(3,12)</code> will show two beat counters, one that counts in 3's (for a waltz), and another that counts to 12 (for 4 bars of a waltz). There cannot be more than 3 readouts. The default is <code>(12,16,32)</code></p>
<p><code>scale</code> Scale eg minor, major, chromatic, majorpentatonic, lydian etc etc. Value resets unless set every time the code is updated.</p>
<p><code>root</code> Main root pitch offset; default <code>0</code> roots the pitches on middle c; <code>1</code> pitches up by one semitone etc. This is fractional, so can be used to 'nudge' the tuning to match other instruments; eg <code>root=0.135</code> </p>
</div>
<h4 onclick="toggleAccordion('accordion-predefined-vars')" class="accordion"> Predefined Vars</h4>
<div id="accordion-predefined-vars" class="closed">
<p>Predefined vars are predefined values that may be useful as shortcuts when live coding.</p>
<p><code>time</code> Time, counted in beats (including fractions of a beat)</p>
<p><code>drop6_2</code> Predefined time var: equivalent to <code>[1,0]t[6.2]</code>. These are all the predefined drops: drop6_2, drop7_1, drop12_4, drop14_2, drop15_1, drop24_8, drop28_4, drop30_2, drop31_1, drop56_8, drop60_4, drop62_2, drop63_1</p>
<p><code>tile_full</code> For <code>loc</code> visual param. Predefined loc param map to cover the full screen: equivalent to <code>{x:0,y:0,w:1,h:1}</code>. Other predefined locations: tile_tl/tr/bl/br/m, tile_h1/2/3/4/5, tile_v1/2/3/4/5</p>
<p><code>fullscreen</code> For <code>loc</code> visual param. Tile covering the full screen</p>
<p><code>tile_random</code> For <code>loc</code> visual param. Tile in a random location</p>
<p><code>tile_rand</code> For <code>loc</code> visual param. Tile in a random location</p>
<p><code>sparkle</code> For <code>loc</code> visual param. Small tile in a random location</p>
<p><code>droplet</code> For <code>loc</code> visual param. Small tile in a random location, then falling down the screen</p>
<p><code>spark</code> For <code>loc</code> visual param. Small tile flying outwards</p>
<p><code>gravity</code> For <code>loc</code> visual param. Accelrating motion downwards. Best combined with other values; eg <code>spark+gravity</code></p>
<p><code>firefly</code> For <code>loc</code> visual param. Random motion like a flying insect</p>
<p><code>transparent</code> For colour visual params. Predefined colour. Others: black, darkgray, gray, lightgray, white, red, orange, yellow, green, blue, indigo, violet, neonpink, neongreen</p>
<p><code>random</code> For colour visual params. Random colour</p>
<p><code>rainbow</code> For colour visual params. Colour changing through the rainbow</p>
<p><code>tg</code> Predefined time var: trance gate signal. Flips on/off every quarter beat.</p>
<p><code>wow</code> Predefined time var: Randomly but smoothly varying signal, good for simulating analog 'wow' pitch distortion; eg <code>addc=wow</code></p>
</div>
<h4 onclick="toggleAccordion('accordion-controls')" class="accordion"> User Input</h4>
<div id="accordion-controls" class="closed">
<p><code>gamepad{}</code> Take input from an external gamepad controller. When called with no args, it will log inputs to the console to help identify which gamepad control is on which button or axis number. Clicking the left and right sticks locks the stick values in place, allowing the stick to be released without losing the locked position. Click again to unlock, or, after 2 seconds, any movement of the stick away from the centre will also unlock.</p>
<p class='sub'><code>gp{}</code> <code>gp</code> is an alias for <code>gamepad</code> for easier access.</p>
<p class='sub'><code>gamepad{1}</code> Take input from axis 1 on the gamepad. Range -1 to 1 based on axis value. Defaults to gamepad 0.</p>
<p class='sub'><code>gamepad{2,1}</code> Take input from axis 2 on gamepad 1. Range -1 to 1 based on axis value.</p>
<p class='sub'><code>gamepad{button:0}</code> Take input from button 0 on the gamepad. Range 0 to 1 based on button press value. Defaults to gamepad 0.</p>
<p class='sub'><code>gamepad{axis:1}</code> Take input from axis 1 on the gamepad. Range -1 to 1 based on axis value. Defaults to gamepad 0.</p>
<p class='sub'><code>gamepad{pad:1}</code> Take input from gamepad 1. Defaults to axis 0.</p>
<p class='sub'><code>gamepad{'lsh'}</code> Take input from the left stick, horizontal axis, mapped to -1 to 1. ls is left stick, rs is right stick, then h/v for horizontal/vertical axis.</p>
<p class='sub'><code>gamepad{'lsl'}</code> Take input from the left stick, left direction, mapped to 0 to 1. ls is left stick, rs is right stick, then u/d/l/r for the directions.</p>
<p class='sub'><code>gamepad{'lsud'}</code> Take input from the left stick, up or down direction, mapped to 0 to 1. ls is left stick, rs is right stick, then ud and du both mean up or down; lr and rl mean left or right.</p>
<p class='sub'><code>gamepad{'lsx'}</code> Take input from the left stick, radially out from the centre, from to 0 to 1. ls is left stick, rs is right stick.</p>
<p class='sub'><code>gamepad{'lt'}</code> Take input from the left trigger, mapped to 0 to 1. lt is left trigger, rt is right trigger.</p>
<p class='sub'><code>gp.lsr</code> Shorthand for <code>gamepad{'lsr'}</code> for easier access. Same for other named axes.</p>
<p><code>midi{}</code> Take input from an external midi controller. When called with no args, it will log inputs to the console to help identify which midi control is on which port, channel, and control/note number.</p>
<p class='sub'><code>midi{70}</code> Take input from control 70 (or note 70 if there is no control 70). Range 0 to 1 based on controller value or velocity and aftertouch. Defaults to port 0 and channel 0.</p>