Entonasyon Analizi
Contents
9. Entonasyon Analizi#
9.1. Entonasyon Analizi#
Bir önceki defterimizde monofonik bir ses kaydında icra edilen ezgiyi sinyalin ardışık küçük kesitlerinde temel titreşim frekansı kestirimi yapıp bu değerlerden bir seri oluşturarak temsil etmiştik. Çizdirdiğimizde frekansın zamanla nasıl değiştiğini gözleyebildiğimiz bu dizilere frekans (zaman) serisi/dizisi adı verebiliriz. Bu defterde, ses sinyalinden otomatik analizle elde ettiğimiz bu dizilerin işlenmesini ele alacağız.
Frekans dizilerinin işlendiği birçok müzik sinyal işleme problemi vardır. Örneğin frekans dizisinden yola çıkarak nota dizisi tespit etmek, otomatik notaya dökme işlemi gerçekleştirmek isteyebiliriz. Veya elimizde eserin notası var ise nota ile ses kaydı arasında bir hizalama (zamanda eşleme) işlemi yapmak isteyebiliriz.
Bu defterde örnek uygulama olarak şu problemi ele alacağız: Klasik ve pop türünde Batı müziği kayıtları için nota frekanslarına dair yaygın kabul gören bir standart bulunmaktadır ve standart gerçek icra ile büyük oranda uyuşmaktadır. Ancak bu durum birçok müzik kültürü için geçerli değildir; bazı müzik kültürlerinde yaygın kabul gören standart bulunmamakta, bazılarında ise kabul gören standart bulunmakla beraber icra ile bazı yönlerden uyuşmazlık gözlenmektedir. İcra ile kuram arasında uyuşmazlıkların gözlendiği durumlarda ses sinyal işleme bize problemi tespit etme ve anlama konusunda yardımcı olabilir.
Örneğin Türk makam müziğinde Hüzzam makamını ele alalım. Bu makamda icra edilen müzikal aralıkların (notaların frekansları arası oranlar/uzaklıklar) yaygın kullanılan kuramda açıklanan ile uyumlu olmadığına birçok kaynakta değinilmektedir (örnek). Bu makamda bir icranın kaydından yola çıkarak otomatik analiz ile kayıtta kullanılan müzikal aralıkları tespit edebilir miyiz? Bu defterimizde bu problemi ele alalım.
Bunun için ilk olarak bir dizi kısa kaydı indirecek, frekans kestirimi yapıp frekans serilerini elde edeceğiz. Aşağıdaki hücreleri çalıştırarak bu işlemi gerçekleştirin ve ses kayıtlarını dinleyin.
İlk olarak kütüphanelerimiz kurup yükleyelim:
!pip install essentia
import os
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import numpy as np
import essentia.standard as ess
from scipy import signal
import urllib.request
from IPython.display import Audio
import librosa
Requirement already satisfied: essentia in /home/baris/miniconda3/envs/KitapYazim/lib/python3.9/site-packages (2.1b6.dev857)
Requirement already satisfied: six in /home/baris/miniconda3/envs/KitapYazim/lib/python3.9/site-packages (from essentia) (1.16.0)
Requirement already satisfied: pyyaml in /home/baris/miniconda3/envs/KitapYazim/lib/python3.9/site-packages (from essentia) (6.0)
Requirement already satisfied: numpy>=1.8.2 in /home/baris/miniconda3/envs/KitapYazim/lib/python3.9/site-packages (from essentia) (1.22.4)
[ INFO ] MusicExtractorSVM: no classifier models were configured by default
Hüzzam makamında 3 adet kayıt indirelim.
baglantilar = {'Tanburi Cemil':'https://archive.org/download/cd_volumes-2-3_tanburi-cemil-bey/disc2/02.01.%20Tanburi%20Cemil%20Bey%20-%20Huzzam%20Taksim_sample.mp3',
'Şükrü Tunar':'https://archive.org/download/cd_istanbul-1925_various-artists-deniz-kizikanuni-artaki-ha/disc1/01.%20Sukru%20Tunar%20-%20Huzzam%20Taksim_sample.mp3',
'Udi Hrant':'https://archive.org/download/06UdiHrantKenkulianHzzamArkrBaharhGrmedenYazGeldiGedtiHoknadzDurtmadz/06%20-%20Udi%20Hrant%20Kenkulian%20-%20H%C3%BCzzam%20%C5%9Eark%C4%B1%20Bahar%C4%B1%20G%C3%B6rmeden%20Yaz%20Geldi%20Ge%C3%A7ti%20-%20Hoknadz%20Durtmadz.mp3'
}
dosyalar = []
for muzisyen, link in baglantilar.items():
dosya = muzisyen + '.mp3'
dosyalar.append(dosya)
urllib.request.urlretrieve(link, dosya)
print(dosya, 'indirildi')
Tanburi Cemil.mp3 indirildi
Şükrü Tunar.mp3 indirildi
---------------------------------------------------------------------------
KeyboardInterrupt Traceback (most recent call last)
/tmp/ipykernel_9621/2934216479.py in <module>
8 dosya = muzisyen + '.mp3'
9 dosyalar.append(dosya)
---> 10 urllib.request.urlretrieve(link, dosya)
11 print(dosya, 'indirildi')
~/miniconda3/envs/KitapYazim/lib/python3.9/urllib/request.py in urlretrieve(url, filename, reporthook, data)
266
267 while True:
--> 268 block = fp.read(bs)
269 if not block:
270 break
~/miniconda3/envs/KitapYazim/lib/python3.9/http/client.py in read(self, amt)
461 # Amount is given, implement using readinto
462 b = bytearray(amt)
--> 463 n = self.readinto(b)
464 return memoryview(b)[:n].tobytes()
465 else:
~/miniconda3/envs/KitapYazim/lib/python3.9/http/client.py in readinto(self, b)
505 # connection, and the user is reading more bytes than will be provided
506 # (for example, reading in 1k chunks)
--> 507 n = self.fp.readinto(b)
508 if not n and b:
509 # Ideally, we would raise IncompleteRead if the content-length
~/miniconda3/envs/KitapYazim/lib/python3.9/socket.py in readinto(self, b)
702 while True:
703 try:
--> 704 return self._sock.recv_into(b)
705 except timeout:
706 self._timeout_occurred = True
~/miniconda3/envs/KitapYazim/lib/python3.9/ssl.py in recv_into(self, buffer, nbytes, flags)
1239 "non-zero flags not allowed in calls to recv_into() on %s" %
1240 self.__class__)
-> 1241 return self.read(nbytes, buffer)
1242 else:
1243 return super().recv_into(buffer, nbytes, flags)
~/miniconda3/envs/KitapYazim/lib/python3.9/ssl.py in read(self, len, buffer)
1097 try:
1098 if buffer is not None:
-> 1099 return self._sslobj.read(len, buffer)
1100 else:
1101 return self._sslobj.read(len)
KeyboardInterrupt:
Kayıtların ilk 30 saniyelik kısımlarını alarak Librosa.pyin fonksiyonu ile frekans serilerini elde edelim. Serileri çizdirelim.
ornekleme_fr = 44100
max_uzunluk = 30 # saniye cinsinden maksimum uzunluk
minF0 = 50 # Hz cinsinden gözlenmesi beklenen minimum frekans
maxF0 = 800 # Hz cinsinden gözlenmesi beklenen maksimum frekans
frekans_serileri = {} # dosya ismi ile frekans serisini eşleyen bir kütüphane oluşturalım
print('PYIN frekans kestirimi gerçekleştiriliyor')
for dosya in dosyalar:
muzik_sinyali = ess.MonoLoader(filename=dosya, sampleRate=ornekleme_fr)()
# Sinyal uzun ise kırpalım
muzik_sinyali = muzik_sinyali[:min(muzik_sinyali.size, int(max_uzunluk*ornekleme_fr))]
# PYIN ile temel titreşim frekans kestirimi
frekans_serisi_pyin, periyodiklik, periyodiklik_olasiligi = librosa.pyin(muzik_sinyali, fmin=minF0, fmax=maxF0, sr=ornekleme_fr)
frekans_serileri[dosya] = frekans_serisi_pyin
print(dosya, 'için frekans kestirimi tamamlandı')
PYIN frekans kestirimi gerçekleştiriliyor
Tanburi Cemil.mp3 için frekans kestirimi tamamlandı
Şükrü Tunar.mp3 için frekans kestirimi tamamlandı
Udi Hrant.mp3 için frekans kestirimi tamamlandı
Şimdi elde ettiğimiz frekans serilerini çizdirelim ve ses kayıtlarını dinleyelim.
dosya = dosyalar[0] # ilk kayıt
fig = plt.figure(figsize=(15,3))
plt.plot(frekans_serileri[dosya])
plt.title(dosya + " frekans serisi");
plt.xlabel('zaman (analiz pencere endeksi)');
plt.ylabel('f0(Hz)');
plt.grid()

Şekil 9.1: Tanburi Cemil kaydının temel titreşim frekans serisi
muzik_sinyali = ess.MonoLoader(filename=dosya, sampleRate=ornekleme_fr)()
muzik_sinyali = muzik_sinyali[:min(muzik_sinyali.size, int(max_uzunluk*ornekleme_fr))]
Audio(muzik_sinyali, rate=ornekleme_fr)