Stories on maker education and innovation 

Home creativity Making Chord Progressions using Sonic Pi
formats

Making Chord Progressions using Sonic Pi

Music

I have to confess that I love music and code. When I get to share my two favorite things in one package, it gets me excited. In previous blog posts, I had talked about an amazing tool called Sonic-Pi for introducing music theory and computer science. While preparing this blog post, I had forgotten how much I enjoy generative music through code.

For the post today, we’re going to focus on making chord progressions and generating arpeggios. Let’s define a few terms before we dive into code.

  • Chords – In music theory, we define a chord as a named collection of notes.  In western music, there are two major flavors of chords. (Major and minor)  Major chords feel happy.   Minor chords are often used in movie scores to represent darker moments or points of anticipation.  For a more formal discussion of chords, check out this article from Wikipedia.  For the purpose of this blog post, keep in mind that a chord has three notes: the root, third, and fifth.
  • Chord progressions – Chord progressions define a sequence of chords that make up a song.    This sequence of chords represents a major component of the soul or emotional thread of a song.
  • Arpeggios – An arpeggio represents a way to play the notes of a chord over time.

We should note that chord progressions for the western ear follow patterns.   The human ear enjoys hearing chord changes according to the circle shown below.  To keep things simple, you can make small transitions between one area of this circle.   You can execute the following chord progression and your eye will believe that it’s pleasing: G,C,D,C.    If your song moves from a G major chord to a D flat major, your ear will not find this automatically pleasing.  It will probably sound weird.

 

Circle of fifths

Circle of fifths

 

With this brief overview of music theory, I wanted to share a small Sonic-Pi program I’m using to enable students to play with chords, chord progressions, and arpeggios. You can inspect the code here.

Let’s break down the major ideas:

In the following code, we configure Sonic-Pi to the tempo of 130 beats per minute(BPM). We also create a Ruby array to hold the list of chords. Sonic-Pi already has a function to generate major and minor chords. We add the chord to the array using a push method.

1
2
3
4
5
6
7
8
9
10
11
12
use_bpm(130)

chord_list = []

chord_list.push(chord(:D4,:minor))
chord_list.push(chord(:A4,:major))
chord_list.push(chord(:D4,:minor))
chord_list.push(chord(:c4,:major))
chord_list.push(chord(:F4,:major))
chord_list.push(chord(:c4,:major))
chord_list.push(chord(:D4,:minor))
chord_list.push(chord(:A4,:major))

We need some way to loop over the chord_list and play each of them. The following code accomplishes this. We place the loop in a thread so that this music idea can exist in parallel with other musical ideas. We configure Sonic-Pi to use the “dtri” synth because it’s cool. The “pick_pattern2” function is something I’ve written to render out our arpeggio.

1
2
3
4
5
6
7
8
in_thread do
  use_synth :dtri
  loop do
    for c in chord_list
      pick_pattern2(c)
    end
  end
end

Let’s define “pick_pattern2”. In the following Ruby function, we’re giving a small collection of code a name. We pass in a chord to be played. In Sonic-Pi, a chord is simply an array of notes. In the first part of the code, we generate 6 notes based on the chord. Element zero represents the root of the chord. Element 1 represents the third. Element 3 represents the fifth. We generate notes 4 to 6 to be one octave above the ones previously mentioned. The rest of the code plays out notes in a timed manner. In general, we’re placing each note a half beat away from each other. The sequence is more artistic than technical.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
def pick_pattern2(chord)
  note1 = chord[0]
  note2 = chord[1]
  note3 = chord[2]
  note4 = chord[0] + 12
  note5 = chord[1] + 12
  note6 = chord[2] + 12
 
  play(note1)
  sleep(0.5)
  play(note2)
  sleep(0.5)
 
  play(note3)
  sleep(0.5)
  play(note4)
  sleep(0.5)
 
  play(note5)
  sleep(0.5)
  play(note6)
  sleep(0.5)
 
  play(note3)
  sleep(0.5)
  play(note4)
  sleep(0.5)
 
end

There’s a few other functions for generating arpeggios. Feel free to play with them and edit them. If you make something cool, leave us a comment below. I’d love to hear what you’re making!!

Photo credit to Trey Jones.

 
 Share on Facebook Share on Twitter Share on Reddit Share on LinkedIn
No Comments  comments 
© Inspired To Educate
credit