Benutzer-Werkzeuge

Webseiten-Werkzeuge


ws1516:melodiegenerator

Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen gezeigt.

Link zu dieser Vergleichsansicht

Beide Seiten der vorigen Revision Vorhergehende Überarbeitung
Nächste Überarbeitung
Vorhergehende Überarbeitung
ws1516:melodiegenerator [2016/02/16 20:52]
h.schoeller96 [Sitzung 10]
ws1516:melodiegenerator [2016/05/10 14:46] (aktuell)
Zeile 478: Zeile 478:
 Anwesend: Sebastian, Svenja, Csaba, Henry Anwesend: Sebastian, Svenja, Csaba, Henry
 Datum: 11.02.2016 Datum: 11.02.2016
 +
 +Heute wurde an der Datei "​Analyse"​ weitergearbeitet. Es wurde eine Methode hinzugefügt,​ welche aus einem "​Folgetonwahrscheinlichkeitswörterbuch"​ (so wie tonstatp, siehe oben) eine zufällige Melodie erzeugt. Diese Methode heißt buid_melodie:​
 +
 +<code python>
 +import random
 +
 +def build_melodie(tonstatp,​ anfangston, laenge=16,​):​
 +    '''​Erzeugt eine Zufallsmelodie,​ die ein relatives Folgetonhäufigkeitswörterbuch tonstatp benötigt. Der Anfangston kann selbst gewählt werden.
 +    '''​
 +    neue_melodie=Stimme(0)
 +    anfangston=hoehenrechner(anfangston)  ​
 +    i=0
 +    while i<​laenge:​
 +        rdauer=random.randint(1,​4)
 +        if i==0:
 +            neuer_ton=Ton(rdauer,​anfangston,​0.4)
 +        else:
 +            rhoehe=random.random()
 +            for folgeton in tonstatp[neue_melodie.toene[len(neue_melodie.toene)-1].hoehe]:​
 +                #Geht die relativen Häufigkeitswerte des Eintrages des aktuell letzten Tones der Melodie im Wörterbuch durch. ​
 +                if rhoehe<​tonstatp[neue_melodie.toene[len(neue_melodie.toene)-1].hoehe][folgeton]:​
 +                    #Ist der Bereich gefunden, in dem die Zufallsvariable rhoehe liegt, wird dieser Ton ausgewählt.
 +                    neuer_ton=Ton(rdauer,​folgeton,​0.4)
 +                    break
 +        neue_melodie.add_ton(neuer_ton)
 +        i+=1
 +    return neue_melodie
 +
 +</​code>​
 +
 +Außerdem wurde nun der bestehende Code so umgeschrieben,​ dass zwischen Moll und Dur differenziert wird und alle eingelesenen Melodien auf Tonarten ohne Vorzeichen transponiert werden (also C-Dur oder A-Moll). Die relevanten Passagen finden sich in der Methode "​add_melodie"​ und der Methode "​trans":​
 +
 +<code python>
 +    def add_melodie(datei)
 +    ​
 +    [...]
 +        ​
 +        #Falls in der .mid Datei die Tonart gespeichert ist, wird sie der Stimme hinzugefügt. ​        
 +        for event in melodie:
 +            if isinstance(event,​ midi.KeySignatureEvent):​
 +                if event.data[1]==0:​
 +                    self.tonart=vorzeichendur[event.data[0]] +"​_"​+"​dur"​
 +                elif event.data[1]==1:​
 +                    self.tonart=vorzeichendur[(event.data[0]+3)%256]+"​_"​+"​moll"​
 +        ​
 +        #Die Melodie wird nun in eine Tonart ohne Vorzeichen transponiert.
 +        if (not self.tonart=="​c_dur"​) and (not self.tonart=="​a_moll"​) and (not self.tonart==""​):​
 +            aktgeschlecht=(self.tonart.split('​_'​))[1]
 +            if aktgeschlecht=='​moll':​
 +                self.trans('​a_moll'​)
 +            elif aktgeschlecht=='​dur':​
 +                self.trans('​c_dur'​)
 +                ​
 +    def trans(self, zieltonart):​
 +        '''​Diese Methode transponiert die Stimme von der aktuellen in die Zieltonart. zieltonart liegt dabei als String der Form "​Ton_Tongeschlecht"​ vor, 
 +        also zum Beispiel "​Fis_dur"'''​
 +        zielgrundton=zieltonart.lower()
 +        zielgrundton=zielgrundton.split('​_'​)
 +        zielgrundton=tonleiter[zielgrundton[0]]
 +        aktgrundton=self.tonart.lower()
 +        aktgrundton=aktgrundton.split('​_'​)
 +        aktgrundton=tonleiter[aktgrundton[0]]
 +        for ton in self.toene:
 +            ton.hoehe=ton.hoehe+(zielgrundton-aktgrundton)
 +        self.tonart=zieltonart
 +</​code>​
 +
 +Auch wurde in der Datei "​analyse"​ einiges umgeschrieben. So wurde in der Methode "​analyse"​ zwischen Dur und Moll differenziert:​
 +
 +<code python>
 +def analyse (Ordner):
 +    '''​Diese Methode analysiert alle Dateien im Verzeichnis Ordner (als String, also bspw. "​Mathesis"​),​ die auf .mid enden.
 +    Sie gibt ein Wörterbuch mit zwei Tonhäufigkeitswörterbüchern (eines für Dur , eines für Moll) zurück.''' ​   ​
 +    tonstatd={}#​dur
 +    tonstatm={}#​moll
 +    for root,​dirs,​files in os.walk(Ordner):​
 +        for file in files:
 +            if str(file)[-4:​]=='​.mid':​
 +                aktmelodie=Stimme(0)#​legt eine neue Stimme an
 +                aktmelodie.add_melodie(os.path.join(Ordner,​file))#​liest die aktuelle Melodie in die Stimme ein
 +                if not aktmelodie.tonart=="":#​Wenn eine Tonart in der Datei gefunden wurde
 +                    aktgeschlecht=aktmelodie.tonart[-4:​]
 +                    if aktgeschlecht=='​_dur':​
 +                        tonstatd=build_markov(aktmelodie,​tonstatd)#​sexy Rekursion; fügt die Tonhäufigkeiten der aktuellen Melodie dem bestehenden Wörterbuch hinzu
 +                    elif aktgeschlecht=='​moll':​
 +                        tonstatm=build_markov(aktmelodie,​tonstatm)
 +    tonstat={'​dur':​tonstatd,​ '​moll':​tonstatm}
 +    return tonstat
 +</​code>​
 +
 +Für ein schnelleres Arbeiten mit dem Programm wurden die Markovtabellen,​ in denen die Wahrscheinlichkeiten gespeichert sind (tonstatp, tonstatpm, tonstatpd) per Pickle gespeichert und müssen somit nicht mehr bei jedem Aufruf des Programms neu eingelesen werden:
 +
 +<code python>
 +
 +with open ("​tonstatp.pickle","​r"​)as f:
 +    u=Unpickler(f)
 +    tonstatp=u.load()
 +
 +with open ("​tonstatpd.pickle","​r"​)as f:
 +    u=Unpickler(f)
 +    tonstatpd=u.load()
 +
 +with open ("​tonstatpm.pickle","​r"​)as f:
 +    u=Unpickler(f)
 +    tonstatpm=u.load()
 +
 +</​code>​
ws1516/melodiegenerator.1455652370.txt.gz · Zuletzt geändert: 2016/05/10 14:46 (Externe Bearbeitung)