my current guess is that the last line is responsible
substruct' :: Pattern Int -> Pattern a -> Pattern a
substruct' s p = p {query = \st -> concatMap (f st) (query s st)}
where f st (Event c (Just a') _ i) = ...
-- Ignore analog events (ones without wholes)
f _ _ = []
but I have no idea why it is there.
[venturing into innards territory here]
I have a horror of any function (like substruct'
, randStruct
) that breaks the abstraction barrier of Pattern
. I think that Pattern
should normally be exported without the constructor, and functions that do need it (to access or build the query
of the pattern) should be treated with great suspicion. I guess these are exactly the ones that make problems for tidal-2, where the Pattern
abstraction is made explicit (as a type class).
Returning to the question at hand - can we implement stripe
in the abstract? To my ears, these sound quite similar:
d1 $ stripe 3 $ n "1 0" + s "casio" -- what we have now
let -- alternative implementation
strp n p = do
rs <- mapM (\ d -> segment 1 $ pure d <~ (choose [1,2,3])) [0 .. (n-1)]
timeCat $ zip rs $ repeat p
in d1 $ strp 3 $ n "1 0" + s "casio"
now the alternative also uses a "magic" function (timeCat
) but it seems more well-behaved: it has a clear specification, and implementation uses compressArc
which has no special provision to "ignore analog events".
Well indeed this works for me:
let strp n p = do
rs <- mapM (\ d -> segment 1 $ pure d <~ (choose [1,2,3])) [0 .. (n-1)]
timeCat $ zip rs $ repeat p
in d1 $ strp 3 $ n "1 0" + s "casio" + speed "^70"
For reference, alternative implementation of `stripe` that does not eat analog (e.g., MIDI) signals · Issue #998 · tidalcycles/Tidal · GitHub
NB: that "casio" sounds ... special (a.k.a. terrible - without further processing) but I like to use it for testing, to have a clear signal.