Mit dem Raspberry Pi Musik machen und "Alle meine Entchen" spielen

Diesmal wollen wir das Sirene-Projekt aus dem letzten Teil ein bisschen abwandeln und versuchen, dem Raspberry Pi eine Melodie zu entlocken.

Eine Warnung gleich vorweg: Die Melodie wird grauenhaft klingen und so mancher Ton wird daneben liegen. Das liegt vor Allem daran, dass das Timing nicht perfekt ist, weil der Raspberry auch noch mit anderen Dingen beschäftigt ist. Besonders bei Aktivität wird es sehr schräg werden.

Als Melodie habe ich mich etwas ganz einfaches ausgesucht, nämlich "Alle meine Entchen". Ich bin nämlich nicht gerade musikalisch, aber hier hat es gerade noch bei mir gereicht, die Noten zu lesen. Außerdem sollte es etwas sein, dass man leicht wiedererkennen kann.

Und so hört sich das Ganze an:





Bewerkstelligt wird das Ganze durch den folgenden Code, der mit den Inline-Kommentaren schon gut dokumentiert ist. Auf ein paar Eigenarten gehen ich nach dem Listing ein.

# -*- encoding: utf-8 -*- # 2018 by Oliver Kuhlemann # Bei Verwendung freue ich mich über Namensnennung, # Quellenangabe und Verlinkung # Quelle: http://cool-web.de/raspberry/ import RPi.GPIO as GPIO # Funktionen für die GPIO-Ansteuerung laden import time # für sleep() (Pause) nötig import sys # um die übergebenen Parameter von der Shell abzufragen GPIO.setmode(GPIO.BCM) # die GPIO-Pins im BCM-Modus ansprechen led=14 # LED/Speaker hängen an BCM-Pin 14 GPIO.setup(led, GPIO.OUT) # in den Pin wird "geschrieben" # Nachfolgend werden die Frequenzen in Hertz für einige Klaviernoten definiert noten = {"c4":261.626, "c#4":277.183, "d4":293.665, "d#4":311.127, "e4":329.628, "f4":349.228, "f#4":369.994, "g4":391.995, "g#4":415.305, "a4":440, "a#4":466.164, "b4":493.883, "c5":523.251, "c#5":554.365, "d5":587.330, "d#5":622.254, "e5":659.255, "f5":698.456, "f#5":739.989, "g5":783.991, "g#5":830.609, "a5":880, "a#5":932.328, "b5":987.767 } tGanze=0.75 # wieviele Sekunden dauert eine ganze Note? pNote=0.04 # Pause / Stille zwischen Noten def sound(freq, t): # Diese Funktion erzeugt eine bestimmte Zeit t lang dur=1.0/freq/2.0 # die Frequenz freq anz=int(t/dur/2) for i in range (0,anz): GPIO.output(led, GPIO.HIGH) time.sleep (dur) GPIO.output(led, GPIO.LOW) time.sleep (dur) def spieleNote (note, xtel): try: freq = noten[note] except KeyError: print "Die Note " + note + " ist nicht definiert." return t = tGanze / xtel sound (freq, t) time.sleep (pNote) print "Spiele Alle Meine Entchen (4/4 Takt)..." spieleNote("c4", 4) # Al- spieleNote("d4", 4) # le spieleNote("e4", 4) # mei- spieleNote("f4", 4) # ne spieleNote("g4", 2) # Ent- spieleNote("g4", 2) # chen spieleNote("a4", 4) # schwim- spieleNote("a4", 4) # men spieleNote("a4", 4) # auf spieleNote("a4", 4) # dem spieleNote("g4", 1) # See, spieleNote("a4", 4) # schwim- spieleNote("a4", 4) # men spieleNote("a4", 4) # auf spieleNote("a4", 4) # dem spieleNote("g4", 1) # See, spieleNote("f4", 4) # Köpf- spieleNote("f4", 4) # chen spieleNote("f4", 4) # in spieleNote("f4", 4) # dem spieleNote("e4", 2) # Was- spieleNote("e4", 2) # ser spieleNote("d4", 4) # Schwänz- spieleNote("d4", 4) # chen spieleNote("d4", 4) # in spieleNote("d4", 4) # die spieleNote("c4", 1) # Höh. GPIO.cleanup() # Programm sauber verlassen und Resourcen wieder freigeben tGanze definiert, wie lange eine ganze Note in Sekunden dauert. Eine halbe Note dauert dann entsprechend halb so lang. Je kleine tGanze ist, je schneller wird das Musikstück gespielt. Es ist wichtig, die Zahl als Fließkommazahl anzugeben, also 1.0 statt 1. Sonst interpretiert Python die Zahl als Integer und hat nachfolgend Schwierigkeit, damit zu rechnen.

pNote ist die Pause in Sekunden zwischen dem Anschlage zwischen zwei Noten, also im Prinzip wie lange z. B. ein Pianist braucht, um von einer Taste zur nächsten zu kommen.

Die Funktion sound(freq, t): kennen wir ja schon aus unserem Sirenen-Projekt.

Darauf baut die Funktion spieleNote (note, xtel) auf. Diese versucht (Befehlswort try) die übergebene Note note im Dictionary noten zu finden. Ist dies nicht der Fall, tritt ein Fehler namens KeyError auf, der durch except KeyError: abgefangen wird. Es wird dann eine Fehlermeldung ausgegeben und die Nicht-Note ignoriert (return verlässt die Funktion augenblicklich).

Außer der Note wird noch die Notenlänge als xtel übergeben, wobei 1 für 1/1, also eine ganze, 2 für 1/2, also eine halbe, 4 für 1/4, also eine viertel und 8 für eine achtel Note steht. Nach dem Spielen einer Note wird eine kurze Pause pNote eingelegt, sonst klingt es ein wenig komisch.

Nachfolgend sieht man am Beispiel von "Alle meine Entchen", wie man die einzelnen Noten eines Liedes abspielt. Bereits definiert sind die zwei Oktaven 4 und 5 samt der Zwischennoten (den schwarzen Tasten auf dem Klavier), wobei c#4 zwischen c4 und d4 liegt. Ihr dürft das Dictionary gern erweitern, falls nötig. Die nötigen Frequenzen findet ihr z. B. hier oder indem ihr nach ihr nach noten frequenzen googelt. Falls ihr eine tolle, eigene Melodie geschrieben habt, dann schickt sie mir doch einfach per e-mail (am Ende der Seite). Viel Spaß beim Experimentieren und Komponieren!