260 Drum Machine Patterns

I'm doing a presentation where I take drum machine patterns found in popular music and recreate and mutate them using TidalCycles. The drum machine patterns I'm using as source material comes from the book 260 Drum Machine Patterns. It's from the 80s and has some great pattens in!

For the presentation I've transcribed a few into TidalCycles notation and thought I'd share them here. If anyone wants to transcribe and share others here please do! The book's still available in print and I recommend it.

Note about my transcriptions: mine are flipped i.e. BD is the first line. Also I used a pattern of #gain functions for programming accents. If there's a more efficient way please share. Also also I just googled the tempos but use whatever's comfortable.

-- Funk 13
setcps(90/60/4)

d1
$ stack [
struct ("1 0 0 0 0 0 1 1 0 0 1 0 0 0 0 0") $ sound "bd",
struct ("0 0 1 0 0 1 0 0 0 0 0 0 1 0 1 1") $ sound "sd",
struct ("1 0 1 1 1 0 1 0 1 1 0 1 0 1 1 0") $ sound "hc"
]
# gain "1 1 1.3 1 1 1 1 1 1 1 1 1 1.3 1 1 1"
-- Pop 10
setcps(100/60/4)

d1
$ stack [
struct ("1 0 1 0 0 0 0 0 1 1 0 1 0 1 0 1") $ sound "bd",
struct ("0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 0") $ sound "sd",
struct ("0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1") $ sound "ho",
struct ("1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0") $ sound "hc"
]
# gain "1 1 1 1 1.3 1 1 1 1 1 1 1 1.3 1 1 1"
-- Disco 8
setcps(120/60/4)

d1
$ stack [
struct ("1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0") $ sound "bd",
struct ("1 0 1 0 1 0 0 0 0 0 0 0 1 0 0 0") $ sound "cp",
struct ("0 0 0 0 1 0 0 0 0 0 0 1 1 0 0 0") $ sound "sd",
struct ("0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 1") $ sound "ho",
struct ("1 1 1 0 0 1 1 0 1 1 1 0 0 1 1 0") $ sound "hc"
]
-- Rock 12
setcps(110/60/4)

d1
$ stack [
struct ("1 0 1 0 0 0 1 0 0 0 1 0 0 0 0 0") $ sound "bd",
struct ("0 0 0 0 1 0 0 0 0 1 0 0 1 0 0 0") $ sound "sd",
struct ("1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0") $ sound "hc"
]
# gain "1 1 1 1 1.3 1 1 1 1 1 1 1 1.3 1 1 1"
-- R&B 12
setcps(80/60/4)

d1
$ stack [
struct ("1 0 1 0 0 0 0 1 1 0 1 0 0 1 1 0") $ sound "bd",
struct ("0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0") $ sound "sd",
struct ("0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0") $ sound "ho",
struct ("1 1 0 1 1 1 0 1 1 1 0 1 1 1 0 1") $ sound "hc"
]
# gain ("1 1 1 1 1.3 1 1 1 1.3 1 1 1 1.3 1 1 1")
18 Likes

Still very much of a beginner, I did experiment in a similar way with some of these Dance Music Rudiments.

I used set functions to be able to change the drum kit. If this could be done easier or more elegantly I am very much open for suggestions.

Generally I think in case of the representation of drum machine patterns it boils down to a balance between transparency (can you see what will happen) versus economy (can you easily edit and change things) or: can you omit redundancy and explicitness without loosing clarity and flexiblity. In this respect your version, @hellocatfood, is much easier to comprehend.

do
  setI "i" $ 0    -- i = hihat
  setI "s" $ 10   -- s = snare
  setI "k" $ 4    -- k = kick
  setS "f" $ "ab" -- f = kit or folder

do
  setI "i" $ 2
  setI "s" $ 1
  setI "k" $ 0
  setS "f" $ "drum"

do
  setI "i" $ 5 -- 5, 28
  setI "s" $ 2  -- 2, 20, 22, 23
  setI "k" $ 13
  setS "f" $ "gretsch"

setcps (150/60/4)

d1 $ stack [
   (slow 2 $ n "^i ~ ^i ~   ^i ~ ^i ^i   ^i ~ ^i ~   ^i ~ ^i ~   ^i ~ ^i ~   ^i ~ ^i ~   ^i ~ ^i ~   ^i ~ ^i ~ " # s "^f"),
   (slow 2 $ n "~ ~ ~ ~   ^s ~ ~ ~   ~ ^s ~ ~   ~ ~ ^s ~   ~ ~ ~ ~   ~ ~ ^s ~  ~ ^s ~ ~  ^s ~ ~ ~ " # s "^f"),
   (slow 2 $ n "^k ~ ~ ~   ~ ~ ~ ~   ~ ~ ^k ~   ~ ~ ~ ~  ~ ~ ^k ~   ~ ~ ~ ~   ~ ~ ^k ~   ~ ~ ~ ~ " # s "^f")
]

-- or, with some additional randomization and short syntax
-- (which makes it much more dense to understand)

d1 $ stack [
   (n "[^i ~ ^i ~]*4" # s "^f"),
   (n "<~!4   ^s ~!3   ~!4   ^s ~!3 . ~!4   ~ ~ ^s ~   ~!4   ^s ~ ~ ~ >" # gain "1" # s "^f"),
   (n "<~ ~ ^s ~   ~ ~ ~ ~   ^s ~ ~ [^s ^s]   ~ ~ ^s ^s . ~ ~ ~ ~   ^s ~ ~ ~   ~ ~ ^s ~   ~ ~ ~ ~ >" # gain (range 0.35 0.75 rand) # s "^f"),
   (n "<^k ~!3   ~ ~ ^k ~   ~ ~ ^k ~   ~!4 . ~ ~ ^k ~   ~!4   ^k ~!3 ~!4>" # s "^f")
]

6 Likes

I'd love to work through some of this with you folks! Is there a place I can find scans of the book for free? I was curious about why you used super long struct strings to define the rhythms, but then I saw the cover of the book and it made sense lol.

There is a version available at archive.org:

2 Likes

Love your idea of transcribing the patterns!

A way to avoid always typing it out would be this function:

    accent :: [Integer] -> Pattern ControlMap
    accent ds = gain accs
            where accs = withEvent (\e -> if elem (eventPartStart e) fracs  then e{value = 1.3 } else e) ("1*16"::Pattern Double)
                  fracs = [(i-1)%16 | i <- ds]

The function takes a list of values from 1 to 16 and will accentuate the notes in the corresponding beats.
So now you could type:

d1
$ stack [
struct ("1 0 0 0 0 0 1 1 0 0 1 0 0 0 0 0") $ sound "bd",
struct ("0 0 1 0 0 1 0 0 0 0 0 0 1 0 1 1") $ sound "sd",
struct ("1 0 1 1 1 0 1 0 1 1 0 1 0 1 1 0") $ sound "hc"
]
# accent [3,13]

Edit: I just tried it with sound and apperently it doesn't work unfortunately. I'll have to think about it some more haha

2 Likes

So here is some code that actually works, if someone is interested:

accent ds = gain (fast 16 $ Sound.Tidal.Core.fromList accs)
          where accs = [ f x | x <- [1..16]]
                f x = if elem x ds then 1.3 else 1
5 Likes

Thanks, this works great! I think for the presentation I'm doing I'll stick to the way of transcribing I'm currently using but if I transcribe more and post them here I'll use your method.

Here's the presentation I mentioned where I used the drum patterns

https://www.youtube.com/watch?v=MMTIdAGu0R4

I'll be working on transcribing the rest of the drum patterns into Tidal notation at some point

7 Likes

Hello,

fyi, I've just found that library of drum patterns (almost 500) in SC:
https://github.com/lvm/SuperUtilities/blob/master/classes/DrumLoop.sc
and its equivalent in Tidal (but I have not tested it) :
https://github.com/lvm/tidal-drum-patterns

Christophe

3 Likes

oh wow that's amazing! Thanks for sharing and thanks @mauro for making it!

This is cool!

I did a gist with a collection of popular beats from a drum YouTuber a couple of years back.

Maybe its time to get cracking on the this new book you suggested.

1 Like

Fun experiment. I wanted to play these patterns while retaining the ability to see them in my editor. I am using vim-tidal. I just mapped various shortcuts in my .vimrc that I can summon when editing .tidal files:

autocmd FileType tidal call s:tidal_abbr()
function! s:tidal_abbr()
    inoreabbr billybd "[t ~ ~ ~] [~ ~ ~ ~] [t ~ ~ ~] [~ ~ ~ ~]"
    inoreabbr billysn "[~ ~ ~ ~] [t ~ ~ ~] [~ ~ ~ ~] [t ~ ~ ~]"
    inoreabbr billych "[t ~ t ~] [t ~ t ~] [t ~ t ~] [t ~ t ~]"
    inoreabbr bluemondaybd "[t ~ ~ ~] [~ ~ ~ ~] [t ~ ~ ~] [~ ~ ~ ~]"
    inoreabbr bluemondaysn "[~ ~ ~ ~] [t ~ ~ ~] [~ ~ ~ ~] [t ~ ~ ~]"
    inoreabbr bluemondaycp "[~ ~ ~ ~] [t ~ ~ ~] [~ ~ ~ ~] [t ~ ~ ~]"
    inoreabbr bluemondayoh "[~ ~ t ~] [~ ~ t ~] [~ ~ t ~] [~ ~ t ~]"
    ... etc ...
endfunction

I could have found better names for them but so far so good.

1 Like

I was wondering how to make this a bit more dynamic, where you can pass the pattern length as the second parameter... it seems I run into a type error when doing this...

accent ds lg = gain (fast lg $ Sound.Tidal.Core.fromList accs)
          where accs = [ f x | x <- [1..lg]]
                f x = if elem x ds then 1.3 else 1

Where lg is length

The error is...

enumFromTo: not supported for patterns

The following should work

let 
_accent :: Int -> [Int] -> ControlPattern
_accent l ds = gain (fast (pure $ fromIntegral l) $ Sound.Tidal.Context.fromList accs)
          where accs = [ f x | x <- [1..l]]
                f x = if elem x ds then 1.3 else 1
accent = tParam _accent

Note that the arguments are switched though

2 Likes

Hi i was wondering if anyone tested @mauro drum pattern for tidal and can help me out. After the installation I get this errors for every module when I try to ghci :browse the module

Here's an example:

: error:

Could not find module ‘Sound.Tidal.Drum.Amen’

It is not a module in the current program, or in any known package.

Prelude>

I am fairly new to tidal and haskell so its bit confusing to me, seems like I have wrong directory?

Thanks

I'm working on the idea of having rhythm patterns pre-written in order to invoke them quickly in a live situation.

In GitHub - Rafrobeat/tidal-drum-patterns: TidalCycles / Haskell modules of drum patterns. there is a big list of patterns, forked from the one by lvm linked in the comments above, with some corrections and some new entries.

The problem I find there is that it's slow to use them in a live situation: first, you have to import the rhythm you want (import Sound.Tidal.Drum.ItaloDisco1a as I), and then you can use it as struct (I.bd) $ s "bd" and so on.

I'm putting together a refactoring of this code, in order to make using these patterns a much more immediate thing.

In my BootTidal.hs, I include another file called rhythm.hs with this content:

import qualified Data.Map as M

afro1a = M.fromList [ ("bd", "[t ~ ~ ~] [~ ~ ~ ~] [t ~ ~ ~] [~ ~ ~ ~] " :: Pattern Bool), ("hh", "[t ~ t t] [t ~ t ~] [t ~ t ~] [t ~ t ~] " :: Pattern Bool), ("rim", "[~ ~ ~ ~] [~ ~ t ~] [~ ~ t ~] [~ ~ t ~] " :: Pattern Bool) ]
afro1b = M.fromList [ ("bd", "[t ~ ~ ~] [~ ~ ~ ~] [t ~ t ~] [~ ~ t ~] " :: Pattern Bool), ("hh", "[t ~ t t] [t ~ t ~] [t ~ t ~] [t ~ t ~] " :: Pattern Bool), ("rim", "[~ ~ ~ ~] [~ ~ t ~] [~ ~ ~ ~] [t ~ ~ ~] " :: Pattern Bool) ]

rhythms = M.fromList [("afro1a", afro1a), ("afro1b", afro1b)]

r name instrument = struct (M.findWithDefault ("" :: Pattern Bool) instrument (M.findWithDefault M.empty name rhythms))

With this, you get a new function r (because I can't spell rhythm quickly without mistakes) that you can use like this:

d1 $ r "afro1a" "hh" $ s "808hc"

This seems to work, and the idea is adding some/all the rhythms in here.

Note that I'm fairly new to Haskell and there are some things I would like to improve:

  • I can't split these dictionaries in multiple lines without the Haskell interpreter complaining.
  • I can't add the r signature without the interpreter complaining (it doesn't like the expression r :: in this context).
  • I would like to hide the afro1a, afro1b and rhythms names from the global scope.

Apart from that, what do you think about this idea?

1 Like

Using an "hs" file means things are getting executed as if you were in interactive mode (ghci), so your first two problems can be solved by using the multiline delimiters :{ and :}.

But being in interactive mode means you can't (as far as I know) easily hide the names in a different scope - I think at best you could obfuscate the names by prefixing them with underscores but that's not particularly elegant.

This should work:

:{
r name instrument = struct (M.findWithDefault ("" :: Pattern Bool) instrument (M.findWithDefault M.empty name rhythms))
  where rhythms = M.fromList [("afro1a", afro1a), ("afro1b", afro1b)] 
        afro1a = M.fromList [ ("bd", "[t ~ ~ ~] [~ ~ ~ ~] [t ~ ~ ~] [~ ~ ~ ~] " :: Pattern Bool), ("hh", "[t ~ t t] [t ~ t ~] [t ~ t ~] [t ~ t ~] " :: Pattern Bool), ("rim", "[~ ~ ~ ~] [~ ~ t ~] [~ ~ t ~] [~ ~ t ~] " :: Pattern Bool) ]
        afro1b = M.fromList [ ("bd", "[t ~ ~ ~] [~ ~ ~ ~] [t ~ t ~] [~ ~ t ~] " :: Pattern Bool), ("hh", "[t ~ t t] [t ~ t ~] [t ~ t ~] [t ~ t ~] " :: Pattern Bool), ("rim", "[~ ~ ~ ~] [~ ~ t ~] [~ ~ ~ ~] [t ~ ~ ~] " :: Pattern Bool) ]
:}

You should be able to add the type signature in there as well

This is my code right now:

import qualified Data.Map as M

:{

rhythms = M.fromList [
  ("afro1a",
  M.fromList [
    ("bd", "[t ~ ~ ~] [~ ~ ~ ~] [t ~ ~ ~] [~ ~ ~ ~] " :: Pattern Bool),
    ("hh", "[t ~ t t] [t ~ t ~] [t ~ t ~] [t ~ t ~] " :: Pattern Bool),
    ("rim", "[~ ~ ~ ~] [~ ~ t ~] [~ ~ t ~] [~ ~ t ~] " :: Pattern Bool) ]
    ),
...
  ("yamama",
  M.fromList [
    ("bd", "[t ~ ~ ~] [~ ~ ~ t] [t ~ ~ ~] [~ ~ ~ ~]" :: Pattern Bool),
    ("cr", "[~ ~ ~ ~] [t ~ ~ ~] [~ ~ ~ ~] [t ~ ~ ~]" :: Pattern Bool) ]
  )
  ]

:}

let
_r name instrument = struct (M.findWithDefault ("" :: Pattern Bool) instrument (M.findWithDefault M.empty name rhythms))
r = tParam2 _r

It works fine, and can invoke any of them and pattern them with just:

r "<funk7c afro1a afro1b>" "hh" $ s "efmhhclose" # gain 0.9,

Love to see this. Makes me hope someday there'll be a package-manager like tool for everyone to share loops with each other.

2 Likes