Week 5, lesson 2 - chords, arpeggios and.. Algoraoke

Ok warming up now! Here's a video exploring chords, arpeggios and the emerging form of Algoraoke, which I think was a term coined at the first live coding conference in Leeds by Ash Sagar. This video contains a preview of the next challenge, to make a 'cover version', which I'll write up in more detail a bit later..

Here's the worksheet:


-- Ok chords! We can play a 'major' chord like this:

d1 $ n "'maj" # sound "supermandolin"
  # legato 2 # gain 1.4

-- The default is c major, you can choose others like this, e.g. to
-- play c then e major:
d1 $ n "c'maj e'maj" # sound "supermandolin"
  # legato 2 # gain 1.4

-- Karaoke (algoraoke) time
-- Lets take the chord from a well known song:
-- https://ukutabs.com/r/radiohead/creep/

d1 $ n "<g'maj b'maj c'maj c'min>" # s "supermandolin"
  # room 0.6 # sz 0.9

-- and strum it a bit with struct:
d1 $ qtrigger 1 $ jux ((|- n "12") . rev) $ struct "t(5,8,<0 4>)" $ n "<g'maj b'maj c'maj c'min>" # s "supermandolin"
  # room 0.6 # sz 0.9

-- You can get a list of all the chords like this:
import Sound.Tidal.Chords

chordList

-- Try some out:
d1 $ n "c'sevenFlat9 a'm9sharp5" # sound "supermandolin"

-- Here's the raw data:
chordTable

-- Again, this all ends up being turned into plain note numbers. These
-- two patterns are the same:
d1 $ n "c'sevenFlat9 a'm9sharp5" # sound "supermandolin"

d1 $ n "[0,4,7,10,13] [9,10,23]" # sound "supermandolin"

-- You can say how many notes you want in a chord, with another ' and
-- the number of notes you want.

-- If you ask for more notes than exist in the basic chord, it will go
-- up the octaves to find more notes, sounding more and more impressive:
d1 $ n "c'maj'4" # s "superpiano"
d1 $ n "c'maj'8" # s "superpiano"
d1 $ n "c'maj'12" # s "superpiano"

-- This is clearer when we start doing.. ARPEGGIOS

-- These are 'broken' chords, where instead of playing the notes at
-- once, they're played one after another:
d1 $ arpeggiate $ n "c'maj" # s "superpiano"

-- The arpeggio happens within the 'step' that the chord occupies:
d1 $ arpeggiate $ n "c'maj e'min7" # s "superpiano"

-- Above, you can hear major chords have three notes, and minor 7
-- chords have four. You can modify that with ' so they have the same
-- number, if you want:
d1 $ arpeggiate $ n "c'maj'4 e'min7'4" # s "superpiano"

-- "arpeggiate" has a shorter, but more flexible cousin "arp", that
-- allows you to specify a different way of breaking up the chord:
d1 $ arp "updown thumbup" $ n "<c'maj'4 e'min7'4>" # s "superpiano"

-- Here's the list of currently available arp styles to explore:
-- up, down, updown, downup, converge, diverge, disconverge, pinkyup,
-- pinkyupdown, thumbup thumbupdown

-- Lots of fun
d1 $ jux rev $ arp "<updown thumbup pinkyupdown converge diverge>"
  $ n "<c4'maj'6 e4'min7'8 g5'maj'5 a5'maj'4>" # s "superpiano"
  # room 0.3 # sz 0.7
9 Likes

Here's the track I mention in the video (an absolute banger):

So here's a challenge - try and replicate the rhythm and tune of the bassline stab pattern that comes in at 0:40.

If you manage to solve it, you could share it here with 'spoiler tags' like this:
[details="spoiler"]
Your pattern goes here.
[/details]

Which then appears like this:

spoiler

Your pattern goes here.

Here's my rough attempt at replicating that bassline, no peeking until you've tried yourself..

spoiler

That first '~' was what threw me for a while. This is much more difficult to do if you try to start the cycle on the first '0'. Once you realise it's a four-step pattern followed by a six-step pattern, it starts making a lot more sense..

d1 $ slow 2 $ note "[~ 0 0 0] [1 1 3 3 3/2 ~]" # sound "jvbass"
  |* speed "[0.5,1,2,5]"
  |+ hpf (range 100 800 perlin) # hpq 0.4
  |+ note "<0 4>" # room 0.4 # sz 0.7

d2 $ iter 4 $ loopAt 1 $ chop 8 $ sound "break:4"
  # gain 1.2

You could make that pattern shorter, although I think in this case that just makes it less clear and harder to play with.. e.g.

 "[~ 0!3] [1!2 3!2 3/2 ~]"

I'd also like to specify inversions of chords.
Here's a haskell function that creates inversions of chords:

inversion :: Int -> [Int] -> [Int]
inversion _ [] = []
inversion n xs = drop n xs ++ [ x + 12 | x <- take n xs ]

But how do I integrate it with TidalCycles?

3 Likes

Ah, I forgot about inversions!

You can do it with roman numerals, e.g. c'maj'ii for second inversion. To specify number of notes in the chord put that immediately in front e.g. c'maj'4ii

10 Likes

Great! Can I do other voicings, too? Like Drop2?

If not, how would I go about building them in either with tidal functions or with haskell?

1 Like

setcps (170/240)

spoiler

d1 $ trigger 1 $ slow 2 $ n "[~ 0 0 0] [1 1 2 2 2 ~]" |+ n "<f4'min bf4'min>" # s "superpiano"

1 Like

Hm, you'd probably have to modify the mininotation parser in Sound.Tidal.ParseBP to support this. That might be a discussion for the innards category.

1 Like

I worked with the chords and trying to figure this one out. I do hear a gradual swing or change in the speed of the rhythm but I couldn't quite wrap my head around how to get that effect. I also think that I rely too much on setcps, and I think there are probably some limitations caused by how I use it.

Spoiler

setcps 0.2
d1 $ trigger 1 $ n "[~ 0 0 0] [1 1 2 2 2 ~]" |+ n "<f4'min bf4'min>" # s "superpiano"

1 Like

A post was merged into an existing topic: Challenge: Algoraoke!

I made a thread for the Algoraoke challenge over here -> Challenge: Algoraoke!

(I moved yours there @hujairi, hope that's ok!)

1 Like

:+1:

Is there a way to force the arpeggiation to play quarter notes, or sixteenth notes independently from the number of notes in the chord? For example d1 $ arpeggiate $ n "'maj 'maj7" # s "superpiano" will play 1/7 notes, is there a way to force these to be n-th notes?

I know that without arpeggiation, this accomplished with the % operator: d1 $ n "{0 4 7 0 4 7 11}%8" # s "superpiano" will solve the above, but without using the arpeggiate function.

So you'd like something like 'maj'4 that didn't add an extra note, but 'rotated' them, so you'd end up with "0 4 7 0"?

Then the question is whether the next cycle you should get "0 4 7 0" again or whether it should continue where it left off with "4 7 0 4"

Right so the idea is to be able to have any pattern of chords and still get an arpeggio that is still eight notes or n-th notes.

spoiler
d1 $ sometimes rev $ slow 4 $ note "[~ 0 0 0] [1 1 3 3 3/2 ~]" # sound "jvbass"
  |* speed "[0.5,1,2,5]"
  |+ hpf (range 100 800 perlin) # hpq 0.4
  |+ note "<0 4>" # room 0.4 # sz 0.7

d2 $ sometimes (degradeBy perlin) $ iter 2 $ loopAt 1 $ chop 4 $ sound "break:4"
  # gain 1.2

maybe not so much a spoiler, as it
is a remix, or a 'flip
with a reworking of code from
@yaxu and @hujairi or,
what do you call it?
[a decoding? | a re-coding? | mis-plagiarization? |
change some numbers add some things and call it something?]
I love that I don't even have to record any audio for you to hear it as a remix
:slight_smile: this is fun, thanks

Hi, wonderful news.
Here is my addition to the mystery algoraoke new genre, can anyone guess what this classic is?

d1 $ qtrigger 1 $ jux ((|- n"16") . rev) $ struct "t(3,11)"
                          $ n "<[-3,9,13,16,21] [1,9,13,16,20] [-6,9,13,16,18] [4,9,13,16] [-3,9,13,16] [6,9,13,18] [4,14,16,20] [4,14,16,20] [11,16,20,23][11,16,20,21][11,14,20][11,14,18] [4,11,14,20][-8,11,14,20][-3,9,13,16,21][1,9,13,16,21][-3,9,13,16,21][4,9,13,16,20][-6,9,13,16,18][-3,9,13,16] [10,16,18,22][6,16,18,22][-1,16,19,23][4,16,19,23][6,14,18,23][2,14,18,21][-3,13,16,21][1,13,18,22][-4,14,16,20][-8,14,16,20][-3,9,13,16,21][-8,9,13,16,21]>"
                          #sound "supersaw"

While trying to arrange other instruments (melody, drums) i stumbled upon a few issues, notation related i think. Help I'm a rock!

first a basic n pattern issue, i don't understand how

d1 $ n "0 2 1 2" #sound "kick:7 snare:6 hc:1"

..gives "kick kick snare closedhat" ! I'm lost.. I thought I would get "kick hat snare hat".

Then, I wanted several orbits (d1, d2, d3) to start playing together, karaoke style, but i didn't manage this either. Fun thing is i really had trouble getting the drums to coincide with the chords at all... Here is my code (the chords are finished, i only sketched the very start of the melody, and the drums are super basic). All in all, I would like to have a decent drum and a matching melody, I'm not so far from the end result once those issues resolved... Here is the "whole" project :

d1 $ qtrigger 1 $ jux ((|- n"16") . rev) $ struct "t(3,11)"
              $ n "<[-3,9,13,16,21] [1,9,13,16,20] [-6,9,13,16,18] [4,9,13,16] [-3,9,13,16] [6,9,13,18] [4,14,16,20] [4,14,16,20] [11,16,20,23][11,16,20,21][11,14,20][11,14,18] [4,11,14,20][-8,11,14,20][-3,9,13,16,21][1,9,13,16,21][-3,9,13,16,21][4,9,13,16,20][-6,9,13,16,18][-3,9,13,16] [10,16,18,22][6,16,18,22][-1,16,19,23][4,16,19,23][6,14,18,23][2,14,18,21][-3,13,16,21][1,13,18,22][-4,14,16,20][-8,14,16,20][-3,9,13,16,21][-8,9,13,16,21]>"
              #sound "supersaw"
              

d2 $ qtrigger 1 $ jux rev $ struct "t(3,11)" 
$ n"<[12 17] [12 16][12 14][12 24][12 0] [12 14] [12 16] [ 12 24] [ 12 24] >"
#sound "supersquare"
#legato 0.5


d3 $ sound "hc:12*8"
#gain 0.8

:slight_smile:

spoiler

d1 $ gain "[0 1 1 1]<[1 1 1 1 1 0]<[1 1 1 1 1 0][1 1 1 1 0 0]>>" # n ("<[[f4 f4][fs4 g4 g4]][bf4 bf4 b4 c c]>" |+ "'min") # s "superpiano"

1 Like

Just replying to the basic pattern bit of things for the moment:

My interpretation of your expectation is that you expect the numbers in the n pattern to index into that list to the right. Is that correct?

What's going to happen instead is that we're getting two pieces of information from the n pattern:

  1. Our pattern structure has four events in it (which is what you wanted, so all is well here!)
  2. If we're using a synth (which we're not, but for the same of completeness), we'll take notes 0, 1, and 2 in the order that you have them. If we're using a sampler (which we are!), we're going to pick sounds 0, 1, and 2 from whatever sample folder(s) is specified.

So, if all we had in the string to the right was "kick", we'd get, basically, "kick:0 kick:2 kick:1 kick:2" as our result.

If we had "kick snare hc" in our string to the right, we'd get kick:0 snare:2 hc:1 kick:2 because the first three in each string would line up, then the second string would loop back around to match a sample to the last event in the string on the left.

| event event event event | event event event event |
| kick  snare hc |  kick  | kick  snare hc |  kick  |

But because you're also specifying which sample to use in the second string, that's going to override the sample index specified in the n pattern, meaning the n pattern is only going to give you event timing, and all sound information is coming from the string on the right, giving us "kick:7 snare:6 hc:1 kick:7". I suspect that the "kick kick" that you're observing at the beginning is actually event four followed by event one.