Sonic Pi ile Biraz Kod Biraz Müzik

nafi durmuş
nafidurmus-blog
Published in
7 min readMay 3, 2020

İlk yazıda kod yazarak müzik yapacağımızı belirtmiştim. Önce ki bölümlerde de bunu yapmaya çalıştım. Bu bölümde biraz daha programlama kısmına giriş yapacağız ve farklı sesler ortaya çıkaracağız.

Önceki bölümlere göz atmak için bölüm 1(sonic pi nedir) , bölüm 2 (ses süresi ve genliği ayarlama) , bölüm 3 (örnek melodiler) , bölüm 4 (Rastgele Sayılar Kullanarak Müzik yapmak) bölümlere göz atabilirsiniz.

Şimdiye kadar hep play ile sleep metotları arasında kod yazdık diyebiliriz.

play 60
sleep 0.5
sample :elec_plip
sleep 0.5
play 75

Örnek bir melodiyi yukarıdan çalıştırabilirsiniz. Yukarıdaki gibi çalıştırdığımızda tek kez çalışıyor ve nerede başlayıp nerede bittiği belli değildi. Aşağıdaki gibi çalıştırırsak sonsuza kadar çalışacaktır ve nereden başladığını nerede bittiğini daha net görebiliriz.

loop do
play 60
sleep 0.5
sample :elec_plip
sleep 0.5
play 75
end

Yani loop do ile başlıyor end ile bitiyor.(yazacağımız bütün döngüler için örnek olması adına loop do ve end kullanılmıştır.) Bu ikisi arasında çalışıyor melodimiz. Şimdi ne demek istediğimi daha da anlayacaksınız. Yine yukarıdaki örnekle devam edelim.

play 60
sleep 0.5
sample :elec_plip
sleep 0.5
play 75

Yazmak istediğiniz melodide 4 kere kullanmak isterseniz yukarıdaki kodu nasıl yazmalıyız ?

play 60
sleep 0.5
sample :elec_plip
sleep 0.5
play 75
play 60
sleep 0.5
sample :elec_plip
sleep 0.5
play 75
play 60
sleep 0.5
sample :elec_plip
sleep 0.5
play 75
play 60
sleep 0.5
sample :elec_plip
sleep 0.5
play 75

Bu şekilde mi yazmalıyız ? Yoksa başka bir yöntemi mi var ? Tabi ki var 😃 Bu yöntemi döngü olarak adlandıracağız. Farklı türleri var onları ilerleyen bölümlerde göreceğiz.

4.times do
play 60
sleep 0.5
sample :elec_plip
sleep 0.5
play 75
end

Yukarıdaki gibi yazarsak daha sade ve daha okunaklı olduğunu görürsünüz. Şimdi bir kaç farklı melodiye birden fazla çalıştırarak güzel bir ses ortaya çıkaralım. Bu

4.times do
play 50
sleep 0.5
end

8.times do
play 55, release: 0.2
sleep 0.25
end

4.times do
play 50
sleep 0.5
end

Nasıl çıkan ses hoşunuza gitti değil mi ?

İstersek bu döngüleri iç içe kullanarak da güzel sesler çıkarabiliriz. Aşağıdaki kod parçasını çalıştıralım.

4.times do
sample :drum_heavy_kick
2.times do
sample :elec_blip2, rate: 2
sleep 0.25
end
sample :elec_snare
4.times do
sample :drum_tom_mid_soft
sleep 0.125
end
end

Çıkan sesler daha da güzelleşiyor. Çok fazla çalışmasını istiyorsanız yazının başında bahsettiğim sonsuz döngü şeklini kullanabilirsiniz.

loop do
sample :loop_amen
sleep sample_duration :loop_amen
end

Sonsuz döngüler siz durdurmadığınız sürece çalışır. Aşağıdaki kodu çalıştıralım.

loop do
play 50
sleep 1
end

sample :drum_cymbal_open

Sonsuz döngü ile başladığı için hiç bir zaman sample :drum_cymbal_open çalışmaz.

Şimdi çok faydalı olacak koşul belirtmemize yarayacak if-else den bahsedeceğim. Programlama ile azıcık uğraşan biri mutlaka duymuştur.

loop do

if one_in(2)
sample :drum_heavy_kick
else
sample :drum_cymbal_closed
end

sleep 0.5

end

Burada one_in(2)2/1 olasılıkla hangi sesin çalacağını belirtiyor.(rastgele melodi çaldığımız bölümden aşına olmalısınız) Birazdan daha işlevsel olarak kullanacağız. Daha iyi bir şekilde anlaşılacağını düşünüyorum.

Farklı bir örneğe bakalım.

use_synth :dsaw

loop do
play 50, amp: 0.3, release: 2
play 53, amp: 0.3, release: 2 if one_in(2)
play 57, amp: 0.3, release: 2 if one_in(3)
play 60, amp: 0.3, release: 2 if one_in(4)
sleep 1.5
end

Yukarıdaki kod parçasını çalıştırdığımızda aşağıdaki görselde işaretli olan alana bakalım.

play 50 sesi sabit şeklide çalıyor ve diğerleri farklı olasılıklarla çalıyor. Yani yine rastgele sesler oluşturduk.

İki tane sonsuz döngüyü birlikte kullanmak istersek in_thread kullanmalıyız. İlk olarak aşağıdaki kod parçasını çalıştıralım.

loop do
sample :drum_heavy_kick
sleep 1
end

loop do
use_synth :fm
play 40, release: 0.2
sleep 0.5
end

Yine sadece ilki çalıştı. in_thread ile birlikte kullanırsak iki döngün birlikte çalışmasını sağlıyoruz.

in_thread do
loop do
sample :drum_heavy_kick
sleep 1
end
end

loop do
use_synth :fm
play 40, release: 0.2
sleep 0.5
end

Birlikte çalıştığını biraz önce görselde gösterdiğim alana bakarak anlayabiliriz.

Eğer 3 döngü kullanmak istersek yine diğer bir döngüyü in_thread metodu için alarak kullanabiliriz.

in_thread do
loop do
sample :drum_heavy_kick
sleep 1
end
end

loop do
use_synth :fm
play 40, release: 0.2
sleep 0.5
end

loop do
use_synth :zawa
play 52, release: 2.5, phase: 2, amp: 0.5
sleep 2
end

Yukarıdaki gibi.

Önceki bölümlerde use_synth metoduyla birlikte kayıtlı sesleri öğrenmiştik. in_thread ile birlikte kullanalım.

play 50
sleep 1

in_thread do
use_synth :tb303
play 50
end

sleep 1
play 50

Ortadaki sesin farklı çıktığını duymuşsunuzdur. Bunun sebebi ilk çalışan sesin ikinci sesi etkilemesidir. Daha iyi anlamak için ilk olarak aşağıdaki kod parçasını çalıştıralım.(sadece play 55 i çalıştırsak değişen bişey olmaz)

in_thread do
play 55
end

Sonra aşağıdaki kod parçasını çalıştırarak sesin nasıl değiştiğine bakalım.

use_synth :tb303
play 50
sleep 1

in_thread do
play 55
end

İlk çalıştırdığımız sese göre ne kadar da farklı değiş mi ? Buna biz kalıtım diye adlandırabiliriz. Yani ilk çalışan sesten miras alarak ikinci ses etkilendi.

İstersek threadlara isim verebiliriz.

in_thread do
loop do
use_synth :prophet
play chord(:e2, :m7).choose, release: 0.6
sleep 0.5
end
end

in_thread(name: :drums) do
loop do
sample :elec_snare
sleep 1
end
end

Yine çalışırken biraz önce bahsettiğim alanı inceleyelim. İlkinde bişey yazmazken ikincide thread : drums olarak yazdığını görmüşsünüzdür.

Bu bölümde çok fazla kod bloğu yazarak karmaşıklığı arttırdık. Şimdi bu karmaşıklığı azaltmak için ne yapabileceğimize bakalım.

Bunu yapacağımızı fonksiyon diye adlanıracağız.(bütün programla dillerinde böyle geçiyor :d) Örnek bir fonksiyon aşağıdadır.

define :foo do
play 50
sleep 1
play 55
sleep 2
end

Bunu çalıştırırsanız sesin çıkmadığını fark edersiniz. foo adında bir fonksiyon oluşturmuş olduk. Şimdi bu oluşturduğumuz fonksiyonu kullanarak ses çıkaralım. Direk fonksiyonun adını yazarak çağırabiliriz.

define :foo do
play 50
sleep 1
play 55
sleep 0.5
end

foo

Şimdi biraz döngü ile kullanalım.

define :foo do
play 50
sleep 1
play 55
sleep 0.5
end

foo

sleep 1

2.times do
foo
end

Oluşturduğumuz fonksiyonu istediğimiz yerde çağırabiliriz. Fonksiyon oluştururken define kullandık istesek define yerine defonce de kullanabiliriz.

rrand metodu ile sayı aralığı girmiştik önceki bölümde min ve max değerleri alarak sesler üretmiştik. Şimdi buna benzer bir olayı fonksiyon yardımıyla yapacağız.

define :my_player do |n|
play n
end

my_player :C
sleep 0.5
my_player 95

Yukarıdaki kod parçasını çalıştırarak neler olduğunu görelim. Fonksiyonumuza kendi istediğimiz sesleri gönderebiliyoruz. Yani fonksiyonumuzu oluşturduktan sonra istediğimiz kadar çağırarak farklı sesleri çalabiliriz. Burada play metoduna :C ve 95 değerlerini göndererek sesler ürettik.(C nin ne olduğunu bilmiyorsanız 1. bölüme göz atabilirsiniz.)

Şimdi işleri biraz daha karmaşıklaştıralım ve fonksiyona 2 değer gönderelim.

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

chord_player :C, 2
sleep 1
chord_player :a3, 3
chord_player :E, 4
sleep 2
chord_player :e3, 3

Yukarıdaki kod parçasını inceleyelim. İlk olarak aşağıdaki satırdan başlayalım.

chord_player :C, 2

Oluşturduğumuz fonksiyon için 2 değer gönderiyoruz. Biri çıkacak sesimiz , diğeri ise bu sesin kaç defa çalacağı.(:C = root , 2 = repeats dir.)

Şimdi seslere nasıl isim verebileceğimizi görelim.

sample_name = :loop_amen

Verdiğimiz isimle sesi istediğimiz yerden çağırabiliriz.

sample_name = :loop_amen
sample sample_name

İsim vermemizin sebepleri ; karmaşıklığı ortadan kaldırma ve tekrarı ortadan kaldırmakdır. İsimlendirme yapmak kendimiz için de çok faydalıdır. Çok güzel bir kod bloğu yazdığımızı farz edelim. Ve isimlendirelim. Aradan süre geçti (2 ay) sonra başka bir proje için çalışıyoruz. Aaaa önce ben buraya iyi gidecek bir şeyi önceden yazmıştım diyip kullanabilirsiniz.

Örnek olarak sleep metodunu bile ismlendirebiliriz. Bekleme süresini daha sonra da kullanabiliriz.

loop_amen_duration = 1.7533
sleep loop_amen_duration

Aşağıdaki kod parçasına bakalım.

sample :loop_amen
sleep sample_duration(:loop_amen)
sample :loop_amen, rate: 0.5
sleep sample_duration(:loop_amen, rate: 0.5)
sample :loop_amen
sleep sample_duration(:loop_amen)

Çok fazla tekrar içerdiğini fark etmişsinizdir. Aşağıdaki gibi güncellersek ;

sample_name = :loop_amen
sample sample_name
sleep sample_duration(sample_name)
sample sample_name, rate: 0.5
sleep sample_duration(sample_name, rate: 0.5)
sample sample_name
sleep sample_duration(sample_name)

Şimdi daha anlaşılırdır.

Bu bölüm de ne kadar da çok öğrendik değil mi ? Öğreneceklerimiz daha bitmedi. Devam edelim. Aşağıdaki kod parçasına bakalım.

s = play 50, release: 8
sleep 2
control s, note: 62

İlk satırda s olarak adlandırdığımızı bir ses var ve çalışıyor. Son satırda ise control metoduyla s ile adlandırdığımız değişkeni çağırarak note: 62 değerini veriyoruz. Bu işlemleri log/kayıt (yazının bağındaki görseldeki alan) alanından takip edebilirsiniz.

Aşağıdaki kodu çalıştıralım ve kayıt/log alanına tekrar bakalım.

a = (ring 6, 5, 4, 3, 2, 1)

live_loop :shuffled do
a = a.shuffle
sleep 0.5
end

live_loop :sorted do
a = a.sort
sleep 0.5
puts "sorted: ", a
end

Burada tek bir liste (a) ile iki tane döngüye gönderdiğimizden karmaşıklık olabilir. Her döngü için ayrı listeler kullanmalıyız.

live_loop :shuffled do
a = (ring 6, 5, 4, 3, 2, 1)
a = a.shuffle
sleep 0.5
end

live_loop :sorted do
a = (ring 6, 5, 4, 3, 2, 1)
a = a.sort
sleep 0.5
puts "sorted: ", a
end

Kullandığımız in_thread sesleri hep birlikte çalıyordu. Bu sesleri cue ve sync metodları yardımıyla sıralı bir şekilde nasıl çalacağımızı öğrenelim. İlk olarak aşağıdaki kod parçasını çalıştıralım.

in_thread do
loop do
cue :tick
sleep 1
end
end

in_thread do
loop do
sync :tick
sample :drum_heavy_kick
end
end

cue her çalıştığında sesi kalp atışı(tick) gibi duyuyoruz. Bunun metonom gibi ses çıkardığını görebilirsiniz. (Metonom nedir ? Düzenli aralıklarla ses çıkaran alet diyebiliriz. Google metonom yazıp inceleyebilirsiniz. Sanatçılar için çok önemli bir konudur metronom. Ben de ukulele çalarken metronom ile düzenli çalışmalar yapıyorum.)

Daha iyi anlamak için aşağıdaki kod parçasını çalıştıralım.

in_thread do
loop do
cue [:foo, :bar, :baz].choose
sleep 0.5
end
end

in_thread do
loop do
sync :foo
sample :elec_beep
end
end

in_thread do
loop do
sync :bar
sample :elec_flip
end
end

in_thread do
loop do
sync :baz
sample :elec_blup
end
end

Bu bölümü burada bitiriyorum. Diğer bölüm daha eğlenceli olacak bol bol denemeler yapacağız. Diğer bölüm de görüşmek üzere.

bu yazıyı alkışlayarak bana destek olabilirsiniz.

Bana ulaşabileceğiniz iletişim adresleri,

nafidurmus.com| Twitter | Instagram | Facebook | Medium

Github| Linkedin | Youtube | Mail

Yararlandığım kaynak ;

ekran resmi

--

--