Because of the dancer in #nudel i'm thinking about mini notations and patterns.

"why doesn't basil have them?" 🤔 I already do have a parser anyway, but I think that would need a native basil -> webgl transpiler (skipping the hydra in between). And then inline the mini notation into the webgsl? with a time parameter to switch it?

#basil #mondo #nudel

Biggest knot in my head right now is how to combine it with chaining.

Like I want it to be possible to change functions, so its possible to instead of rotate move by x:
` o 3 # <(r 2) (x .3)>`

I keep hitting a few roadblocks:
- How too start a pattern
- How to embed a thing into it.
- how to mark these things as "chaining" (maybe this can be an automatic thing?)

the `(r 2)` and `(x .3)` are primitives regarding the pattern, and should result in `o 3 # r 2`

#mondo seems to allow individual items to be patterned. But doesn't allow `s <bd bd>*2 # [(room 1) (delay 2)] # fast 2`

(cc @froos or did I read that wrong?)

Maybe its enough to just allow `[]`, and not arbitrary patterns (as they always can be represented with a `[]`) .

With only allowing the pattern to do one primitive, it sidesteps my 3. option

@froos also I low key like the beat lol. its so expressive, with very dense syntax lol https://strudel.cc/#bW9uZG9gCnMgPGJkIGJkPioyICMgW3Jvb20gZGVsYXldIDEgIyA8ZmFzdCBzbG93PiBbMiA0XQpg
Strudel REPL

Strudel is a music live coding environment for the browser, porting the TidalCycles pattern language to JavaScript.

@froos Ah mondo can do this with `(# room 2)`
this works: `s <bd bd>*2 # [(# room 3) (# delay 1)] # <fast slow> [2 4]`
That syntax would still be free as well. Not sure if we can borrow the lambda syntax `(> fft)` here, we are not technically calling anything, but we are chaining 🤔

ok new knot unlocked:
hydra needs to hoist functions up, that do coordinate calculations (rotate / scrollX / etc) When allowing patterns in what function to call, we need to hoist it depending on what functions is being called at that time 🤯

Which probably means I need to just bubble up all patterns and combine them into one big pattern essentially, that way I can just witch out what gsls functions to call based on timings. Or carry the timing information in the hoisting 🤔

I'm not even at the hoisting state yet. Still working on the part that gets an AST where all the timings are resolved.

Then I can start to hoist the calls up, if needed.

This tickles one of the nerdiest corners of my brain.

I have a timed AST now. (nothing Hydra specific yet!)
Next up is hoisting (will need hydra specific code).

When this works out, basil will make a huge step away from #hydra.

Which still requires a lot of footwork. Need to implement all the glsl code and rendering framework etc.

If I can pull this of this will be possible:
`add <(s 4) [(<o s> 3) (voronoi [4 6])]> # out`

Hah I just found another edge case. the <o s> in the middle will currently not work as intended (in this case, it will always be s), it needs to be multiplexed with the containing <> pattern. Damn.

Currently I am converting each pattern individually to timing events, but I need to respect the inner patterns when converting 🤔

Maybe it's easier to bubble the patterns all the way up and re-construct the ast in each resolved event? That would make the resulting translation into gsls waaay easier, but probably now as small as it can be.

Could I normalize the timing signal at each sub-pattern?
Currently one cycle is 0-1, twi cycles would be 0-2.
in the code `add <(s 4) [(<o t> 3) (voronoi [4 6])]> # out` the <o t> should make one full loop when the containing pattern makes two.
If instead of using the same timing signal the inner pattern uses one that goes up 1 every full outer cycle, but from 0-1 "in every invoation", would that work?

"in every invocation" in quotes, because the "o" would see 0-.5, because its in the first spot of the [ ] patter. the "t" would then see 1.0-1.5 (.5-1 goes to the voronoi part).
The global timing would go from 0-4 for the whole code to loop, but the outer pattern will only be a cycle of 2 with this.

I kind alike this because it doesn't just bubble up the whole timing all the way. It makes propagation harder though.

Especially because with hoisting I would need to track the correct timings closely. 🤔

I think I managed to get this "working".
It's now split into 3 parts:
- 1. I convert all Patterns into "Timings"
- 2. I scope the timings, so they all run on global time (trickling down!)
- 3. I do the "normal" hydra hoisting, while keeping these timings in tact

I've not tested this other then looking at somer examples yet. (and even that I've only done for like 3 minutes).

My head is smoking though lol

From this:
`osc # mod <(s 4) [(<o t> 3) (x [4 6])]> # y # out`
I now can generate
`y
mod [ <(y # s 4)>(0:1|2) | <(y # [ <o>(1:1.5|4) | <t>(3:3.5|4) ] 3)>(1:1.5|2) | <(y # x [ <4>(1.5:1.75|2) | <6>(1.75:2|2) ])>(1.5:2|2) ]
osc
out `

"[ | ]" denote timing groups, "() timing information: (start:end|cycle).

I'm at the point where I can start writing the translation layer to gsls!

If this works, its gonna be so cool =D

There is a lot of crucial mini-notation features missing currently (all the modifiers like !@/*. But this is a integrated mini-notation in the Base-parser of the language! (cc @froos )
There is a few turns on the road left, but I can kinda make it out now, which is 🎉
What do you mean? This is totally readable glsl code!
Now I have to actually put this on a website, so I can see it!
then you blink and you wonder why you are googling "GLSL 3.00 ES" and why you get " ERROR: unsupported shader version" and why modulo isn't a think without it. wat
YESSSS

This is already so amazing!

Need to get all the timings and scalings correct.

But its looking so promising!

I still can barely contain my excitement over this.

This took quite some brain juice. I have a few of the basics to implement before I feel it is ready for the Nudel alpha test torture implementation 😅

(Like multiple outputs and inputs and syncing to the strudel time is probably a must. Ah btw @froos how to seconds map to cycles in strudel? Is there an east function to get the cpm? (Or the cycle count directly?)

If it’s ready (for alpha ) it’s gonna join dente too

huh, apparently ternaries in GLSL cannot be used with uniform sampler2D as the value they result in? :o
That means I have to hoist these timings further up, so I can replace it with more if calls.

I should be able to convert the dancers to this too! (maybe not into the "hydra" part of basil, but as a standalone thing maybe)

But I'm getting ahead of myself

#nudel