Kısaca amaçtan bahsedeyim. Path ve Os aracılığıyla “Genres” değişkenine atanmış klasörlerin içerisindeki .wav dosyalarının özelliklerini Librosa ile alıp csv. dosyasına yazdıracağım. Kodun tamamı en alttadır.
Elimde şöyle bir kod var. Günlerdir anlamaya çalışıyorum. Çoğu kısmını anladım fakat bazı yerleri bana zorlama geldi.
Anlamadığım bir kısım burası;
header = 'filename chroma_stft rmse spectral_centroid spectral_bandwidth rolloff zero_crossing_rate'
for i in range(1, 21):
header += f' mfcc{i}'
header += ' label'
header = header.split()
Yukarıda neden range(1, 21) kadar mfcc içerisinde header içeriği oluşturmuş.
for e in mfcc:
to_append += f' {np.mean(e)}'
to_append += f' {g}'
Bu şekilde listeye atayarak yazdırmak yerine Pandas ile spesifik bir şekilde sütun ve satırlar oluşturup daha kısa ve işlevsel bir biçimde kod yazılabilir sanırım. Ama okuduğum kaynaklar varolan bir csv dosyasında metod ve fonksiyonların pratiğini yaptırıyor. Bunu nasıl yapacağımı bir türlü çözemedim.
Daha kullanışlı ve pratik bir yol varsa söyleyebilir misiniz?
Kodun tamamı;
import librosa
import pandas as pd
import numpy as np
import pathlib
import os
import csv
header = 'filename chroma_stft rmse spectral_centroid spectral_bandwidth rolloff zero_crossing_rate'
for i in range(1, 21):
header += f' mfcc{i}'
header += ' label'
header = header.split()
file = open('dataset.csv', 'w', newline='')
with file:
writer = csv.writer(file)
writer.writerow(header)
genres = 'blues classical country disco hiphop jazz metal pop reggae rock'.split()
for g in genres:
for filename in os.listdir(f'./drive/My Drive/genres/{g}'):
songname = f'./drive/My Drive/genres/{g}/{filename}'
y, sr = librosa.load(songname, mono=True, duration=30)
rmse = librosa.feature.rmse(y=y)
chroma_stft = librosa.feature.chroma_stft(y=y, sr=sr)
spec_cent = librosa.feature.spectral_centroid(y=y, sr=sr)
spec_bw = librosa.feature.spectral_bandwidth(y=y, sr=sr)
rolloff = librosa.feature.spectral_rolloff(y=y, sr=sr)
zcr = librosa.feature.zero_crossing_rate(y)
mfcc = librosa.feature.mfcc(y=y, sr=sr)
to_append = f'{filename} {np.mean(chroma_stft)} {np.mean(rmse)} {np.mean(spec_cent)} {np.mean(spec_bw)} {np.mean(rolloff)} {np.mean(zcr)}'
for e in mfcc:
to_append += f' {np.mean(e)}'
to_append += f' {g}'
file = open('dataset.csv', 'a', newline='')
with file:
writer = csv.writer(file)
writer.writerow(to_append.split())
Bunu örneklemek için şöyle birşey de yazabilirsiniz. Değişkene atadığımız bir dizin var. O dizin içerisinde bulunan 3 tane ses dosyasının boyutunu bir csv dosyasına yazdırsın.
Bunu yazarken Pandas ile faydalanırsak sorumun cevabı olmuş olacak.
Siz niye yapmiyorsunuz?
Kaynagi belli olmayan bir kodun nasil calistigini anlamaya calismaktan daha faydali olacaktir.
Problemi uce ayirmamiz lazim:
Dizindeki ses dosyalarini bulma.
Bir ses dosyasinin boyutunu ogrenme.
Ses dosyasi boyutuna benzer bir sayiyi CSV dosyasina yazdirma.
Bunlarin ucunun de birbirinden bagimsiz olmasi lazim, yoksa belirli bir sirayla ilerlemek gerekir.
Mesela yukaridaki kodda bagimsiz degiller ve yazdigim sirada ilerlememiz lazim. Elimizde ses dosyalari olmadigi icin kodu calistiramiyoruz. bkz: Soru Sorarken Sıkça Düşülen Hatalar#7
CSV yazmak icinse ve veriler hali hazirda Pandas formatinda degilse csv modulu daha iyi olacaktir.
wav = glob.glob(‘C:\Users\Furkan\Desktop\Klasör\*wav’)
wav1 = []
for w in wav:
wav1.append(w[31:])
print(wav1)
Çıktısı:
[‘blues.00000.wav’,
‘blues.00001.wav’,
‘blues.00002.wav’,
‘blues.00003.wav’,
‘blues.00004.wav’]
Tamam. Dosyaların isimlerini aldım, listeye atadım, ama şunun içerisine;
librosa.feature.rms(wav1)
Liste yollarsam normal olarak hata verir. Listedeki her elemanı yollamamın yolu index değerleriyle göndermek. İşte burada tıkanıyorum. Listedeki her elemanı tek tek yukarıdaki fonksiyona nasıl sokabilirim.
Kodu parçalara ayırdım ve tekrardan inceledim. Düşündüğüm kadar karmaşık olmadığını gördüm. Bu temel ve önemli bir işlem. Bir klasörün içerisindeki öğrelere erişip onları işleme koymak her zaman karşılaşacağım bir senaryo ve bu işlemde yetersiz olmak beni huzursuz etti. Ama sonunda mantığını anladım. Bu gece biraz daha pratik yaparsam gönül rahatlığıyla uyuyabilirim
Tekrardan yardımınız için teşekkür ederim. İyi çalışmalar.
Kodu (veya algoritmayi veya problemi) birbirinden bagimsiz parcalaya ayirabilmek yazilim tasariminin en temel becerisi. Soru sorarken bile eksigi/varligi hissedilebiliyor. Bu yuzden bu son mesajiniz beni sevindirdi.
import csv
import glob
def get_filenames():
return glob.glob('/tmp/*.png')
def get_audio_length(filename):
return len(filename) #TODO
def write_csv(filename, rows):
with open(filename, 'w') as f:
writer = csv.writer(f)
writer.writerows(rows)
def main():
files = get_filenames()
rows = [["Filename", "Audio Length"]]
for f in files:
audio_length = get_audio_length(f)
row = [f, audio_length]
rows.append(row)
write_csv('/tmp/files.csv', rows)
if __name__ == '__main__':
main()