How to randomly choose from patterns of varying lengths?

Scenario 1: I want eight subdivisions per cycle, and for each subdivision randomly choose between “1 ~ 1” and “2”, while preserving the integrity of each pattern. For example:

| 1 ~ 1 2 2 2 1 ~ | 1 1 ~ 1 2 2 2 1 | ~ 1 2 2 1 ~ 1 2 |

I tried markovPat, choose, (<~), but none work.

Scenario 2: Randomly choose from patterns where a pattern may last longer than one cycle. For example, choosing between “<1 1>“ and “~”:

| 1 | 1 | ~ | 1 | 1 | 1 | 1 | ~ |

I tried wrandcat and cycleChoose, but neither preserves the integrity of patterns lasting longer than one cycle.

Bonus: Instead of “<1 1>” I really want to sustain “1” for 2 cycles, rather than rearticulating.

  1. in mini-notation: try [1 ~ 1 | 2]*8.

    perhaps you tried in Haskell, and noticed that this type does not match your use case:
    choose :: [a] -> Pattern a (you want [Pattern a] -> Pattern a).

    Then why does it work in mininotation? Implementation https://codeberg.org/uzu/tidal/src/branch/main/tidal-core/src/Sound/Tidal/ParseBP.hs#L204 uses
    unwrap :: Pattern (Pattern a) -> Pattern a

    the parser translates [1 ~ 1 | 2]*8 to

fast 8 $ unwrap $ segment 1 $ choose [ "1 ~ 1", "2" :: Pattern Int ]
  1. "patterns of .. length": a pattern has no length. a pattern is a function from (interval of) time to (set of) events. as the saying goes, time has no beginning, and no end.

    That is a basic design decision about the semantics of Pattern a. It may go counter to intuition coming from scores (sheet music), and traditional computer music systems. mininotation (and some of its tutorials) sometimes hide (ignore, respectively) that concept.

  2. there are patterns that have a period (it's called tidal-cycles after all) but: the functions that operate on Pattern a don't know its period. Still it's interesting to ask, for some operator f applied to a pattern p, how the period of f p (if there is one) depends on the period of p (if ...). (Anything random will destroy the peroid, mostly. But it's deterministic pseudo-random, so it may not, and this can be used to interesting effect.)

  3. finally, mininotation complicates matters sometimes when it appears that the length of a pattern does exist. This happens for the left argument of the % operator, which appears to be a pattern, but it is not - it is a sequence of patterns. Proof: (a) see implementation in ParseBP, (b) tidal has no Haskell function (on patterns) that does exactly what % does (?)

This (all of the above) is in no way a negative opinion on tidalcycles' design, or on the question that was asked here, and about % in the other thread.

I do care about clear explanations (it is my job) and I teach tidal-for-beginners from time to time, so I watch carefully here what questions are being asked, and I try to think of how I would answer them, and sometimes do.

Thank you for explaining, this is definitely a change in thinking.

The mininotation example you provided [1 ~ 1 | 2]*8 expands to something like:

| [1 ~ 1] 2 2 [1 ~ 1] [1 ~ 1] 2 2 2 |

whereas I wanted:

| 1 ~ 1 2 2 2 1 ~ | 1 1 ~ 1 2 1 ~ 1 |

so I am still wondering if a solution exists.

If MarkovPat weren’t broken right now, and if it didn’t reset to the start index at the start of each cycle, then it would be a solution, albeit a convoluted one that would quickly get out of hand for more complex patterns for this use case. But there could hypothetically exist a cleaner syntax that would translate to this MarkovPat in the backend. The more important question is: does the very idea of MarkovPat not resetting to the start index each cycle contradict TidalCycles design?

  • ah, now I see better what you mean.
  • markovPat is not broken (I think)
  • markoPat does "reset the start index", by design (of tidal). partial work-arounds are to use slow, or to use a random start index - but ...

indeed, as you mention, tidal's patterns don't have state. That's a difference to "behaviours" from functional reactive programming which allow a stepper function (and similar) https://hackage.haskell.org/package/threepenny-gui-0.9.4.2/docs/Reactive-Threepenny.html#v:stepper

you could still hide the state in tidal's back-end somewhere, and I guess that's done with https://tidalcycles.org/docs/reference/state_values - which I never use.

returning to your question, I think I would compute a very long list of events by a pseudo-random Haskell function, and then make a Pattern from that. That's exactly what `runMarkov'/'markovPat' do, so you might as well use these, with a transition matrix that consists of two loops (of different lenght, overlapping in one point, where you start). (most weights are 0 or 1, only in the overlap: 0.5 and 0.5)

[EDIT] re: markovPat broken: in 1.10.1, see #1230 - MarkovPat does not obey the probability matrix - uzu/tidal - Codeberg.org

1 Like

I think I fixed markov, and the following models your example [ 0 | 1 2 3 ]

ghci> runMarkov 40 [[0.5,0.5,0,0],[0,0,1,0],[0,0,0,1],[0.5,0.5,0,0]] 0 42
[0,1,2,3,0,0,1,2,3,0,1,2,3,0,0,0,1,2,3,0,0,0,1,2,3,0,0,0,1,2,3,1,2,3,0,1,2,3,0,0]

1 Like