Hierarchical Euclidian Distributions
by eric.p.fairbanks＠gmail.com

This is a technique that I've used extensively in SuperCollider and Overtone, but that I have yet to bring into my TidalCycles workflow.
Euclidian distributions let you evenly select <n> out of <k> items. This is great, but it only gives you two states for any rhythmic quantum. Music is a series of descending (or ascending depending on your point of view, I guess) rhythmic/metric/structural hierarchies, so why not extend this technique to reflect that?
To achieve this, we can generate a basic Euclidian (<n>,<k>) distribution, and then use another Euclidian distribution where <k> is equal to the <n> of the previous distribution to select a subset of the distributed elements to be marked or modified in some way.
An example where <n> = 4, <k> = 8, and the second <n> which we will call <n'> = 2:
(<n>,<k>) == [1,0,1,0,1,0,1,0]
To selectively choose and replace only the elements from this list represented by <n>, we must determine the indices of those elements, use (<n'>,<n>) as a mask to remove those indices which are not to be selected, and then replace the elements in (<n>,<k>) that exist at those indices with a new value. Let's have that value be 2.
[0,2,4,6] -- indices
[1,0,1,0] -- mask (<n'>,<n>) or (2,4)
[0,4] -- new list of indices with mask applied
If we replace indices 0 and 4 in (<n>,<k>) with 2 like we said we would, we get:
[2,0,1,0,2,0,1,0]
If we replace these elements with some sensible percussion elements, we get a familiar rhythm from any house track:
["bd","hh","sn","hh","bd","hh","sn","hh"] -- boots n cats n boots n cats
This technique can be applied to a pattern recursively about as many times as you'd like to create increasingly complex rhythmic hierarchies while maintaining a relative evenness. It's especially useful for breaking up odd/prime meters into sensible chunks or for automating parameters in interesting and pleasing ways without relying on beat-synced LFOs.
I'm interested in bringing this into Tidal in some way, but I'm not totally sure how to sensibly convert these into proper Patterns/ParamPatterns. I'm working on it, but any input is appreciated.
Finally, because seeing is believing, here is some example code.
// --------------------------------------- //
// --- CODE TO BE RUN BELOW --- //
// --------------------------------------- //
import Sound.Tidal.Bjorklund
-- do a running sum on a list
integrate' x l =
if (length l) > 0
then [runningSum] ++ integrate' runningSum (tail l)
else []
where runningSum = x + (head l)
integrate = integrate' 0
-- get the indices of the list elements for which a given function returns true
matchedIndices' i f l =
if (length l) > 0
then matchedIndex ++ (matchedIndices' (i+1) f (tail l))
else []
where matchedIndex = if (f $ head l) then [i] else []
matchedIndices = matchedIndices' 0
-- replace list elements of <l> that exist at indices specified by <il> with <r>
replaceIndices' i r il l =
if (min (length l) (length il)) > 0
then [newVal] ++ (replaceIndices' (i+1) r il (tail l))
else []
where newVal = if (elem i il) then r else (head l)
replaceIndices = replaceIndices' 0
-- evenly distribute <replace> among elements in <l> that match <find>
bjorkSelect find replace n l =
replaceIndices replace (matchedIndices id $ bjorklund (n, (length l))) l
convertBools t f = map (\x -> if x then t else f)
-- use bjorkSelect to create a pattern based on a hierarchy of distributions
bjorkBuildHierarchy' i pattern selects =
if (length selects) > 0
then bjorkBuildHierarchy' (i + 1) (bjorkSelect i (i + 1) (head selects) pattern) (tail selects)
else pattern
bjorkBuildHierarchy n selects =
bjorkBuildHierarchy' 0 (replicate n 0) selects
-- boots n cats
map (\x -> ["hh","sn","bd"]!!x) $ bjorkBuildHierarchy 8 [4,2]
-- tidal> ["bd","hh","sn","hh","bd","hh","sn","hh"]
-- some crazy distribution
bjorkBuildHierarchy 23 [17,11,7,5,3]
-- tidal> [5,0,2,1,3,4,2,3,5,4,3,1,2,0,4,1,5,3,4,1,3,0,1]
-- hey look, we can integrate euclidian rhythms to
-- index into other things in a rhythmically even way
integrate (convertBools 1 0 $ bjorklund (3,8))
-- tidal> [1,1,1,2,2,2,3,3]
-- we can use hieararchies and modulus to get even crazier
map (flip mod 3) $ integrate $ bjorkBuildHierarchy 16 [5,2]
-- tidal> [2,2,2,0,0,0,1,1,0,1,1,1,2,2,2,2]