# Need help patterning with sequences of random values

I was going to post a function I use in custom functions, but realized that there are probably better ways of doing this and I wanted see if anyone had any ideas.

I really like being able to generate random persistent sequences, for example, shuffling a pattern and having that particular shuffle repeat. I made a custom function I call `lock` which uses `repeatCycles` with an arbitrarily large number.

``````lock n offset p = slow n \$ repeatCycles 10000 \$ fast n \$ (offset  <~) p
``````

This works in that it 'locks in' any randomness in a loop that is n cycles long, and allows me vary the random pattern by changing the offset value.

I'm not crazy about the `repeatCycles 10000` which feels like a code smell, but more importantly, it doesn't let me use patterns for the offset values in a predictable way. I might find two different offset vales that produce interesting sequences, for example 0 and 1, and set it to either value, but I can't set it to alternate between the two sequences produced by those offsets.

E.g., I can make two patterns:

``````d1 \$ lock 1 "0"  \$ s "arpy*4" # n (irand 8)
``````

and

``````d1 \$ lock 1 "1"  \$ s "arpy*4" # n (irand 8)
``````

but

``````d1 \$ lock 2 "<0 1>"  \$ s "arpy*4" # n (irand 8)
``````

won't alternate between the two. I can easily see the reason why: the random values used in the 2nd cycle won't be the same as the random values in the first cycle, but if I loop every cycle then I can't pattern any variation.

Does anyone have any suggestion for how I can accomplish this (I've also experimented with using `qtrigger` in the function but either I'm doing it wrong or it's not what I need)? Or alternatively, other strategies for getting repeatable bits of randomness that can patterned together. Thanks!

2 Likes

I'd be really interested in understanding how to work in this way as well.

There's a `loopFirst` function (and related `timeLoop`) that can build what you want. For example, `lock` could be written as

``````lock n offset = timeLoop n . (offset <~)
``````

which then produces

``````tidal> lock 1 0 \$ s "arpy*4" # n (irand 8)

(0>¼)|n: 2.0f, s: "arpy"
(¼>½)|n: 4.0f, s: "arpy"
(½>¾)|n: 1.0f, s: "arpy"
(¾>1)|n: 3.0f, s: "arpy"

tidal> lock 1 1 \$ s "arpy*4" # n (irand 8)

(0>¼)|n: 5.0f, s: "arpy"
(¼>½)|n: 6.0f, s: "arpy"
(½>¾)|n: 4.0f, s: "arpy"
(¾>1)|n: 3.0f, s: "arpy"

tidal> lock 1 "0 1" \$ s "arpy*4" # n (irand 8)

(0>¼)|n: 2.0f, s: "arpy"
(¼>½)|n: 4.0f, s: "arpy"
(½>¾)|n: 4.0f, s: "arpy"
(¾>1)|n: 3.0f, s: "arpy"
``````
1 Like

Thanks @bgold. `timeLoop` is worlds better than `repeatCycles 10000` in terms of hackiness. But unfortunately it has the same behaviour across cycles. I should have been clearer stating my problem: (as with `repeatCycles 10000`) I am able to pattern the offset values within a single cycle, but not across multiple cycles.

E.g., I get 4 sequences A,B,C, and D with 4 different offset values:

``````-- A: ibdk
d1 \$ lock 1 0 \$ s "alphabet*4" # n (irand 26)

-- B: rbfk
d1 \$ lock 1 1 \$ s "alphabet*4" # n (irand 26)

-- C: xbez
d1 \$ lock 1 2 \$ s "alphabet*4" # n (irand 26)

-- D: rlas
d1 \$ lock 1 3 \$ s "alphabet*4" # n (irand 26)
``````

If I want to alternate between A and C, I can't use `lock 2 "<0 2>"`, that will produce A D. Because C is occurring in the 2nd cycle I need to offset its `offset` value by 1:

``````-- A C
d1 \$ lock 2 "<0 1>" \$ s "alphabet*4" # n (irand 26)
``````

While reversing the order to C A would require:

``````-- C A
d1 \$ lock 2 "<2 -1>" \$ s "alphabet*4" # n (irand 26)
``````

This comes out the same with either definition of `lock`

It's not tough math, but especially if I want to sequence together more than 2 cycles, it's big investment of cognitive load.

Ah, ok, I think I get it now. The issue is the periodicity of the "offset" pattern. I don't know if there's a way around the math, but it's possible build it into the `lock` function so you don't have to think about it

``````lock n offset = timeLoop n . ((offset |- (slow n \$ run n)) <~)

d1 \$ lock 1 0 \$ s "alphabet*4" # n (irand 26)
-- "I P D K"

d1 \$ lock 1 2 \$ s "alphabet*4" # n (irand 26)
-- "X C E Z"

d1 \$ lock 2 "<0 2>" \$ s "alphabet*4" # n (irand 26)
-- alternates each cycle
``````

The thing to remember is that in the last example, since you want a two-cycle offset pattern, that you need to use `lock 2`, but I think that's not too tricky to remember once you get the hang of it.

This function probably does strange stuff if you spread events over cycle boundaries, but I think that's unavoidable.

2 Likes

Hey, do you have any links to an explanation of timeLoop? I couldn't find anything in the tidal documentation.

@bgold Perfect! That's what I was trying to get. Thanks for help!