-- 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)]")
                       ]

-- Don't forger you can stack seqPLoop:
d3 $ stack [
    seqPLoop [
    (0, 2, s "[bd*2] hh bd sn:8"),
    (1, 3, s "[hh*4] bd bd sn:8"),
    (2, 4, s "bd bd sn:8 sn:8"),
    (4, 5, s "bd sn:8 [bd*2] sn:8")
    ],
    seqPLoop [
    (0, 2, s "jvbass(3,8)"),
    (2, 4, s "jvbass(5,8)"),
    (4, 5, s "jvbass*4" # speed 1.1)
    ]
]
