Sorry a bit of a late start to the week. Here's a starter, looking at different ways of composing patterns together. I'll continue this in the next video with a look at the ur
function for composing patterns of patterns.
- 0:00 Intro - comparing composition in music vs composition in (functional) programming
- 2:30 - using 'overlay' to stick one pattern on top of another
- 4:22 - using 'stack' to stick any number of patterns on top of one another
- 5:23 - applying functions / effects to whole stacks
- 6:06 - (sidetrack) - using 'all' to apply a function to all the patterns that are running
- 8:30 - append and cat - for alternating between cycles from a pair or a list of patterns
- 10:35 - fastappend and fastcat
- 11:50 - seqPLoop - for making a looped sequence of patterns
- 14:20 - naming patterns within a seqPLoop
- 15:36 - seqP - for making a single-shot (non looped) sequence of patterns
-- Composing patterns together
-- We've already looked at different ways of composing patterns
-- together. Something as simple as this is a composition:
d1 $ fast "1 2 3 4" $ sound "lt mt ht bd*2"
-- Not a super interesting one, but it composes together a pattern of
-- densities, and a pattern of sounds, to create a new pattern that is
-- more than the sum of its parts.
-- In this lesson though we're going to look at ways to compose what
-- you could call 'independent' patterns, where one isn't used to
-- manipulate the other.
-- Tidal is often used in live situations, but there are some
-- functions that help you assemble multiple patterns into something
-- like a complete 'piece', such as a structured four-minute track.
-- Before we get to that, lets look at some extra-simple ways of
-- composing patterns together.. as they can be surprisingly useful
-- First, there's `overlay` that simply plays the two given patterns
-- at the same time:
d1 $ overlay (fast "1 2 3 4" $ sound "lt mt ht ~")
(sound "clap:4(3,8)" # speed 2)
-- Similar to this is `stack`, which lets you overlay any number of
-- patterns on top of each other. People tend to use this rather than
-- `overlay`, as it's more flexible:
d1 $ stack [(fast "1 2 3 4" $ sound "lt mt ht ~"),
(sound "clap:4(3,8)" # speed 2),
sound "[kick:5(5,8), snare:3(7,16,3)]"
]
-- The above composes a list of three patterns together. You can see that
-- a list is given using square brackets ('[' and ']'), with the patterns
-- in the list separated by commas (','). You have to remember *not* to
-- put a comma at the end of the list, only between the elements.
-- The above might not seem too useful, as you could do the same with
-- separate patterns. This sounds exactly the same as the above:
d1 $ fast "1 2 3 4" $ sound "lt mt ht ~"
d2 $ sound "clap:4(3,8)" # speed 2
d3 $ sound "[kick:5(5,8), snare:3(7,16,3)]"
-- Remember though that stack combines everything into a single
-- pattern. This is useful as you can manipulate all those patterns as
-- one. For example:
d1 $ chunk 4 (hurry 2) $
stack [(fast "1 2 3 4" $ sound "lt mt ht ~"),
(sound "clap:4(3,8)" # speed 2),
sound "[kick:5(5,8), snare:3(7,16,3)]"
]
-- Or adding a parameter that applies to the whole stack:
d1 $ stack [(fast "1 2 3 4" $ sound "lt mt ht ~"),
(sound "clap:4(3,8)" # speed 2),
sound "[kick:5(5,8), snare:3(7,16,3)]"
] # squiz "<0 2>"
-- So `overlay` and `stack` stack things up, so that they happen at
-- the same time. Howabout sticking things together over time, so they
-- happen one after another?
-- Like overlay and stack, there is one function, 'append' for
-- composing two patterns together, and another, 'cat' for composing a
-- list of patterns together.
-- For two patterns:
d1 $ append (fast "1 2 3 4" $ sound "lt mt ht ~")
(sound "clap:4(3,8)" # speed 2)
-- For a list of patterns:
d1 $ cat [fast "1 2 3 4" $ sound "lt mt ht ~",
sound "clap:4(3,8)" # speed 2,
sound "[kick:5(5,8), snare:3(7,16,3)]"
]
-- Again, you'll see `cat` used more often than `append`.
-- `append` and `cat` maintain the original 'density' of the patterns,
-- taking one cycle per cycle.
-- There are variants `fastappend` and `fastcat`, that take a cycle
-- from each of the patterns, and squash them all into a single cycle:
-- For two patterns:
d1 $ fastappend (fast "1 2 3 4" $ sound "lt mt ht ~")
(sound "clap:4(3,8)" # speed 2)
-- For a list of patterns:
d1 $ fastcat [fast "1 2 3 4" $ sound "lt mt ht ~",
sound "clap:4(3,8)" # speed 2,
sound "[kick:5(5,8), snare:3(7,16,3)]"
]
-- That's fine, but what if you don't want to loop between patterns a
-- cycle at a time, but have something between a `stack` and a `cat`,
-- where you can have the patterns overlap? `seqPLoop` is one answer.
-- With `seqPLoop`, you say when each pattern starts and stops.
-- Lets first emulate the `cat` from earlier, by having each
-- pattern last one cycle.
d1 $ seqPLoop [(0, 1, fast "1 2 3 4" $ sound "lt mt ht ~"),
(1, 2, sound "clap:4(3,8)" # speed 2),
(2, 3, sound "[kick:5(5,8), snare:3(7,16,3)]")
]
-- Now let's adjust the starts and stops, so the first two overlap by
-- a pattern, then there's a gap of a cycle before the last one plays:
d1 $ seqPLoop [(0, 2, fast "1 2 3 4" $ sound "lt mt ht ~"),
(1, 3, sound "clap:4(3,8)" # speed 2),
(5, 6, sound "[kick:5(5,8), snare:3(7,16,3)]")
]
-- If you want to use the same pattern more than once, you can give it a name
--, like this:
let florence = fast "1 2 3 4" $ sound "lt mt ht ~"
in
d1 $ seqPLoop [(0, 2, florence),
(1, 3, sound "clap:4(3,8)" # speed 2),
(3, 4, sound "[kick:5(5,8), snare:3(7,16,3)]"),
(3, 5, florence # coarse 5)
]
-- If you don't want the pattern sequence to loop, then use
-- seqP. You'll need to use something like `qtrigger`, so it starts
-- from cycle 0
d1 $ qtrigger 1 $ seqP [(0, 2, fast "1 2 3 4" $ sound "lt mt ht ~"),
(1, 3, sound "clap:4(3,8)" # speed 2),
(5, 6, sound "[kick:5(5,8), snare:3(7,16,3)]")
]