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:41]
h.schoeller96 [Sitzung 10]
ws1516:melodiegenerator [2016/05/10 14:46] (aktuell)
Zeile 405: Zeile 405:
 from pickle import Pickler from pickle import Pickler
 from pickle import Unpickler from pickle import Unpickler
-import os 
-import random 
  
 def speicher(wb,​ datei): def speicher(wb,​ datei):
Zeile 423: Zeile 421:
     sie ein Wörterbuch an, welches Für jeden Ton speichert, ob und wenn ja,     sie ein Wörterbuch an, welches Für jeden Ton speichert, ob und wenn ja,
     wie häufig ein anderer Ton nach diesem Ton vorkam. Nur die Tonhöhe ist relevant.     wie häufig ein anderer Ton nach diesem Ton vorkam. Nur die Tonhöhe ist relevant.
-    Ebenfalls erwartet es ein Wörterbuch,​ in dem die Tonflogehäufigkeiten ​gespeichert sind. Gibt es keins, wird ein leeres erzeugt.'''​+    Ebenfalls erwartet es ein Wörterbuch,​ in dem die Tonfolgehäufigkeiten ​gespeichert sind. Gibt es keins, wird ein leeres erzeugt.'''​
     for i,ton in enumerate (melodie.toene):​     for i,ton in enumerate (melodie.toene):​
         if i==len(melodie.toene)-1:​         if i==len(melodie.toene)-1:​
Zeile 437: Zeile 435:
                 tonstat[ton.hoehe][melodie.toene[i+1].hoehe]+=1                 tonstat[ton.hoehe][melodie.toene[i+1].hoehe]+=1
     return tonstat     return tonstat
 +
 +</​code>​
 +
 +Die Methode build_markov liefert also die absolut statistische Grundlage für eine Analyse. Lediglich kann die Methode nur eine einzelne Datei zur Zeit analysieren. Zur Analyse von einer ganzen Menge Dateien dient die Methode "​analyse":​
  
 <code python> <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 einem Tonhäufigkeitswörterbuch für alle Dateien zusammen zurück.''' ​   ​
 +    tonstat={}
 +    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
 +                tonstat=build_markov(aktmelodie,​tonstat)#​sexy Rekursion; fügt die Tonhäufigkeiten der aktuellen Melodie dem bestehenden Wörterbuch hinzu
 +    return tonstat
 +</​code>​
 +
 +Als letztes wurde eine Methode geschrieben,​ die aus einem Wörterbuch,​ welches absolute Häufigkeiten gespeichert hat, ein Wörterbuch erzeugt, welches für jeden Ton die Wahrscheinlichkeiten für die Folgetöne speichert. Dies geschieht in der Methode "​build_markovp":​
 +
 +<code python>
 +def build_markovp(tonstat):​
 +    '''​Diese Methode erwartet ein absolute Häufigkeiten und wandelt diese in relative Häufigkeiten um.'''​
 +    tonstatp={} ​   ​
 +    for ton in tonstat:
 +        tonstatp[ton]={}
 +        summe=0 ​       ​
 +        for folgeton in tonstat[ton]:#​Zählt,​ wie viele Folgetöne für den Ton (absolut) vorkamen.
 +            summe=summe+tonstat[ton][folgeton]
 +        for folgeton in tonstat[ton]:#​Weist jedem Folgeton seinen relativen Häufigkeitswert zu.
 +            tonstatp[ton][folgeton]=(tonstat[ton][folgeton])/​summe
 +        neue_summe=0
 +        for folgeton in tonstatp[ton]:#​Weist den Folgetönen Bereiche zwischen 0 und 1 zu, deren Länge ihrer Häufigkeit entsprechen.
 +            neue_summe=neue_summe+tonstatp[ton][folgeton]#​Wird später eine Zufallszahl ziwschen 0 und 1 erzeugt, wird der Ton gewählt, in dessen Bereich diese Zufallszahl trifft. ​       ​
 +            tonstatp[ton][folgeton]=neue_summe
 +    return tonstatp
 +</​code>​
 +
 +
 ==== Sitzung 11 ==== ==== Sitzung 11 ====
 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.1455651718.txt.gz · Zuletzt geändert: 2016/05/10 14:46 (Externe Bearbeitung)