Issue re. midi cc + stripe function

Hi everyone,

Apoligies if I'm missing something obvious here, as I don't know code outside of tidal, but while trying to build a patch this evening, I came across a bizarre issue that I hoped someone could help me with. I realised that if I attempted to midi control a parameter inside pattern that contained the function "stripe" the result would be pure silence.

For example "d1 $ stripe 3 $ s "bd8" #speed "^70"" will produce nothing, but "d1 $ s "bd8" #speed "^71"" will work just fine. There is also no error message, and a quick google didn't bring me any documentation that would resolve this discrepancy.

Please let me know if you have any ideas <3

no idea, but confirm: stripe does silence the pattern.

NB: I had no idea that stripe exists, and when I look at the source (https://hackage.haskell.org/package/tidal-1.9.3/docs/src/Sound.Tidal.UI.html#randStruct ), well, I still have no idea what this does to MIDI values.

At first I thought, well, "^70" (etc.) are real-time signals, so you could never apply fast (or stripe, or anything that transforms time.) But apparently you can, fast 2 "^70" just seems to query the real-world more often. But it's not like rand (continuous), where you can't s "casio:1" + speed rand, only s "casio:1" + segment 4 (speed rand).

So, what kind of signal do we get from "^70"?

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.

2 Likes