tidalcycles / Tidal

Pattern language
http://tidalcycles.org/
GNU General Public License v3.0
2.19k stars 253 forks source link

Contiguous euclid #760

Open yaxu opened 3 years ago

yaxu commented 3 years ago

In response to a @kindohm question, a contiguous version of euclid, e.g. euclidGapless 3 8 gives the equivalent of "1@3 1@3 1@2" rather than 1 0 0 1 0 0 1 0:

import Sound.Tidal.Bjorklund

euclidGapless :: Int -> Int -> Pattern Bool
euclidGapless n x = timeCat $ map (\d -> (toRational d,pure True)) $ iois 0 $ bjorklund (n,x)
  where iois :: Int -> [Bool] -> [Int]
        iois 0 [] = []
        iois i [] = (i:[])
        iois 0 (True:xs) = iois 1 xs
        iois i (True:xs) = i:(iois 1 xs)
        iois i (False:xs) = iois (i+1) xs

Would be nice to add this to tidal, and think about mininotation shorthand for it.. The best I could think of was double parens: "t((3,8))"

kindohm commented 3 years ago

Any chance we could also support a third parameter for the rotation?

d1 $ euclidGapless "3" "8" "<0 3>" $ s "bd"

d1 $ s "bd((3,8,<0 3>))"
telephon commented 3 years ago

Would be nice to add this to tidal, and think about mininotation shorthand for it.. The best I could think of was double parens: "t((3,8))"

Thinking into the future, I wonder if it would be useful to have a more extendable notation convention? There are not many kinds of brackets left :)

yaxu commented 3 years ago

Yes what are the options? Regex uses a question mark and another character for different groupings like (?! ) for negative lookahead iirc. They look a bit like emoticons so are quite easy to remember but look like line noise for the uninitiated..

telephon commented 3 years ago

Not sure. So currently, the schema is a nested ABXB', where A is some expression like an instrument name, B…B' is a pair of matching parentheses, and X is some arbitrary term? (well, not arbitrary, but depends on A, I suppose).

yaxu commented 3 years ago

Another approach would be to embed named function names into the mini notation like {% euclidGapless 3 8 %}.. Or make the mini notation redundant by making the native haskell side as expressive

telephon commented 3 years ago

Or make the mini notation redundant by making the native haskell side as expressive

That sounds like a good idea to me.

yaxu commented 3 years ago

So currently, the schema is a nested ABXB', where A is some expression like an instrument name, B…B' is a pair of matching parentheses, and X is some arbitrary term? (well, not arbitrary, but depends on A, I suppose).

Well there's a(3,8) for euclid but also [a,a,...] and {a,a,...} for subpatterns / layering

The latter is based on BP2 polymetric expressions https://bolprocessor.org/misc/docs/bp2-Polymet.html

It seems Bernard has _rest for an 'undetermined rest. We could do something similar with_euclidGapless(3,8)` in the mininotation.

But it does feel like it's shoehorning things into the mininotation.

You could also do

setF "x" $ euclidGapLess 3 8 

and then use that as ^x in mininotation.

ndr-brt commented 3 years ago

What about an underscore before the parenthesis? bd_(3,8)

ovitus commented 3 years ago

Can we get the euclid values patternable on this? Even a quick hack? This function should be added to tidal, it's great for sequencing legato.

capogreco commented 2 years ago

maybe a haskell function that coalesces rests in any pattern into the note event immediately previous to them?

bgold-cosmos commented 2 years ago

Ah, somehow I missed this and was recently thinking of something similar. Coalescing rests is actually rather tricky since patterns have all sorts of overlapping things going on.

As for the mininotation, bd_(3,8) seems intuitive but I'm wondering if bd(_3,8) might parse more easily. And in some sense, it's only the "3" that gets modified, so maybe that makes a weird kind of sense?

import GHC.Exts ( IsString(..) )

import Sound.Tidal.Bjorklund (bjorklund)

import Data.Bool (bool)

_euclidEBool :: Int -> Int -> Pattern Bool
_euclidEBool n k = fromString . concatMap (bool "_ " "t ") $ bjorklund (n,k)

_euclidEOffBool _ 0 _ _ = silence
_euclidEOffBool n k s p = rotL (fromIntegral s % fromIntegral k) $ (\a b -> if b then a else not a) <$> _euclidEBool n k <*> p

euclidEOffBool = tParam3 _euclidEOffBool
euclidEBool n k p = euclidEOffBool n k 0 p