very wip
This commit is contained in:
678
notes
678
notes
@@ -7,7 +7,7 @@
|
|||||||
"steps": [
|
"steps": [
|
||||||
{
|
{
|
||||||
"active": true,
|
"active": true,
|
||||||
"script": "< < c5 c1 > m3 M3 m6 > note\n\"sine\" sound\n0.2 decay @",
|
"script": "0.2 0.9 rand gain 0.2 decay\n0.1 dur 1 4 rand fm 0.5 fmh\n\"tri\" < << c3 c2 >> 4 ! g3 > note sound @",
|
||||||
"source": null
|
"source": null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -25,6 +25,340 @@
|
|||||||
"script": "",
|
"script": "",
|
||||||
"source": 0
|
"source": 0
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "0.2 0.9 rand gain 0.2 decay\n0.1 dur 1 4 rand fm 0.5 fmh\n0.5 0.9 rand verb \n< << c3 f3 >> 4 ! eb3 M3 > note \"tri\" sound @",
|
||||||
|
"source": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"length": 8,
|
||||||
|
"speed": "Normal",
|
||||||
|
"name": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "\"ikick\" sound 2 gain @",
|
||||||
|
"source": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"length": 4,
|
||||||
|
"speed": "Normal",
|
||||||
|
"name": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "\"hh\" sound 0.5 comb 400 combfreq @\n4 scale!\n{\n\"noise\" sound 0.05 dur 0.0 1.0 rand gain 0.05 decay 1 100 rand @\n} 2 div for",
|
||||||
|
"source": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "<< \"hh\" 4 ! \"crbongo\" >> sound @\n{ \"snare\" sound 0.2 dur 0.1 decay 200 freq @ } 2 every ?",
|
||||||
|
"source": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"active": true,
|
||||||
|
"script": "",
|
||||||
|
"source": 0
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"active": true,
|
"active": true,
|
||||||
"script": "",
|
"script": "",
|
||||||
@@ -174,7 +508,7 @@
|
|||||||
"steps": [
|
"steps": [
|
||||||
{
|
{
|
||||||
"active": true,
|
"active": true,
|
||||||
"script": "",
|
"script": " {\n {\n | eb3 g3 bb3 c4 | note 0.1 decay 0.1 dur \"tri\" sound\n 0.5 fmh 0.5 delay 4.5 delaytime 0.75 delayfeedback\n 2 fm 0.9 verb 4 orbit @\n } 4 every ? \n} 4 stack for",
|
||||||
"source": null
|
"source": null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -333,341 +667,7 @@
|
|||||||
"source": null
|
"source": null
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"length": 16,
|
"length": 4,
|
||||||
"speed": "Normal",
|
|
||||||
"name": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"steps": [
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"length": 16,
|
|
||||||
"speed": "Normal",
|
|
||||||
"name": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"steps": [
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"active": true,
|
|
||||||
"script": "",
|
|
||||||
"source": null
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"length": 16,
|
|
||||||
"speed": "Normal",
|
"speed": "Normal",
|
||||||
"name": null
|
"name": null
|
||||||
},
|
},
|
||||||
@@ -42834,6 +42834,8 @@
|
|||||||
"name": null
|
"name": null
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"sample_paths": [],
|
"sample_paths": [
|
||||||
|
"/Users/bubo/Documents/samples"
|
||||||
|
],
|
||||||
"tempo": 110.0
|
"tempo": 110.0
|
||||||
}
|
}
|
||||||
@@ -31,7 +31,6 @@ pub struct App {
|
|||||||
pub patterns_nav: PatternsNav,
|
pub patterns_nav: PatternsNav,
|
||||||
|
|
||||||
pub metrics: Metrics,
|
pub metrics: Metrics,
|
||||||
pub sample_pool_mb: f32,
|
|
||||||
pub script_engine: ScriptEngine,
|
pub script_engine: ScriptEngine,
|
||||||
pub variables: Variables,
|
pub variables: Variables,
|
||||||
pub rng: Rng,
|
pub rng: Rng,
|
||||||
@@ -61,7 +60,6 @@ impl App {
|
|||||||
patterns_nav: PatternsNav::default(),
|
patterns_nav: PatternsNav::default(),
|
||||||
|
|
||||||
metrics: Metrics::default(),
|
metrics: Metrics::default(),
|
||||||
sample_pool_mb: 0.0,
|
|
||||||
variables,
|
variables,
|
||||||
rng,
|
rng,
|
||||||
live_keys,
|
live_keys,
|
||||||
@@ -280,7 +278,6 @@ impl App {
|
|||||||
let ctx = StepContext {
|
let ctx = StepContext {
|
||||||
step: step_idx,
|
step: step_idx,
|
||||||
beat: link.beat(),
|
beat: link.beat(),
|
||||||
bank,
|
|
||||||
pattern,
|
pattern,
|
||||||
tempo: link.tempo(),
|
tempo: link.tempo(),
|
||||||
phase: link.phase(),
|
phase: link.phase(),
|
||||||
@@ -355,7 +352,6 @@ impl App {
|
|||||||
let ctx = StepContext {
|
let ctx = StepContext {
|
||||||
step: step_idx,
|
step: step_idx,
|
||||||
beat: 0.0,
|
beat: 0.0,
|
||||||
bank,
|
|
||||||
pattern,
|
pattern,
|
||||||
tempo: link.tempo(),
|
tempo: link.tempo(),
|
||||||
phase: 0.0,
|
phase: 0.0,
|
||||||
|
|||||||
@@ -87,13 +87,13 @@ pub struct ActivePatternState {
|
|||||||
#[derive(Clone, Default)]
|
#[derive(Clone, Default)]
|
||||||
pub struct SharedSequencerState {
|
pub struct SharedSequencerState {
|
||||||
pub active_patterns: Vec<ActivePatternState>,
|
pub active_patterns: Vec<ActivePatternState>,
|
||||||
pub pattern_traces: HashMap<PatternId, Vec<SourceSpan>>,
|
pub step_traces: HashMap<(usize, usize, usize), Vec<SourceSpan>>,
|
||||||
pub event_count: usize,
|
pub event_count: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct SequencerSnapshot {
|
pub struct SequencerSnapshot {
|
||||||
pub active_patterns: Vec<ActivePatternState>,
|
pub active_patterns: Vec<ActivePatternState>,
|
||||||
pub pattern_traces: HashMap<PatternId, Vec<SourceSpan>>,
|
pub step_traces: HashMap<(usize, usize, usize), Vec<SourceSpan>>,
|
||||||
pub event_count: usize,
|
pub event_count: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,8 +118,8 @@ impl SequencerSnapshot {
|
|||||||
.map(|p| p.iter)
|
.map(|p| p.iter)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_trace(&self, bank: usize, pattern: usize) -> Option<&Vec<SourceSpan>> {
|
pub fn get_trace(&self, bank: usize, pattern: usize, step: usize) -> Option<&Vec<SourceSpan>> {
|
||||||
self.pattern_traces.get(&PatternId { bank, pattern })
|
self.step_traces.get(&(bank, pattern, step))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,7 +136,7 @@ impl SequencerHandle {
|
|||||||
let state = self.shared_state.lock().unwrap();
|
let state = self.shared_state.lock().unwrap();
|
||||||
SequencerSnapshot {
|
SequencerSnapshot {
|
||||||
active_patterns: state.active_patterns.clone(),
|
active_patterns: state.active_patterns.clone(),
|
||||||
pattern_traces: state.pattern_traces.clone(),
|
step_traces: state.step_traces.clone(),
|
||||||
event_count: state.event_count,
|
event_count: state.event_count,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -284,6 +284,7 @@ impl RunsCounter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
fn sequencer_loop(
|
fn sequencer_loop(
|
||||||
cmd_rx: Receiver<SeqCommand>,
|
cmd_rx: Receiver<SeqCommand>,
|
||||||
audio_tx: Sender<AudioCommand>,
|
audio_tx: Sender<AudioCommand>,
|
||||||
@@ -301,7 +302,7 @@ fn sequencer_loop(
|
|||||||
let mut audio_state = AudioState::new();
|
let mut audio_state = AudioState::new();
|
||||||
let mut pattern_cache = PatternCache::new();
|
let mut pattern_cache = PatternCache::new();
|
||||||
let mut runs_counter = RunsCounter::new();
|
let mut runs_counter = RunsCounter::new();
|
||||||
let mut pattern_traces: HashMap<PatternId, Vec<SourceSpan>> = HashMap::new();
|
let mut step_traces: HashMap<(usize, usize, usize), Vec<SourceSpan>> = HashMap::new();
|
||||||
let mut event_count: usize = 0;
|
let mut event_count: usize = 0;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
@@ -360,13 +361,15 @@ fn sequencer_loop(
|
|||||||
}
|
}
|
||||||
for id in audio_state.pending_stops.drain(..) {
|
for id in audio_state.pending_stops.drain(..) {
|
||||||
audio_state.active_patterns.remove(&id);
|
audio_state.active_patterns.remove(&id);
|
||||||
pattern_traces.remove(&id);
|
step_traces.retain(|&(bank, pattern, _), _| {
|
||||||
|
bank != id.bank || pattern != id.pattern
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let prev_beat = audio_state.prev_beat;
|
let prev_beat = audio_state.prev_beat;
|
||||||
|
|
||||||
for (id, active) in audio_state.active_patterns.iter_mut() {
|
for (_id, active) in audio_state.active_patterns.iter_mut() {
|
||||||
let Some(pattern) = pattern_cache.get(active.bank, active.pattern) else {
|
let Some(pattern) = pattern_cache.get(active.bank, active.pattern) else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
@@ -391,7 +394,6 @@ fn sequencer_loop(
|
|||||||
let ctx = StepContext {
|
let ctx = StepContext {
|
||||||
step: step_idx,
|
step: step_idx,
|
||||||
beat,
|
beat,
|
||||||
bank: active.bank,
|
|
||||||
pattern: active.pattern,
|
pattern: active.pattern,
|
||||||
tempo,
|
tempo,
|
||||||
phase: beat % quantum,
|
phase: beat % quantum,
|
||||||
@@ -406,8 +408,10 @@ fn sequencer_loop(
|
|||||||
if let Ok(cmds) =
|
if let Ok(cmds) =
|
||||||
script_engine.evaluate_with_trace(script, &ctx, &mut trace)
|
script_engine.evaluate_with_trace(script, &ctx, &mut trace)
|
||||||
{
|
{
|
||||||
pattern_traces
|
step_traces.insert(
|
||||||
.insert(*id, std::mem::take(&mut trace.selected_spans));
|
(active.bank, active.pattern, step_idx),
|
||||||
|
std::mem::take(&mut trace.selected_spans),
|
||||||
|
);
|
||||||
for cmd in cmds {
|
for cmd in cmds {
|
||||||
match audio_tx.try_send(AudioCommand::Evaluate(cmd)) {
|
match audio_tx.try_send(AudioCommand::Evaluate(cmd)) {
|
||||||
Ok(()) => {
|
Ok(()) => {
|
||||||
@@ -450,7 +454,7 @@ fn sequencer_loop(
|
|||||||
iter: a.iter,
|
iter: a.iter,
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
state.pattern_traces = pattern_traces.clone();
|
state.step_traces = step_traces.clone();
|
||||||
state.event_count = event_count;
|
state.event_count = event_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ pub struct ExecutionTrace {
|
|||||||
pub struct StepContext {
|
pub struct StepContext {
|
||||||
pub step: usize,
|
pub step: usize,
|
||||||
pub beat: f64,
|
pub beat: f64,
|
||||||
pub bank: usize,
|
|
||||||
pub pattern: usize,
|
pub pattern: usize,
|
||||||
pub tempo: f64,
|
pub tempo: f64,
|
||||||
pub phase: f64,
|
pub phase: f64,
|
||||||
@@ -1751,7 +1750,7 @@ fn parse_interval(name: &str) -> Option<i64> {
|
|||||||
Some(simple)
|
Some(simple)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compile_word(name: &str, ops: &mut Vec<Op>) -> bool {
|
fn compile_word(name: &str, span: Option<SourceSpan>, ops: &mut Vec<Op>) -> bool {
|
||||||
for word in WORDS {
|
for word in WORDS {
|
||||||
if word.name == name {
|
if word.name == name {
|
||||||
match &word.compile {
|
match &word.compile {
|
||||||
@@ -1762,7 +1761,7 @@ fn compile_word(name: &str, ops: &mut Vec<Op>) -> bool {
|
|||||||
}
|
}
|
||||||
Context(ctx) => ops.push(Op::GetContext((*ctx).into())),
|
Context(ctx) => ops.push(Op::GetContext((*ctx).into())),
|
||||||
Param => ops.push(Op::SetParam(name.into())),
|
Param => ops.push(Op::SetParam(name.into())),
|
||||||
Alias(target) => return compile_word(target, ops),
|
Alias(target) => return compile_word(target, span, ops),
|
||||||
Probability(p) => {
|
Probability(p) => {
|
||||||
ops.push(Op::PushFloat(*p, None));
|
ops.push(Op::PushFloat(*p, None));
|
||||||
ops.push(Op::ChanceExec);
|
ops.push(Op::ChanceExec);
|
||||||
@@ -1775,7 +1774,7 @@ fn compile_word(name: &str, ops: &mut Vec<Op>) -> bool {
|
|||||||
// @varname - fetch variable
|
// @varname - fetch variable
|
||||||
if let Some(var_name) = name.strip_prefix('@') {
|
if let Some(var_name) = name.strip_prefix('@') {
|
||||||
if !var_name.is_empty() {
|
if !var_name.is_empty() {
|
||||||
ops.push(Op::PushStr(var_name.to_string(), None));
|
ops.push(Op::PushStr(var_name.to_string(), span));
|
||||||
ops.push(Op::Get);
|
ops.push(Op::Get);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1784,7 +1783,7 @@ fn compile_word(name: &str, ops: &mut Vec<Op>) -> bool {
|
|||||||
// !varname - store into variable
|
// !varname - store into variable
|
||||||
if let Some(var_name) = name.strip_prefix('!') {
|
if let Some(var_name) = name.strip_prefix('!') {
|
||||||
if !var_name.is_empty() {
|
if !var_name.is_empty() {
|
||||||
ops.push(Op::PushStr(var_name.to_string(), None));
|
ops.push(Op::PushStr(var_name.to_string(), span));
|
||||||
ops.push(Op::Set);
|
ops.push(Op::Set);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1792,14 +1791,14 @@ fn compile_word(name: &str, ops: &mut Vec<Op>) -> bool {
|
|||||||
|
|
||||||
// Note names: c4, c#4, cs4, eb4, etc. -> MIDI number
|
// Note names: c4, c#4, cs4, eb4, etc. -> MIDI number
|
||||||
if let Some(midi) = parse_note_name(name) {
|
if let Some(midi) = parse_note_name(name) {
|
||||||
ops.push(Op::PushInt(midi, None));
|
ops.push(Op::PushInt(midi, span));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Intervals: m3, M3, P5, etc. -> dup top, add semitones (for chord building)
|
// Intervals: m3, M3, P5, etc. -> dup top, add semitones (for chord building)
|
||||||
if let Some(semitones) = parse_interval(name) {
|
if let Some(semitones) = parse_interval(name) {
|
||||||
ops.push(Op::Dup);
|
ops.push(Op::Dup);
|
||||||
ops.push(Op::PushInt(semitones, None));
|
ops.push(Op::PushInt(semitones, span));
|
||||||
ops.push(Op::Add);
|
ops.push(Op::Add);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1827,8 +1826,8 @@ enum Token {
|
|||||||
Float(f64, SourceSpan),
|
Float(f64, SourceSpan),
|
||||||
Str(String, SourceSpan),
|
Str(String, SourceSpan),
|
||||||
Word(String, SourceSpan),
|
Word(String, SourceSpan),
|
||||||
QuoteStart(SourceSpan),
|
QuoteStart,
|
||||||
QuoteEnd(SourceSpan),
|
QuoteEnd,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tokenize(input: &str) -> Vec<Token> {
|
fn tokenize(input: &str) -> Vec<Token> {
|
||||||
@@ -1869,22 +1868,14 @@ fn tokenize(input: &str) -> Vec<Token> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if c == '{' {
|
if c == '{' {
|
||||||
let start = pos;
|
|
||||||
chars.next();
|
chars.next();
|
||||||
tokens.push(Token::QuoteStart(SourceSpan {
|
tokens.push(Token::QuoteStart);
|
||||||
start,
|
|
||||||
end: start + 1,
|
|
||||||
}));
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if c == '}' {
|
if c == '}' {
|
||||||
let start = pos;
|
|
||||||
chars.next();
|
chars.next();
|
||||||
tokens.push(Token::QuoteEnd(SourceSpan {
|
tokens.push(Token::QuoteEnd);
|
||||||
start,
|
|
||||||
end: start + 1,
|
|
||||||
}));
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1923,15 +1914,15 @@ fn compile(tokens: &[Token]) -> Result<Vec<Op>, String> {
|
|||||||
Token::Int(n, span) => ops.push(Op::PushInt(*n, Some(*span))),
|
Token::Int(n, span) => ops.push(Op::PushInt(*n, Some(*span))),
|
||||||
Token::Float(f, span) => ops.push(Op::PushFloat(*f, Some(*span))),
|
Token::Float(f, span) => ops.push(Op::PushFloat(*f, Some(*span))),
|
||||||
Token::Str(s, span) => ops.push(Op::PushStr(s.clone(), Some(*span))),
|
Token::Str(s, span) => ops.push(Op::PushStr(s.clone(), Some(*span))),
|
||||||
Token::QuoteStart(_) => {
|
Token::QuoteStart => {
|
||||||
let (quote_ops, consumed) = compile_quotation(&tokens[i + 1..])?;
|
let (quote_ops, consumed) = compile_quotation(&tokens[i + 1..])?;
|
||||||
i += consumed;
|
i += consumed;
|
||||||
ops.push(Op::Quotation(quote_ops));
|
ops.push(Op::Quotation(quote_ops));
|
||||||
}
|
}
|
||||||
Token::QuoteEnd(_) => {
|
Token::QuoteEnd => {
|
||||||
return Err("unexpected }".into());
|
return Err("unexpected }".into());
|
||||||
}
|
}
|
||||||
Token::Word(w, _) => {
|
Token::Word(w, span) => {
|
||||||
let word = w.as_str();
|
let word = w.as_str();
|
||||||
if word == "|" {
|
if word == "|" {
|
||||||
if pipe_parity {
|
if pipe_parity {
|
||||||
@@ -1952,7 +1943,7 @@ fn compile(tokens: &[Token]) -> Result<Vec<Op>, String> {
|
|||||||
ops.push(Op::Branch(else_ops.len()));
|
ops.push(Op::Branch(else_ops.len()));
|
||||||
ops.extend(else_ops);
|
ops.extend(else_ops);
|
||||||
}
|
}
|
||||||
} else if !compile_word(word, &mut ops) {
|
} else if !compile_word(word, Some(*span), &mut ops) {
|
||||||
return Err(format!("unknown word: {word}"));
|
return Err(format!("unknown word: {word}"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1969,8 +1960,8 @@ fn compile_quotation(tokens: &[Token]) -> Result<(Vec<Op>, usize), String> {
|
|||||||
|
|
||||||
for (i, tok) in tokens.iter().enumerate() {
|
for (i, tok) in tokens.iter().enumerate() {
|
||||||
match tok {
|
match tok {
|
||||||
Token::QuoteStart(_) => depth += 1,
|
Token::QuoteStart => depth += 1,
|
||||||
Token::QuoteEnd(_) => {
|
Token::QuoteEnd => {
|
||||||
depth -= 1;
|
depth -= 1;
|
||||||
if depth == 0 {
|
if depth == 0 {
|
||||||
end_pos = Some(i);
|
end_pos = Some(i);
|
||||||
@@ -2039,10 +2030,12 @@ impl Forth {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
pub fn stack(&self) -> Vec<Value> {
|
pub fn stack(&self) -> Vec<Value> {
|
||||||
self.stack.lock().unwrap().clone()
|
self.stack.lock().unwrap().clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
pub fn clear_stack(&self) {
|
pub fn clear_stack(&self) {
|
||||||
self.stack.lock().unwrap().clear();
|
self.stack.lock().unwrap().clear();
|
||||||
}
|
}
|
||||||
@@ -2104,6 +2097,7 @@ impl Forth {
|
|||||||
Ok(outputs)
|
Ok(outputs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
fn execute_ops(
|
fn execute_ops(
|
||||||
&self,
|
&self,
|
||||||
ops: &[Op],
|
ops: &[Op],
|
||||||
|
|||||||
@@ -13,6 +13,9 @@ pub enum TokenKind {
|
|||||||
Sound,
|
Sound,
|
||||||
Param,
|
Param,
|
||||||
Context,
|
Context,
|
||||||
|
Note,
|
||||||
|
Interval,
|
||||||
|
Variable,
|
||||||
Default,
|
Default,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28,6 +31,9 @@ impl TokenKind {
|
|||||||
TokenKind::Sound => Style::default().fg(Color::Rgb(100, 220, 200)),
|
TokenKind::Sound => Style::default().fg(Color::Rgb(100, 220, 200)),
|
||||||
TokenKind::Param => Style::default().fg(Color::Rgb(180, 150, 220)),
|
TokenKind::Param => Style::default().fg(Color::Rgb(180, 150, 220)),
|
||||||
TokenKind::Context => Style::default().fg(Color::Rgb(220, 180, 120)),
|
TokenKind::Context => Style::default().fg(Color::Rgb(220, 180, 120)),
|
||||||
|
TokenKind::Note => Style::default().fg(Color::Rgb(120, 200, 160)),
|
||||||
|
TokenKind::Interval => Style::default().fg(Color::Rgb(160, 200, 120)),
|
||||||
|
TokenKind::Variable => Style::default().fg(Color::Rgb(200, 140, 180)),
|
||||||
TokenKind::Default => Style::default().fg(Color::Rgb(200, 200, 200)),
|
TokenKind::Default => Style::default().fg(Color::Rgb(200, 200, 200)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -39,18 +45,21 @@ pub struct Token {
|
|||||||
pub kind: TokenKind,
|
pub kind: TokenKind,
|
||||||
}
|
}
|
||||||
|
|
||||||
const STACK_OPS: &[&str] = &["dup", "drop", "swap", "over", "rot", "nip", "tuck"];
|
const STACK_OPS: &[&str] = &["dup", "dupn", "drop", "swap", "over", "rot", "nip", "tuck"];
|
||||||
const OPERATORS: &[&str] = &[
|
const OPERATORS: &[&str] = &[
|
||||||
"+", "-", "*", "/", "mod", "neg", "abs", "min", "max", "=", "<>", "<", ">", "<=", ">=", "and",
|
"+", "-", "*", "/", "mod", "neg", "abs", "min", "max", "=", "<>", "<", ">", "<=", ">=", "and",
|
||||||
"or", "not",
|
"or", "not", "ceil", "floor", "round", "mtof", "ftom",
|
||||||
];
|
];
|
||||||
const KEYWORDS: &[&str] = &[
|
const KEYWORDS: &[&str] = &[
|
||||||
"if", "else", "then", "emit", "get", "set", "rand", "rrand", "seed", "cycle", "choose",
|
"if", "else", "then", "emit", "rand", "rrand", "seed", "cycle", "choose", "chance", "[", "]",
|
||||||
"chance", "[", "]",
|
"zoom", "scale!", "stack", "echo", "necho", "for", "div", "each", "at", "pop", "adsr", "ad",
|
||||||
|
"?", "!?", "<<", ">>", "|", "@", "!", "pcycle", "tempo!", "prob", "sometimes", "often",
|
||||||
|
"rarely", "almostAlways", "almostNever", "always", "never", "coin", "fill", "iter", "every",
|
||||||
|
"gt", "lt",
|
||||||
];
|
];
|
||||||
const SOUND: &[&str] = &["sound", "s"];
|
const SOUND: &[&str] = &["sound", "s"];
|
||||||
const CONTEXT: &[&str] = &[
|
const CONTEXT: &[&str] = &[
|
||||||
"step", "beat", "bank", "pattern", "tempo", "phase", "slot", "runs",
|
"step", "beat", "bank", "pattern", "tempo", "phase", "slot", "runs", "stepdur",
|
||||||
];
|
];
|
||||||
const PARAMS: &[&str] = &[
|
const PARAMS: &[&str] = &[
|
||||||
"time",
|
"time",
|
||||||
@@ -160,6 +169,28 @@ const PARAMS: &[&str] = &[
|
|||||||
"cut",
|
"cut",
|
||||||
"reset",
|
"reset",
|
||||||
];
|
];
|
||||||
|
const INTERVALS: &[&str] = &[
|
||||||
|
"P1", "unison", "m2", "M2", "m3", "M3", "P4", "aug4", "dim5", "tritone", "P5", "m6", "M6",
|
||||||
|
"m7", "M7", "P8", "oct", "m9", "M9", "m10", "M10", "P11", "aug11", "P12", "m13", "M13", "m14",
|
||||||
|
"M14", "P15",
|
||||||
|
];
|
||||||
|
|
||||||
|
fn is_note(word: &str) -> bool {
|
||||||
|
let bytes = word.as_bytes();
|
||||||
|
if bytes.len() < 2 {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if !matches!(bytes[0], b'a'..=b'g' | b'A'..=b'G') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
let rest = &bytes[1..];
|
||||||
|
let digits_start = if rest.first().is_some_and(|&b| b == b'#' || b == b's' || b == b'b') {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
rest[digits_start..].iter().all(|&b| b.is_ascii_digit()) && digits_start < rest.len()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn tokenize_line(line: &str) -> Vec<Token> {
|
pub fn tokenize_line(line: &str) -> Vec<Token> {
|
||||||
let mut tokens = Vec::new();
|
let mut tokens = Vec::new();
|
||||||
@@ -252,6 +283,18 @@ fn classify_word(word: &str) -> TokenKind {
|
|||||||
return TokenKind::Param;
|
return TokenKind::Param;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if INTERVALS.contains(&word) {
|
||||||
|
return TokenKind::Interval;
|
||||||
|
}
|
||||||
|
|
||||||
|
if is_note(word) {
|
||||||
|
return TokenKind::Note;
|
||||||
|
}
|
||||||
|
|
||||||
|
if word.len() > 1 && (word.starts_with('@') || word.starts_with('!')) {
|
||||||
|
return TokenKind::Variable;
|
||||||
|
}
|
||||||
|
|
||||||
TokenKind::Default
|
TokenKind::Default
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -180,7 +180,7 @@ fn render_step_preview(frame: &mut Frame, app: &App, snapshot: &SequencerSnapsho
|
|||||||
}
|
}
|
||||||
|
|
||||||
let runtime_spans = if app.ui.runtime_highlight && app.playback.playing {
|
let runtime_spans = if app.ui.runtime_highlight && app.playback.playing {
|
||||||
snapshot.get_trace(app.editor_ctx.bank, app.editor_ctx.pattern)
|
snapshot.get_trace(app.editor_ctx.bank, app.editor_ctx.pattern, step_idx)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -362,7 +362,7 @@ fn render_modal(frame: &mut Frame, app: &App, snapshot: &SequencerSnapshot, term
|
|||||||
let (cursor_row, cursor_col) = app.editor_ctx.text.cursor();
|
let (cursor_row, cursor_col) = app.editor_ctx.text.cursor();
|
||||||
|
|
||||||
let runtime_spans = if app.ui.runtime_highlight && app.playback.playing {
|
let runtime_spans = if app.ui.runtime_highlight && app.playback.playing {
|
||||||
snapshot.get_trace(app.editor_ctx.bank, app.editor_ctx.pattern)
|
snapshot.get_trace(app.editor_ctx.bank, app.editor_ctx.pattern, app.editor_ctx.step)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ pub fn default_ctx() -> StepContext {
|
|||||||
StepContext {
|
StepContext {
|
||||||
step: 0,
|
step: 0,
|
||||||
beat: 0.0,
|
beat: 0.0,
|
||||||
bank: 0,
|
|
||||||
pattern: 0,
|
pattern: 0,
|
||||||
tempo: 120.0,
|
tempo: 120.0,
|
||||||
phase: 0.0,
|
phase: 0.0,
|
||||||
@@ -127,6 +126,7 @@ pub fn expect_outputs(script: &str, count: usize) -> Vec<String> {
|
|||||||
outputs
|
outputs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
pub fn expect_output_contains(script: &str, substr: &str) {
|
pub fn expect_output_contains(script: &str, substr: &str) {
|
||||||
let outputs = expect_outputs(script, 1);
|
let outputs = expect_outputs(script, 1);
|
||||||
assert!(
|
assert!(
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ fn multiple_emits() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn subdivide_each() {
|
fn subdivide_each() {
|
||||||
let outputs = expect_outputs(r#""kick" s 4 div each"#, 4);
|
let _outputs = expect_outputs(r#""kick" s 4 div each"#, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
Reference in New Issue
Block a user