Tuesday, August 9, 2016

Learn music for programmers with Sonci Pi - 04 - Jam Session

In second lesson we created random Chinese music generator just by randomly playing tones from pentatonic scale. But pentatonic scale is not the only one of course.

Theory


Diatonic Scale


The basic and most known is of course diatonic scale. It's the one all of you know C-D-E-F-G-A-B(H)-C. I will not go in to further details. First of all we already touch the basic in first lesson and second you can ready more on wikipedia.

Pentatonic Scale


We touch pentatonic scale in second lesson and we said it's the black keys on the piano, so C# D# F# G# A#. However in the music the difference between tones matter more then the frequencies so if you move all of them by half tones you again get pentatonic scale. If you are interested more you can go on and again wikipedia is good source

Jazz Scale


There is also jazz scale. A great deal of modern jazz harmony arises from the modes of the ascending form of the melodic minor scale, also known as the jazz melodic minor scale C D E-flat F G A B
Well there are many jazz scales and again rather then explain all, you can read wikipedia.

There are also other scales, but for today enough of theory.


Sonic PI


So the question is if  we can create the Chinese music by just randomly playing pentatonic scale can we create Jam session by "randomly" playing jazz scale?

Let's start with little repetition

Function

Just use define :name do |prametr1, parametr2| to define function, if you want it to be function  you must return some value, so then before the end use name = value
Below example is factorial function.

define :fact do |n|
  fact = (1..n).reduce(:*)||1
end

So with factorial and combination functions, I've create ghoose function from second lesson, choose "randomly" with Gaussian probability distribution, but this time it's general for any list.

define :gchoose do |list|
  fl = list.length
  choosen_index = (fl/2).to_i
  base = 2**(fl-1)
  index = 0
  (fl). times do
    #puts (combination (fl-1), index)
    choosen_index = index if one_in((base/(combination (fl-1), index)).to_i)
    index = inc index
  end
  ghoose = list[choosen_index]
end


Now we just play random notes from Jazz scale with random duration

loop do
  play (gchoose jazz_scale)
  sleep (gchoose durations)
end

Here is the complete code on github if you will play it you find out that it's not what you would expect. The problem is that it miss one important think, rhythm.

OK, let's add underlying rhythm (jazz use 4/4 time signature so easiest would be 4 quarter notes, F D D D for example).

#Basic rhythm
in_thread do
  loop do
    play (F-12)
    sleep 1
    3. times do
      play (D-12)
      sleep 1
    end
  end
end

We also need to sync the our "improvisation" part to reflect the time signature. We just set Total Duration to 4 and initiate Remaining Duration to the same. Choose Current Duration, if it's higher then remaining we cut it short and use remaining. Once RD is 0 we reset it to TD.

#Total Duration
TD = 4
#Remaining Duration
RD = TD

loop do
  play (gchoose jazz_scale)
  #Choosen Duration
  CD = gchoose durations
  if CD > RD
    CD = CD - RD
  end
  sleep CD
  RD = RD - CD
  if RD <= 0
    RD = TD
  end
end

The complete code is my github. If you will try to play it I think you find that even we add rhythm and it sound little more like jazz, it's actually terrible. If you use default choose function instead of my gchoose it sound better, but still not jam session.

So let's can we create Jam session by "randomly" playing jazz scale?
No, not even if add rhythm to it.

No comments: