Math Makes Music...using Sonic Pi

Code adventure in the music-land in which we rely on mathematics to keep the music going on...

Math Makes Music...using Sonic Pi

Sonic Pi is a free software, which has its own language that lets you write code for the music you need. It is like programming your own musicians. The software is written by Sam Aaron and team and the language is fairly easy and conducive to play music using code. We will go through the code structure, figuring out ways to incorporate our math idea inside it and let us listen to our results.

Music 101 - Basic Music structure

Musical alphabet includes 7 letters namely, A B C D E F G . These notes fall inside a broader category called octaves. An octave is a sequence of notes in the above order starting from C, so, the sequence C-D-E-F-G-A-B is called an octave. A leftmost white key in a piano always start with a C in the lowest octave and gradually increases octaves multiple times as you go right.

There are steps in between these notes. So, you can essentially play a sound which is in between A and B which is called, an A sharp A# or B flat Bb . So now, the full sequence of notes in a single octave looks like this: C C# D D# E F F# G G# A A# B and the total notes count has grown to 12! As you can see that  the next step from B is always C because B does not have a sharp note to it, and the same goes for the note E.

Go over to this link to have a look at a virtual piano. All the white keys are one of A B C D E F G and all the black keys are one of C# D# F# G# A#. A lower octave will always have more bass and less treble than the octaves higher than those.

To represent a C note in the 4th octave,  we write it as C4. This is all the theory we need for this article.


Sonic Pi: Installation

It is extremely easy to install Sonic-Pi, just head over to their official website and download a copy of installer for your operating system. Let it finish installation and something like this should appear on your screen,

Sonic Pi: Software

This has a code editor on the left, some control buttons on the top and a waveform on the right.


Sonic-Pi: Basics

Okay now let's write our first instruction to play the C4 note.

play :C4

Click run button and hear a note being played. We can pause in between notes using

play :C4
sleep 1
play :D4

Now we know how to play notes with delays, but there is no music without loops, so let's do that,

loop do
	sleep 1
    	play :c4
    	sleep 1
    	play :d5
    end

If, in case, you do not want to loop forever, you can write 3.times do instead of loop do to loop for 3 times. And, of course, nested loops are possible. If you are a fan of Japanese animated shows, Death Note, the main character has a very iconic & recognizable theme sound which, when coded for sonic-pi looks like this:

loop do
  2.times do
    sleep 0.2
    play :d4
    sleep 0.2
    play :e5
    sleep 0.2
    play :d5
    sleep 0.2
    play :a4
    sleep 0.2
    play :f5
    sleep 0.2
    play :d5
    sleep 0.2
    play :a4
    sleep 0.2
    play :a5
    
    sleep 0.2
    play :d4
    sleep 0.2
    play :e5
    sleep 0.2
    play :d5
    sleep 0.2
    play :a4
    sleep 0.2
    play :f5
    sleep 0.2
    play :d5
    sleep 0.2
    play :a4
    sleep 0.2
    play :g5
  end
  
  #second time
  2.times do
    sleep 0.2
    play :a4
    sleep 0.2
    play :e5
    sleep 0.2
    play :c5
    sleep 0.2
    play :a4
    sleep 0.2
    play :f5
    sleep 0.2
    play :c5
    sleep 0.2
    play :a4
    sleep 0.2
    play :a5
    
    sleep 0.2
    play :d4
    sleep 0.2
    play :e5
    sleep 0.2
    play :c5
    sleep 0.2
    play :a4
    sleep 0.2
    play :f5
    sleep 0.2
    play :c5
    sleep 0.2
    play :a4
    sleep 0.2
    play :g5
  end
  
end

Now, as cool as this sounds, we lack some beats! Sonic-Pi comes preloaded with a large sample pack. Syntax to load a sample is simple, just write: sample :name_of_the_sample. Let us use a simple kick drum sample drum_heavy_kick, We also need another loop on a different thread, for that we add this to our code at the start,

in_thread do
  loop do
    sample :drum_heavy_kick, amp:1
    sleep 0.4
    
  end
end

It sounds a little authentic, but this how do we sync up the two threads? For that we will use cue and sync keywords! We cue from the thread we want to send signal from and to receive the signal we will use sync.

in_thread do
  sync "somecue"
  loop do
    sample :drum_heavy_kick, amp:1
    sleep 0.4
    
  end
end

loop do
  2.times do
    sleep 0.2
    cue "somecue"
    play :D4
    sleep 0.2
    play :e5
    sleep 0.2
    play :d5
    sleep 0.2
    play :a4
    sleep 0.2
    play :f5
    sleep 0.2
    play :d5
    sleep 0.2
    play :a4
    sleep 0.2
    play :a5
    
    sleep 0.2
    play :d4
    sleep 0.2
    play :e5
    sleep 0.2
    play :d5
    sleep 0.2
    play :a4
    sleep 0.2
    play :f5
    sleep 0.2
    play :d5
    sleep 0.2
    play :a4
    sleep 0.2
    play :g5
  end
  
  #second time
  2.times do
    sleep 0.2
    play :a4
    sleep 0.2
    play :e5
    sleep 0.2
    play :c5
    sleep 0.2
    play :a4
    sleep 0.2
    play :f5
    sleep 0.2
    play :c5
    sleep 0.2
    play :a4
    sleep 0.2
    play :a5
    
    sleep 0.2
    play :d4
    sleep 0.2
    play :e5
    sleep 0.2
    play :c5
    sleep 0.2
    play :a4
    sleep 0.2
    play :f5
    sleep 0.2
    play :c5
    
    sleep 0.2
    play :a4
    sleep 0.2
    play :g5
  end
end

Beat timings match with that of the notes being played now. Enough with the theme song, we need some mathematics to play music for us, so we pick up the famous Fibonacci series for that!

A function with parameters in Sonic-Pi looks like this,

# chord_player: A function to play a chord
define :chord_player do |root, repeats|
  repeats.times do
    play chord(root, :minor), release: 0.3
    sleep 0.5
  end
end

#calling chord_player
chord_player :e3, 2

Variables are simple too,

# definition
sample_name = :loop_amen

#usage
sample sample_name

Sonic-Pi: Fibonacci Series

The series looks like this: 1 1 2 3 5 8 13 21....Found the pattern? Just add last two numbers to generate the next! 1+1=2, 1+2=3, 2+3=5 and so on.... Check the diagram for the algorithm,

Pseudo-code

The only originality we will show will be in the selection of notes we play depending on the current number in the series. We generate the current number and we devide and take remainder from 7 so that we could assign one of the seven, full, notes to play.

#Our algorithm in a single function!
define :fib do
  a=1
  b=1
  loop do
    c=a+b
    a=b
    b=c
    play :a4 if c%7==0
    play :b4 if c%7==1
    play :c4 if c%7==2
    play :d4 if c%7==3
    play :e4 if c%7==4
    play :f4 if c%7==5
    play :g4 if c%7==6
    
    sleep 0.5
  end
end

#calling fib to start playing
fib

Play and listen to the sound of our universe! JK! It does not sound like Hans Zimmer but I still loved it, its maths. Play around with the code on Sonic-Pi to generate your algorithm to play sounds, maybe you will stumble upon something very beautiful! Enjoy...

Sign up for the blog-newsletter! I promise that we do not spam...