1
0
Fork 0

Toteutettu korkeamman tason funktioita

This commit is contained in:
Vili Sinervä 2022-10-01 16:27:12 +03:00
parent 83152ddc4a
commit 65a8d0abfd
4 changed files with 110 additions and 12 deletions

View file

@ -17,7 +17,7 @@ class MarkovKetju:
self._trie = trie self._trie = trie
self._aste = aste self._aste = aste
self._menneet_tilat = deque() self.menneet_tilat = deque()
def kasittele_opetusdata(self, opetusdata: list): def kasittele_opetusdata(self, opetusdata: list):
"""Lukee opetusdata Markovin ketjun omaan trie-rakenteeseen. """Lukee opetusdata Markovin ketjun omaan trie-rakenteeseen.
@ -43,24 +43,24 @@ class MarkovKetju:
""" """
if len(alkuosa) < self._aste: if len(alkuosa) < self._aste:
raise ValueError("Liian lyhyt alkuosa!") raise ValueError("Liian lyhyt alkuosa!")
self._menneet_tilat = deque([alkuosa[i] for i in range(0, self._aste)]) self.menneet_tilat = deque([alkuosa[i] for i in range(0, self._aste)])
def seuraava(self): def seuraava(self):
"""Antaa seuraavan merkin muilla funktioilla annettujen opetusdata ja alkuosan """Antaa seuraavan merkin muilla funktioilla annettujen opetusdata ja alkuosan
perusteella. Päivittää alkuosan automaattisesti seuraavaa askelta varten perusteella. Päivittää alkuosan automaattisesti seuraavaa askelta varten
""" """
if len(self._menneet_tilat) < self._aste: if len(self.menneet_tilat) < self._aste:
raise ValueError("Markovin ketjulle ei ole asetettu sopivaa alkuosaa!") raise ValueError("Markovin ketjulle ei ole asetettu sopivaa alkuosaa!")
todennakoisyydet, merkit = self._trie.etsi_seuraavat(self._menneet_tilat) todennakoisyydet, merkit = self._trie.etsi_seuraavat(self.menneet_tilat)
if todennakoisyydet and merkit: if todennakoisyydet and merkit:
#Valitsee merkeistä yhden, valinta painotetaan triessä olevien todennäköisyyksien avulla #Valitsee merkeistä yhden, valinta painotetaan triessä olevien todennäköisyyksien avulla
seuraava = choices(merkit, weights=todennakoisyydet)[0] seuraava = choices(merkit, weights=todennakoisyydet)[0]
#Päivittää alkuosan seuraavaa iteraatiota varten #Päivittää alkuosan seuraavaa iteraatiota varten
self._menneet_tilat.popleft() self.menneet_tilat.popleft()
self._menneet_tilat.append(seuraava) self.menneet_tilat.append(seuraava)
return seuraava return seuraava

View file

@ -18,7 +18,7 @@ savellaji_arvot = {
"Cb":1, "Cb":1,
} }
def LueMidi(tiedostopolku): def lue_midi(tiedostopolku):
midi = mido.MidiFile(tiedostopolku) midi = mido.MidiFile(tiedostopolku)
tulos = [] tulos = []
for raita in midi.tracks: for raita in midi.tracks:
@ -41,11 +41,11 @@ def LueMidi(tiedostopolku):
return tulos return tulos
def KirjoitaMidi(tiedostopolku, nuotit): def kirjoita_midi(tiedostopolku, nuotit, tempo=120):
midi = mido.MidiFile() midi = mido.MidiFile()
track = mido.MidiTrack() track = mido.MidiTrack()
track.append(mido.MetaMessage("set_tempo", tempo=mido.bpm2tempo(120), time=0)) track.append(mido.MetaMessage("set_tempo", tempo=mido.bpm2tempo(tempo), time=0))
track.append(mido.MetaMessage("time_signature")) track.append(mido.MetaMessage("time_signature"))
for nuotti in nuotit: for nuotti in nuotit:

View file

@ -0,0 +1,98 @@
from collections import deque
from glob import glob
from markov_ketju import MarkovKetju
from midi_kasittelija import lue_midi, kirjoita_midi
from trie import Trie
class MusiikkiGeneraattori:
def __init__(self):
self._ketju = None
self._nuotit = []
self._opetusdata = []
self._nuotti_midiksi = {
"C":0,
"C#":1,
"Db":1,
"D":2,
"D#":3,
"Eb":3,
"E":4,
"F":5,
"F#":6,
"Gb":6,
"G":7,
"G#":8,
"Ab":8,
"A":9,
"A#":10,
"Bb":10,
"B":11}
def lue_opetusdata(self, polku):
tiedostot = glob(polku)
self._opetusdata = []
for tiedosto in tiedostot:
try:
for x in lue_midi(tiedosto):
self._opetusdata.append(x)
except:
continue
def valmistele_ketju(self, alkuosa, aste=1):
alkuosa = self._nuotit_midiksi(alkuosa)
if len(alkuosa) < aste:
trie = Trie()
for jono in self._opetusdata:
if len(jono) > aste:
alkio = deque()
for i in range(0, len(jono)):
if len(alkio) > aste:
alkio.popleft()
alkio.append(jono[i])
for j in range(-len(alkio), 0):
trie.lisaa([alkio[x] for x in range(j, 0)])
alkuosa = [x for x in alkuosa]
while len(alkuosa) < aste:
self._ketju = MarkovKetju(len(alkuosa), trie)
self._ketju.aseta_alkuosa(alkuosa)
alkuosa += [self._ketju.seuraava()]
self._ketju = MarkovKetju(aste, trie)
self._ketju.aseta_alkuosa(alkuosa)
else:
self._ketju = MarkovKetju(aste)
self._ketju.kasittele_opetusdata(self._opetusdata)
self._ketju.aseta_alkuosa(alkuosa)
def generoi_nuotteja(self, n):
self._nuotit = list(self._ketju.menneet_tilat)
nuotteja = n - len(self._nuotit)
for i in range(nuotteja):
# Tunnistaa jos edellinen Markovin ketjun iteraatio palautti None
if not self._nuotit[-1]:
break
self._nuotit.append(self._ketju.seuraava())
return len(self._nuotit)
def kirjoita_midi(self, tiedostopolku, tempo=120):
kirjoita_midi(tiedostopolku, self._nuotit, tempo)
def _nuotit_midiksi(self, nuotit: str):
nuotit = nuotit.split(" ")
midi = []
for nuotti in nuotit:
arvo = (int(nuotti[-1])+1) * 12
arvo += self._nuotti_midiksi[nuotti[:-1]]
midi.append(arvo)
return midi
musiikki_generaattori = MusiikkiGeneraattori()

View file

@ -1,6 +1,6 @@
import os import os
import unittest import unittest
from midi_kasittelija import LueMidi, KirjoitaMidi from midi_kasittelija import lue_midi, kirjoita_midi
class TestMidiKasittelija(unittest.TestCase): class TestMidiKasittelija(unittest.TestCase):
def test_molemmat(self): def test_molemmat(self):
@ -9,6 +9,6 @@ class TestMidiKasittelija(unittest.TestCase):
os.remove(testi_polku) os.remove(testi_polku)
nuotit = [60, 62, 64] nuotit = [60, 62, 64]
KirjoitaMidi(testi_polku, nuotit) kirjoita_midi(testi_polku, nuotit)
luetut_nuotit = LueMidi(testi_polku)[0] luetut_nuotit = lue_midi(testi_polku)[0]
self.assertEqual(nuotit, luetut_nuotit) self.assertEqual(nuotit, luetut_nuotit)