-
-
Notifications
You must be signed in to change notification settings - Fork 120
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Real legato #1142
base: main
Are you sure you want to change the base?
Real legato #1142
Conversation
I've been thinking about this and I'm worried about the name collision with the original Tidal legato. How about https://en.wikipedia.org/wiki/Articulation_(music) |
thinking the same. articulate seems a bit abstract to me.. how about fill? |
I like fill I think that makes sense and is easy to type :) technically it is legato though and a fill means something different musically. Maybe that’s okay |
another alternative could be flood |
well yeah but in this context it wouldn't mean "a fill" more of like "fill-in the silences" |
btw this has a problem, i've run into this in tidal and yeah it replicates in strudel too. the malformed haps list is troublesome when combined with other complex hap-changing functions such as rev: $: s("supersaw")
// .euclid(11,16)
.struct("1 0 0 1 1").fast(2)
// .beat("0:1:3:4:6:5", 8).fast(2)
.legato("1").rev()
._pianoroll() |
hmm yeah im not sure what the solve is for this edge case, it still works if you put rev before legatio at least.. ```$: s("supersaw") .struct("1 0 0 1 1").fast(2).rev() .legato("1") |
looks like fill is a reserved param for the pianoroll, does it need to be? |
here's my solution from the haskell side: a function which, given any event (hap), it encloses it into the original query arc (span), if it shouldn't be there it'll return nothing. in the js side returning null will probably be good enough encloseHap (Span spanBegin spanEnd) hp@(Hap _ (Just (Span wholeBegin wholeEnd)) _ _)
| wholeEnd <= spanBegin = Nothing
| wholeBegin >= spanEnd = Nothing
| wholeBegin >= spanBegin && wholeEnd <= spanEnd = Just hp -- fully within
| wholeBegin >= spanBegin && wholeEnd > spanEnd = Just hp { part = Span wholeBegin spanEnd } -- starts within, ends outside
| wholeBegin < spanBegin && wholeEnd > spanEnd = Just hp { part = Span spanBegin spanEnd } -- starts outside, ends outside
| wholeBegin < spanBegin && wholeEnd <= spanEnd = Just hp { part = Span spanBegin wholeEnd } -- starts outside, ends within
| otherwise = Nothing edit: changed function to be more understandable from a strudel perspective
|
ok here's the issue with the lookahead scenario: there are times where some haps will be lost only because their original times weren't on the query. what i did for quantization for tidal doesn't run into this scenario, since what i do there is, for every query span, query the whole cycle (floor and ceiling of the current query span, basically), and then enclose it. if you make sure you always query from the cycle start, you're good to go to then enclose it and have it well-formed you could also just lookbehind by the same amount you lookahead heh |
Other name idea |
Legato now changes the note duration relative to the gap between notes.
s("sawtooth").euclid(11,16).legato("<1 .5>")._pianoroll()
second array parameter is "lookahead" which is the number of cycles in the future to query for the next event
s("supersaw").euclid(7,16).legato("1:<1
.15>")._pianoroll()`