From 4bf5257534c9fcffba844d182c307950ddb87429 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vili=20Sinerv=C3=A4?= Date: Sat, 1 Oct 2022 20:57:46 +0300 Subject: [PATCH] Siisti koodia --- .coveragerc | 2 +- src/main.py | 1 + src/midi_kasittelija.py | 18 +++++++++------ src/musiikki_generaattori.py | 40 ++++++++++++++++++++++----------- src/ui.py | 43 ++++++++++++++++++++++++------------ 5 files changed, 69 insertions(+), 35 deletions(-) diff --git a/.coveragerc b/.coveragerc index 06ab5ed..31861db 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,3 +1,3 @@ [run] source = src -omit = src/main.py,src/**/__init__.py,src/tests/**,src/ui* +omit = src/main.py,src/**/__init__.py,src/tests/**,src/ui.py,src/musiikki_generaattori.py diff --git a/src/main.py b/src/main.py index ffaed8d..d68a637 100644 --- a/src/main.py +++ b/src/main.py @@ -1,3 +1,4 @@ +"""Päämoduuli. Käynnistää ainoastaan UI:n""" from ui import UI ui = UI() diff --git a/src/midi_kasittelija.py b/src/midi_kasittelija.py index 78e8b5c..691a65b 100644 --- a/src/midi_kasittelija.py +++ b/src/midi_kasittelija.py @@ -1,3 +1,6 @@ +"""Mahdollistaa MIDI-tiedostojen lukemisen ja kirjoittamisen. +from midi_kasittelija imort lue_midi, kirjoita_midi +""" import mido savellaji_arvot = { @@ -19,6 +22,7 @@ savellaji_arvot = { } def lue_midi(tiedostopolku): + """Lukee nuotit MIDI tiedostosta""" midi = mido.MidiFile(tiedostopolku) tulos = [] for raita in midi.tracks: @@ -42,17 +46,17 @@ def lue_midi(tiedostopolku): return tulos def kirjoita_midi(tiedostopolku, nuotit, tempo=120): + """Kirjoittaa halutut nuotit valittuun MIDI-tiedostoon annetulla tempolla""" midi = mido.MidiFile() - track = mido.MidiTrack() + raita = mido.MidiTrack() - track.append(mido.MetaMessage("set_tempo", tempo=mido.bpm2tempo(tempo), time=0)) - track.append(mido.MetaMessage("time_signature")) + raita.append(mido.MetaMessage("set_tempo", tempo=mido.bpm2tempo(tempo), time=0)) + raita.append(mido.MetaMessage("time_signature")) for nuotti in nuotit: if nuotti: - track.append(mido.Message("note_on", note=nuotti, velocity=64, time=0)) - track.append(mido.Message("note_on", note=nuotti, velocity=0, time=480)) - - midi.tracks.append(track) + raita.append(mido.Message("note_on", note=nuotti, velocity=64, time=0)) + raita.append(mido.Message("note_on", note=nuotti, velocity=0, time=480)) + midi.tracks.append(raita) midi.save(tiedostopolku) diff --git a/src/musiikki_generaattori.py b/src/musiikki_generaattori.py index 044630d..9aeab3b 100644 --- a/src/musiikki_generaattori.py +++ b/src/musiikki_generaattori.py @@ -1,11 +1,14 @@ +"""Mahdollistaa musiikin generoinnin Markovin ketjujen avulla. +from musiikki_generaattori import musiikki_generaattori +""" from collections import deque from glob import glob from markov_ketju import MarkovKetju -from midi_kasittelija import lue_midi, kirjoita_midi +from midi_kasittelija import lue_midi, kirjoita_midi from trie import Trie - class MusiikkiGeneraattori: + """Yhden instanssin luokka musiikin generoimiseen.""" def __init__(self): self._ketju = None self._nuotit = [] @@ -31,34 +34,42 @@ class MusiikkiGeneraattori: "B":11} def lue_opetusdata(self, polku): + """Lukee nuotit annetun polun MIDI-tiedostoista. + Useamman tiedoston lukeminen *-merkillä esim 'kansio/*.mid' + """ tiedostot = glob(polku) self._opetusdata = [] for tiedosto in tiedostot: try: - for x in lue_midi(tiedosto): - self._opetusdata.append(x) - except: + for jono in lue_midi(tiedosto): + self._opetusdata.append(jono) + # Kaikki virheet halutaan ohittaa + except: # pylint: disable=bare-except continue def valmistele_ketju(self, alkuosa, aste=1): + """Luo ja valmistelee halutun asteisen Markovin ketjun annetulla alkuosalla""" alkuosa = self._nuotit_midiksi(alkuosa) if len(alkuosa) < aste: trie = Trie() + # Rakentaa poikkeuksellisesti Trien, jossa on kaikki ENINTÄÄN 'aste' mittaiset alkiot, + # jotka löytyvät opetusdatasta. for jono in self._opetusdata: if len(jono) > aste: alkio = deque() - for i in range(0, len(jono)): + for nuotti in 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)]) + alkio.append(nuotti) + for i in range(-len(alkio), 0): + trie.lisaa([alkio[x] for x in range(i, 0)]) - alkuosa = [x for x in alkuosa] + # Täydentää alkuosan riittävän pitkäksi käyttämällä asteittain pidempiä Markovin ketjuja + alkuosa = list(alkuosa) while len(alkuosa) < aste: self._ketju = MarkovKetju(len(alkuosa), trie) self._ketju.aseta_alkuosa(alkuosa) @@ -72,10 +83,11 @@ class MusiikkiGeneraattori: self._ketju.kasittele_opetusdata(self._opetusdata) self._ketju.aseta_alkuosa(alkuosa) - def generoi_nuotteja(self, n): + def generoi_nuotteja(self, maara): + """Generoi halutun määrän nuotteja aiemmin alustetulla Markovin ketjulla""" self._nuotit = list(self._ketju.menneet_tilat) - nuotteja = n - len(self._nuotit) - for i in range(nuotteja): + nuotteja = maara - len(self._nuotit) + for _ in range(nuotteja): # Tunnistaa jos edellinen Markovin ketjun iteraatio palautti None if not self._nuotit[-1]: break @@ -84,9 +96,11 @@ class MusiikkiGeneraattori: return len(self._nuotit) def kirjoita_midi(self, tiedostopolku, tempo=120): + """Kirjoittaa nuotit MIDI-tiedostoon halutulla tempolla""" kirjoita_midi(tiedostopolku, self._nuotit, tempo) def _nuotit_midiksi(self, nuotit: str): + """Muuttaa perinteiset nuottimerkinnät kuten C#4 MIDI-arvoiksi""" nuotit = nuotit.split("|") midi = [] for nuotti in nuotit: diff --git a/src/ui.py b/src/ui.py index f67c3fc..db8bba4 100644 --- a/src/ui.py +++ b/src/ui.py @@ -1,9 +1,12 @@ +"""Musiikki generaattorin tekstipohjainen käyttöliittymä +from ui import UI""" from os import system, name from re import search from sys import exit as sys_exit from musiikki_generaattori import musiikki_generaattori -class UI: +class UI: # pylint: disable=too-few-public-methods, too-many-instance-attributes + """Tekstipohjainen käyttöliittymä. Käynnistyy automaattisesti, kun olio luodaan""" def __init__(self): self._opetusdata_polku = "opetusdata/*.mid" self._tulos_polku = "savelma.mid" @@ -13,15 +16,24 @@ class UI: self._tempo = 120 self._toiminnot = { - "A": ("(A)pu", self._tulosta_apu, 0, "Tulosta apu"), - "O": ("(O)petusdata [polku]", self._aseta_opetusdata, 1, "Valitse opetusdata"), - "P": ("(P)olku [polku]", self._aseta_tulos_polku, 1, "Valitse valmiin sävelmän polku"), - "K": ("(K)etjun aste", self._aseta_aste, 1, "Aseta Markovin ketjun aste valittuun kokonaislukuun"), - "L": ("a(L)kuosa [merkkijono]", self._aseta_alkuosa, 1, "Aseta alkuosa. Esim. 'C4|D#5|Gb3'"), - "N": ("(N)uotteja [luku]", self._aseta_nuottien_maara, 1, "Aseta sävelmän nuottien määrä valittuun kokonaislukuun"), - "T": ("(T)empo [luku]", self._aseta_tempo, 1, "Aseta tempo valittuun kokonaislukuun"), - "G": ("(G)eneroi sävelmä", self._generoi_savelma, 0, "Generoi sävelmä valituilla asetuksilla"), - "S": ("(S)ulje", self._sulje, 0, "Sulje ohjelma") + "A": ("(A)pu", self._tulosta_apu, 0, + "Tulosta apu"), + "O": ("(O)petusdata [polku]", self._aseta_opetusdata, 1, + "Valitse opetusdata"), + "P": ("(P)olku [polku]", self._aseta_tulos_polku, 1, + "Valitse valmiin sävelmän polku"), + "K": ("(K)etjun aste", self._aseta_aste, 1, + "Aseta Markovin ketjun aste valittuun kokonaislukuun"), + "L": ("a(L)kuosa [merkkijono]", self._aseta_alkuosa, 1, + "Aseta alkuosa. Esim. 'C4|D#5|Gb3'"), + "N": ("(N)uotteja [luku]", self._aseta_nuottien_maara, 1, + "Aseta sävelmän nuottien määrä valittuun kokonaislukuun"), + "T": ("(T)empo [luku]", self._aseta_tempo, 1, + "Aseta tempo valittuun kokonaislukuun"), + "G": ("(G)eneroi sävelmä", self._generoi_savelma, 0, + "Generoi sävelmä valituilla asetuksilla"), + "S": ("(S)ulje", self._sulje, 0, + "Sulje ohjelma") } self._virheet = [] @@ -42,6 +54,7 @@ class UI: if komento: if komento[0].upper() in self._toiminnot: + # Virheiden välttämiseksi sulkeminen käsitellään ennen muita if komento[0].upper() == "S": self._sulje() @@ -53,9 +66,9 @@ class UI: for i in range(1, 1+parametrien_maara): parametrit.append(komento[i]) funktio(parametrit) - except: + # Kaikki virheet halutaan ohittaa + except: # pylint: disable=bare-except self._virheet.append("KOMENNON MUOTO VÄÄRÄ!") - continue def _tyhjenna(self): # windows @@ -104,7 +117,7 @@ class UI: def _aseta_alkuosa(self, alkuosa): alkuosa = alkuosa[0] - if search("^([CcDdEeFfGgAaBb][#b]?[0-8]\|)*[CcDdEeFfGgAaBb][#b]?[0-8]$", alkuosa): + if search(r"^([CcDdEeFfGgAaBb][#b]?[0-8]\|)*[CcDdEeFfGgAaBb][#b]?[0-8]$", alkuosa): self._alku = alkuosa else: self._virheet.append("ANNETTU ALKUOSA EI KELPAA!") @@ -124,7 +137,9 @@ class UI: def _generoi_savelma(self, _): musiikki_generaattori.lue_opetusdata(self._opetusdata_polku) musiikki_generaattori.valmistele_ketju(self._alku, self._aste) - print(f"Generoitiin {musiikki_generaattori.generoi_nuotteja(self._nuottien_maara)} nuottia!\n") + + generoitu_maara = musiikki_generaattori.generoi_nuotteja(self._nuottien_maara) + print(f"Generoitiin {generoitu_maara} nuottia!\n") musiikki_generaattori.kirjoita_midi(self._tulos_polku, self._tempo) def _sulje(self):