Benutzer-Werkzeuge

Webseiten-Werkzeuge


Seitenleiste

ws1516:jazz-komposition

Jazz-Komposition

Mitglieder

Manon, Theresa

Idee

Wir moechten ein Programm schreiben, das uns nach einem gewissen Schema ein Lied komponiert. Die Grundlage soll die Jazz-Theorie bilden. Der Bediener kann aussuchen, mit welchem Akkord begonnen wird. Der Plan ist, eine Melodie, aber auch einen Impro-Teil zu schreiben. Jedes Mal wird ein neues Stück komponiert.

Ein erster grober Plan

  • Ein allgemeines Schema für Jazzharmonik finden.–>Recherche: Bücher, Internet
  • Programm in Python schreiben, das nach Eingabe eines Tons das Schema in der passenden Tonart ausgibt
  • Töne einlesen, Programm mit Tönen versehen
  • Merkmale einer Jazzmelodie–>Recherche
  • Programm schreiben, dass eine Melodie improvisiert, erstmal über vier Takte
  • Akkord- und Melodieprogramm kombinieren

19.11.15: Das Bluesschema

Wir haben uns entschieden, erstmal das Blues Akkord-Schema zu benutzen, damit wir uns auf die Melodiestimme konzentrieren können. Das Bluesschema besteht aus zwölf Takten und sieht so aus:

vier Takte Tonika, zwei Takte Subdominante, zwei Takte Tonika ein Takt Dominante, ein Takt Subdominante, zwei Takte Tonika, in C-dur wäre das also

CCCC FFCC GFCC

Außerdem haben wir eine Cloud eingerichtet und versucht das Modul midi zu installieren, um Töne abspielen zu können.

26.11.15:Einen Ton abspielen

Wir haben das Modul sequencer, das PyAudio benutzt, installiert und ein bisschen ausprobiert. Mithilfe von sequencer können wir einen Ton abspielen.

from sequencer import *
 
def einzelnen_ton_abspielen():
		tonhoehe=0
		tondauer=4
		sound=Sound()
		sound.klanggen=EasySequencer(6,1) 
		threading.Thread(target=sound.play).start()
		sound.klanggen.add_note_easy(0,tonhoehe,tondauer,0.5)
		time.sleep(tondauer*VIERTELNOTE)
		time.sleep(1)
		sound.outStream.close()
 
einzelnen_ton_abspielen()

03.12.15: Einen Tonschritt abspielen

Von einem Ton ausgehend wollen wir nun eine Melodie erzeugen. Melodien bestehen aus Tonschritten und Tonsprüngen. Unsere Funktion soll, nachdem sie einen Anfangston abgespielt hat, entweder den Ton abspielen, der um einen Ganztonschritt über dem Anfangston liegt oder den Ton, der einen Ganztonschritt bzw. zwei Halbtonschritte unter ihm liegt. Das heißt der Zufall soll entscheiden, ob als nächstes ein höherer oder ein tieferer Ton gespielt wird. Dazu bedienen wir uns dem Modul random. Nachdem der Anfangston abgespielt wurde, wird in der while-Schleife die zufällig gewählte Größe i bestimmt und damit auch der folgende Ton bestimmt und abgespielt.

def tonschritt_abspielen():
		tonhoehe=1  #Anfangston
		tondauer=1
		sound=Sound()
		sound.klanggen=EasySequencer(6,1) 
		threading.Thread(target=sound.play).start() 
		time.sleep(0)
		k=0
		while k<=2:  
 
			sound.klanggen.add_note_easy(0,tonhoehe,tondauer,0.3)
			time.sleep(tondauer*VIERTELNOTE)
			i=random.randint(0,1)
 
			if i==0: 
			        tonhoehe=tonhoehe+2
			else:
		             tonhoehe=tonhoehe-2
 
 
			k=k+tondauer
 
 
		time.sleep(1)
		sound.outStream.close()
 
tonschritt_abspielen()

Für unsere Literaturrecherche hat uns Stefan einige Links über algorithmisches Komponieren geschickt und ein Buch bestellt. Hoffentlich können wir mithilfe des Buchs oder anderer Quellen mehr über die Merkmale von Bluesmelodien erfahren.Außerdem hat er uns auf ein aktuelles Forschungsprojekt namens Jazzomat hingewiesen, welches -so wie wir auch- Jazzmelodien untersucht.

10.12.15: Eine Melodie kreieren und abspielen lassen

Unser Melodieprogramm wurde nun aufgeteilt in zwei Funktionen: die erste Funktion kreiert die Melodie und speichert sie als eine Liste von Tönen. Diese Funktion enthält das Argument „Viertelnoten“. Wenn man also die Funktion aufruft, dann muss man bestimmen wie lang die Melodie in Viertelnoten sein soll. Die Längen der einzelnen Töne werden in unserer Funktion zufällig bestimmt mit dem Befehl random.randint(). Die tondauer kann die Werte 1 bis 8 annehmen.

from sequencer import *
import random
def create_melody(Viertelnoten):
	melodietoene=[]
	k=0
	while k<Viertelnoten:
		tonhoehe=0
		tondauer=random.randint(1,8)#z ist ein zufaellig gewaehlter Wert zwischen 1 und 8
		tonlautstaerke=0.05
		z=random.randint(0,100)
		if z<=5 and z>=0:  
			tonhoehe=tonhoehe
		elif z>15 and z<=30:  
			tonhoehe=tonhoehe+2
		elif z>30 and z<=35:
			tonhoehe=tonhoehe+4
		elif z>35 and z<=60:
			tonhoehe=tonhoehe+5
 		elif z>60 and z<=85:
			tonhoehe=tonhoehe+7
		elif z>85 and z<=90:
			tonhoehe=tonhoehe+9
		elif z>90 and z<=95:
			tonhoehe=tonhoehe+11
		else:
			tonhoehe=tonhoehe+12
			tonlautstaerke=0 
		if k+tondauer>Viertelnoten:
			tondauer=Viertelnoten-k
			tonhoehe=0
		k=k+tondauer
 
		melodietoene.append((tonhoehe,tondauer,tonlautstaerke))
	return melodietoene

Die zweite Funktion play_melody spielt die Liste der Melodietöne ab.

def play_melody(liste):  
	sound=Sound()
	sound.klanggen=EasySequencer(600,1)
	threading.Thread(target=sound.play).start()
	for x in liste:
			print x[0],x[1],x[2]
			sound.klanggen.add_note_easy(0,x[0],x[1],x[2])
			time.sleep(x[1]*VIERTELNOTE)
 
melodie1=create_melody(10000)
play_melody(melodie1)

Wir sind noch unzufrieden mit dem Klang unserer Soundausgabe. Es wäre schön, wenn wir bald ein Saxophon oder ein Klavier nachahmen könnten. Um Jazzmelodien zu erzeugen, haben wir versucht typische Merkmale von Jazzmelodien aus z. B. dem folgenden Tonbeispiel der Jazzdatenbank Jazzomat herauszuhören. In dem Beispiel hört man viele Pausen und die Töne sind eher kurz. {{:ws1516:artpepper_anthropology_prefinal.mid|}}

17.12.15: Dreiklänge

Die Tondauer im Melodieprogramm haben wir jetzt auf 1 und 2 beschränkt. Damit klingt es schon viel aufgeweckter und bluesiger!!

tondauer=random.randint(1,2)

Inzwischen haben wir ein Programm, welches uns die fertigen Dreiklänge für die Akkorde ausgibt.

from __future__ import division
 
from music21 import *  
 
from music21.midi.realtime import StreamPlayer
from music21.midi import MidiFile
 
grundton=raw_input('Geben Sie einen Grundton ein ')
grundton=grundton.upper()
 
l=['C','C#','D','D#','E','F','F#','G','G#','A','A#','B']
 
m=0
while m<=len(l):
 
    if grundton==l[m]:
        print m
        break
    else:
        m=m+1
 
## Erste Stimme
 
part1=stream.Part()
 
notes=[]
ton1=l[m]
notes_raw=[(ton1,4)]
 
for i,v in enumerate(notes_raw):
	n = note.Note(v[0])
	n.duration.quarterLength = v[1]
	n.volume.velocity=70   # das ist die Lautstärke 0.. 127
	notes.append(n)
 
 
part1.append(notes)
part1.insert(instrument.Piano())
 
## Zweite Stimme
 
part2=stream.Part()
 
notes=[]
m=m+4
print m
ton2=l[m]
notes_raw=[(ton2,4)]
for i,v in enumerate(notes_raw):
	n = note.Note(v[0])
	n.duration.quarterLength = v[1]
	n.volume.velocity=100
	notes.append(n)
 
part2.append(notes)
part2.insert(instrument.Piano())
 
## Dritte Stimme
 
part3=stream.Part()
 
notes=[]
m=m+3
print m
ton3=l[m]
notes_raw=[(ton3,4)]
for i,v in enumerate(notes_raw):
	n = note.Note(v[0])
	n.duration.quarterLength = v[1]
	n.volume.velocity=100
	notes.append(n)
 
part3.append(notes)
part3.insert(instrument.Piano())
 
 
## Beide Stimmen in einem 'Stream'
 
stream=stream.Stream([part1,part2,part3])
 
## Tempo setzen:
 
metronome=tempo.MetronomeMark("allegro", 240, note.Note(type='quarter'))
stream.insert(metronome)
 
##  Abspielen  (benötigt PyGame und einen midi-Synthesizer)
 
player=StreamPlayer(stream)
player.play()
 

07.01.16: Das Bluesschema als Programm

Hier ein Programm, das die Begleitung für die 12 Takte des Blusschemas abspielt.

def Begleitung(grundton):
    Akkorde(grundton)
    Akkorde(grundton)
    Akkorde(grundton)
    Akkorde(grundton)
 
    l=['C','C#','D','D#','E','F','F#','G','G#','A','A#','B','C','C#','D','D#','E','F','F#']
 
    m=0
    while m<=len(l):
 
        if grundton==l[m]:
            print l[m+5]
            break
        else:
            m=m+1
    stufevier=l[m+5]
 
    Akkorde(stufevier)
    Akkorde(stufevier)
    Akkorde(grundton)
    Akkorde(grundton)
 
    l=['C','C#','D','D#','E','F','F#','G','G#','A','A#','B','C','C#','D','D#','E','F','F#']
 
    m=0
    while m<=len(l):
 
        if grundton==l[m]:
            print l[m+7]
            break
        else:
            m=m+1
    stufefuenf=l[m+7]
 
    Akkorde(stufefuenf)
    Akkorde(stufevier)
    Akkorde(grundton)
    Akkorde(grundton)
 
grundton=raw_input('Geben Sie einen Grundton ein ')
grundton=grundton.upper()
 
Begleitung(grundton)

Ins Melodieprogramm konnten wir jetzt noch Pausen einfügen. Eine Pause hat genau wie ein Ton eine festgelegte Dauer. Der Unterschied ist aber, dass sie lautlos ist. Deswegen haben wir die tonhoehe=1000 eingefügt. Tritt diese tonhoehe nämlich auf, dann ist die tonlautstärke=0.

14.01.16: Saxophonklang

Die Melodie, die beim Ausführen der create_melody-Funktion entsteht, können wir jetzt mithilfe von music21 von einem Saxophon abspielen lassen.

import threading, time
from sequencer_music21 import Sound21 as Sound
from sequencer_music21 import Music21Sequencer as Sequencer
from sequencer_music21 import *
 
viertelnote=0.25
grundton=220   # Frequenz des kleinen a
def test(l):
	sound=Sound()  #  das Objekt, das sich um die Tonausgabe kümmert
 
 
	instruments=['instrument.AltoSaxophone()']    
	sound.klanggen=Sequencer(6000,1,instruments=instruments)         
 
	anfang=0.0
	for ton in l:
		ende=anfang+ton[1]*viertelnote
		sound.klanggen.add_note(0,grundton*HALBTON**ton[0],anfang, ende,0.3) 
		sound.klanggen.add_note(1,grundton*2*HALBTON**ton[0],anfang, ende, 0.3) 
 
		anfang=ende
 
 
 
 
	threading.Thread(target=sound.play).start() # Tonausgabe gestartet
	time.sleep(1)
 
	jetzt=time.time()
	while jetzt+ende+1>time.time():
		pass
 
l=create_melody(16)	
test(l)

Ab jetzt wollen wir versuchen unsere beiden Programme zu kombinieren.

21.01.16: Unsere Programme als Klassen

Dafür haben wir drei Klassen definiert: Komposition, Dreiklang und Melodie. In der Klasse Komposition sollen Objekte der Klasse Melodie mit Objekten der Klasse Dreiklang kombiniert werden, sodass eine Jazz-Komposition entsteht.

class Dreiklang:
    def __init__(self):
        self.l=['C','C#','D','D#','E','F','F#','G','G#','A','A#','B','C','C#','D','D#','E','F','F#']
        self.noten=[]
    def create_dreiklang(self,grundton):
          .
          .
          . 
class Melodie:
    def __init__(self):
        self.tonliste=[]
        self.melodielaenge=0
 
    def create_melody(self,Viertelnoten):
        k=0
        while k<Viertelnoten:
            ton=0
            j=random.randint(1,8)
            i=random.randint(0,100)
            if i<=20 and i>=0:
		      ton=ton
            elif i>20 and i<=40:
            .
            .
            .

Dabei ergibt sich für uns das Problem, dass die Melodie und die Dreiklänge unterschiedlich abgespielt werden. Dies wollen wir nun vereinheitlichen.

28.01.16: Zusammenführung der Klasse Melodie und Akkorde

Wir haben beschlossen, dass Theresa sich um die Zusammenführung unserer beiden Programme in einer Klasse Komposition kümmert, während Manon ab jetzt die Dokumentation in der Wiki übernimmt. Die Kompositionsklasse schuat folgendermaßen aus:

from __future__ import division
 
from music21 import *  
 
from music21.midi.realtime import StreamPlayer
from music21.midi import MidiFile
import dreiklang
import melodie
 
class Komposition:
    def __init__(self):
        self.akkorde=[]
        self.melodie=[]
 
    def add_akkord(self,m):
        self.akkorde.append(dreiklang.Dreiklang())
        self.akkorde[-1].create_dreiklang(m)
 
    def play_dreiklang(self,m):
        stream2=stream.Stream(self.akkorde[m].dreiklang)
        metronome=tempo.MetronomeMark("allegro", 240, note.Note(type='quarter'))
        stream2.insert(metronome)
 
        player=StreamPlayer(stream2)
        player.play()
 
    def play_begleitung(self,o):
        play_dreiklang(o)
        play_dreiklang(o)
        play_dreiklang(o)
        play_dreiklang(o)
        l=['C','C#','D','D#','E','F','F#','G','G#','A','A#','B','C','C#','D','D#','E','F','F#']
        p=0
        while p<=len(l):
            if o==l[p]:
                print l[o+5]
                break
            else:
                o=o+1
        stufevier=l[o+5]
 
        play_dreiklang(stufevier)
        play_dreiklang(stufevier)
        play_dreiklang(o)
        play_dreiklang(o)
        l=['C','C#','D','D#','E','F','F#','G','G#','A','A#','B','C','C#','D','D#','E','F','F#']
        p=0
        while p<=len(l):
            if o==l[p]:
                print l[o+7]
                break
            else:
                o=o+1
        stufefuenf=l[o+7]
 
        play_dreiklang(stufefuenf)
        play_dreiklang(stufevier)
        play_dreiklang(o)
        play_dreiklang(o)
 
    def add_ton(self):
        self.melodie.append(melodie.Melodie())
        self.melodie.create_melody()
 
    def play_melodie(self):
        sound=Sound()  
        instruments=['instrument.AltoSaxophone()']    
        sound.klanggen=Sequencer(6000,1,instruments=instruments)
        anfang=0.0
        for ton in self.melodie:
            ende=anfang+ton[1]*viertelnote
            sound.klanggen.add_note(0,grundton*HALBTON**ton[0],anfang, ende,0.3) 
            #sound.klanggen.add_note(1,grundton*2*HALBTON**ton[0],anfang, ende, 0.3) 
            anfang=ende
        threading.Thread(target=sound.play).start() 
        time.sleep(1)
        jetzt=time.time()
        while jetzt+ende+1>time.time():
            pass

Momentan kann aber die Begleitung nur sehr holprig abgespielt werden, da jedes Mal die Funktion neu aufgerufen wird.

04.02.16: Klasse Komposition

Dieses Problem haben wir jetzt lösen können -es wird jetzt eine Liste angelegt, die dann abgespielt wird- und erhalten ein Programm, das uns Jazzmelodien auf dem Blusschema improvisiert.

from __future__ import division
 
from music21 import *  
 
from music21.midi.realtime import StreamPlayer
from music21.midi import MidiFile
import dreiklang as v
import melodie as u
 
class Komposition:
    def __init__(self):
        m=u.Melodie()
        self.tonliste=m.create_melodie(48)
        self.akkorde1=[]
        self.akkorde2=[]
        self.akkorde3=[]
        self.l=['C','C#','D','D#','E','F','F#','G','G#','A','A#','B','C','C#','D','D#','E','F','F#']
 
    def create_bluesschema(self,grundton):
        grundton=grundton.upper()
        p=self.l.index(grundton)
        z=v.Dreiklang()
        stufevier=self.l[p+5]
        stufefuenf=self.l[p+7]        
 
        self.akkorde1.append(z.create_dreiklang1(grundton))
        self.akkorde1.append(z.create_dreiklang1(grundton))
        self.akkorde1.append(z.create_dreiklang1(grundton))
        self.akkorde1.append(z.create_dreiklang1(grundton))
        self.akkorde1.append(z.create_dreiklang1(stufevier))
        self.akkorde1.append(z.create_dreiklang1(stufevier))
        self.akkorde1.append(z.create_dreiklang1(grundton))
        self.akkorde1.append(z.create_dreiklang1(grundton))
        self.akkorde1.append(z.create_dreiklang1(stufefuenf))
        self.akkorde1.append(z.create_dreiklang1(stufevier))
        self.akkorde1.append(z.create_dreiklang1(grundton))
        self.akkorde1.append(z.create_dreiklang1(grundton))
        #print grundton
 
        self.akkorde2.append(z.create_dreiklang2(grundton))
        self.akkorde2.append(z.create_dreiklang2(grundton))
        self.akkorde2.append(z.create_dreiklang2(grundton))
        self.akkorde2.append(z.create_dreiklang2(grundton))
        self.akkorde2.append(z.create_dreiklang2(stufevier))
        self.akkorde2.append(z.create_dreiklang2(stufevier))
        self.akkorde2.append(z.create_dreiklang2(grundton))
        self.akkorde2.append(z.create_dreiklang2(grundton))
        self.akkorde2.append(z.create_dreiklang2(stufefuenf))
        self.akkorde2.append(z.create_dreiklang2(stufevier))
        self.akkorde2.append(z.create_dreiklang2(grundton))
        self.akkorde2.append(z.create_dreiklang2(grundton))
        #print grundton
 
        self.akkorde3.append(z.create_dreiklang3(grundton))
        self.akkorde3.append(z.create_dreiklang3(grundton))
        self.akkorde3.append(z.create_dreiklang3(grundton))
        self.akkorde3.append(z.create_dreiklang3(grundton))
        self.akkorde3.append(z.create_dreiklang3(stufevier))
        self.akkorde3.append(z.create_dreiklang3(stufevier))
        self.akkorde3.append(z.create_dreiklang3(grundton))
        self.akkorde3.append(z.create_dreiklang3(grundton))
        self.akkorde3.append(z.create_dreiklang3(stufefuenf))
        self.akkorde3.append(z.create_dreiklang3(stufevier))
        self.akkorde3.append(z.create_dreiklang3(grundton))
        self.akkorde3.append(z.create_dreiklang3(grundton))
        #print grundton
 
    def play_melodie(self):
        sound=Sound()  
        instruments=['instrument.AltoSaxophone()']    
        sound.klanggen=Sequencer(6000,1,instruments=instruments)
        anfang=0.0
        for ton in self.tonliste:
            ende=anfang+ton[1]*viertelnote
            sound.klanggen.add_note(0,grundton*HALBTON**ton[0],anfang, ende,0.3) 
            #sound.klanggen.add_note(1,grundton*2*HALBTON**ton[0],anfang, ende, 0.3) 
            anfang=ende
        threading.Thread(target=sound.play).start() 
        time.sleep(1)
        jetzt=time.time()
        while jetzt+ende+1>time.time():
            pass
 
    def melodie_und_begleitung(self):
        part4=stream.Part()
        notes=[]
        for i,v in enumerate(self.tonliste):
            n = note.Note(v[0])
            n.duration.quarterLength = v[1]
            n.volume.velocity=70
            notes.append(n)
        part4.append(notes)
 
        part1=stream.Part()
        part1.append(self.akkorde1)
 
        part2=stream.Part()
        part2.append(self.akkorde2)
 
        part3=stream.Part()
        part3.append(self.akkorde3)
 
        fertig=[part1, part2, part3, part4]
        stream2=stream.Stream(fertig)
        metronome=tempo.MetronomeMark("allegro", 240, note.Note(type='quarter'))
        stream2.insert(metronome)
 
        player=StreamPlayer(stream2)
        player.play()

Leider treten vereinzelt störende, sehr tiefe Töne auf, die wir noch nicht vermeiden können. Im folgenden Beispiel haben wir die Wahrscheinlichkeit dieser deutlich erhöht. tiefe_toene.mid

11.02.16: Kompositionen als Midi-Dateien

Die entstehenden Kompositionen können wir jetzt als Midi-Dateien und als Textdateien speichern. Auch die tiefen Töne können wir nach längerem Herumprobieren vermeiden. Das Programm improvisiert nun über 12 Takte eine Melodie auf dem Bluesschema. Hier eine Kostprobe von unserem Programm:kostprobe_blues_improvisation.mid

Im Großen und Ganzen sind wir zufrieden mit unserem Ergebnis. Wir haben wie geplant ein Programm geschrieben, das uns immer wieder neue bluesige Stücke komponiert, wenn auch noch sehr einfach gehalten. Uns beiden macht das Projekt aber immer noch großen Spaß und wir sind dabei, es immer weiter zu verbessern. Beispielsweise ist die Dynamik noch gar nicht beachtet und auch die Harmonien sind noch sehr simpel. Außerdem versuchen wir eine Möglichkeit zu finden, in der Begleitung einen Rhythmus zu finden, der dann in der Melodie aufgegriffen und verändert werden kann. Wenn wir irgendwann das Projekt als abgeschlossen betrachten, werden wir noch eine Homepage erstellen, auf der das Programm abgespielt werden kann.

ws1516/jazz-komposition.txt · Zuletzt geändert: 2016/05/10 14:46 (Externe Bearbeitung)