Wie man an einzelnen Beiträgen in diesem Blog sehen kann, beschäftige ich mich seit einiger Zeit verstärkt mit Soundsynthese und Audioprocessing. Als bekennender Fan von Python habe ich mich mal nach Tools für die mathematische Analyse und Verarbeitung von Audiosignalen in Python umgesehen und möchte hier mal meine Recherche-Ergebnisse vorstellen.
NumPy / SciPy
Das NumPy-Paket für Python bildet die Grundlage für eine Sammlung an Paketen für wissenschaftliche Berechnungen, SciPy. NumPy stellt ein Array-Objekt zu Verfügung, mit dem sich Arrays, also Ansammlungen von Objekten gleichen Typs, mit beliebigen Dimensionen darstellen lassen. Transformations-Funktionen lassen sich auf das ganze Array anwenden, indem die Funktion auf jedes einzelne Elemente angewandt wird. Da dies alles in C implementiert ist, ist es auch sehr schnell. Schnell genug für etliche Wissenschaftler in großen Forschungseinrichtungen jedenfalls.
Solche Arrays sind für Audio-Daten wunderbar geeignet, denn hier hat man es ja i.A. mit einer Folge von Samples, meist als Float-Zahlen zwischen -1 und +1 zu tun. Um NumPy-Arrays aus Audio-Daten zu erzeugen oder um Arrays in eine WAV-Datei o.ä. zu schreiben, gibt es das SciPy-Extensionpakat scikits.audiolab, das auf libsndfile basiert, also jede Menge Dateiformate, Samplingraten, Samplegrößen und Byteorders unterstützt. Aus patentrechtlichen Gründen liest und schreibt es aber leider keine MP3-Dateien, wohl aber Ogg Vorbis.
matplotlib
Um sich die Audio-Daten und sonstige Arrays auch schön mit Diagrammen darstellen zu lassen, gibt es das Paket matplotlib, das sich stark an MATLAB anlehnt. Auf der Webseite findet man eine Galerie mit hunderten Beispielen und ausführliche Dokumentation, um schnell zum ersten Plot zu kommen.
IPython
Eins der besten Features an Python ist m.E. der interaktive Modus. Damit kann man, wie auf der Shell, Statements und Ausdrücke interaktiv eingeben und bekommt gleich das Ergebnis angezeigt. Ideal, um Ideen auszuprobieren und Fehlern auf den Grund zu gehen. Einer der Hauptgründe, warum ich in Python meist ohne aufgeblasene GUI-IDE und Debugger auskomme (auch wenn es das natürlich alles gibt).
IPython mach die Python-Shell noch komfortabler, indem es automatische Code-Vervollständigung, interaktive Hilfe, Makros, Zugriff auf Shell-Befehle u.v.m. bietet. Das Beste ist aber, das NumPy und matplotlib wunderbar in IPython integriert sind. Wenn man IPython mit der Option “-pylab” aufruft, werden alle Symbole von NumPy und matplotlib bereits importiert und ein extra Thread für die grafische Darstellung gestartet, so dass man Plots interaktiv darstellen und anpassen kann, ohne dass man eine eigene Event-Loop für die Grafikverarbeitung programmieren muss und den Python-Prompt immer zur Verfügung hat.
Der ganze Krempel lässt sich unter Debian/Ubuntu leicht mit folgenden Befehlen installieren:
$ sudo apt-get install python ipython python-pip python-numpy \ python-matplotlib python-scipy
(python-scipy
ist optional.)
Audiolab ist leider noch nicht in den Paketquellen verfügbar, man kompiliert
& installiert es also am besten selbst, was aber Dank
setuptools/easy_install distutils/pip kein (größeres) Problem darstellt:
sudo apt-get install python-dev python-setuptools libsndfile1-dev \ libasound2-dev sudo pip install scikits.audiolab
Exkurs: will man IPython, NumPy, matplotlib & Audiolab in eine eigene
virtuelle Python-Umgebung installieren, wird es etwas umständlicher und dauert
länger, dafür braucht man aber keine Root-Rechte. Zunächst sollte man
virtualenv und
virtualenvwrapper installiert
haben, entweder aus den debian/Ubuntu-Paketquellen oder über easy_install/pip.
Dann installiert man die Dependencies um NumPy zu kompilieren, erzeugt dann die
virtuelle Python-Umgebung (im Beispiel mit dem Namen audiolab
) und
installiert dann mit pip die ganzen Python-Pakete (am Besten eins nach dem
anderen, um eventuelle Fehler besser zu bemerken):
sudo apt-get install build-dep python-numpy mkvirtualenv audiolab pip install numpy pip install matplotlib pip install scikits.audiolab pip install ipython
Unter neueren debian/Ubuntu-Versionen kann es vorkommen, dass man eine
Fehlermeldung beim Kompilieren der Audiolab-Extension bekommt, weil die
sndfile Bibliothek nicht gefunden wird. Dies liegt daran, dass das
Debian-Paket libsndfile1-dev
die Links mit den generischen .so-Namen
nun in einem Architektur-spezifischen Verzeichnis unterhalb /usr/lib
erstellt, also z.B. /usr/lib/i386-linux-gnu
. Davon weiß aber leider
die NumPy-Variante von distutils nichts, welche die Kompilierung steuert. Man
kann ihr dies aber beibringen, indem man die Datei ~/.numpy-site.cfg
erstellt und folgendes einfügt:
[DEFAULT] library_dirs = /usr/lib64:/usr/lib:/usr/lib/<arch>-linux-gnu include_dirs = /usr/include:/usr/include/X11
wobei <arch>
mit der Ausgabe von uname -i
zu ersetzen ist, also i.d.R.
entweder i386
oder x86_64
. Danach sollte die Kompilierung und Installation
fehlerfrei klappen, auch wenn es Hunderte von Kompilerwarnungen hagelt.
scikits.samplerate
Eine weitere interessante SciPy-Extension ist scikits.samplerate, die das Ändern der Samplingrate von Sampledaten in hoher Qualität ermöglicht. Auch hier muss selbst kompiliert werden:
sudo apt-get install libsamplerate0-dev sudo pip install scikits.samplerate
Unter Windows muss man entsprechende Binary-Installer von den Webseiten der
Projekte runter laden und installieren. Wichtig ist hier, dass man Python 2.x und
nicht Python 3.x verwenden sollte. (Update 2011-02-28: so schnell
können Informationen veralten: heute ist SciPy 0.9.0 raus gekommen, das nun
auch Python 3 unterstützt. Hier gibt es Windows und OS X (10.6)
Binary-Installer)
Unter Mac OS X gilt das Gleiche oder man installiert alles über Paketmanager
wie fink oder
MacPorts.
finally:
Jetzt kann man das Ganze ausprobieren: Shell öffnen und ipython -pylab
(Return) eingeben. Man landet am Python-Prompt. Hier kann man sich mit
help(pylab)
erstmal die Hilfe zur NumPy/matplotlib-Umgebung anzeigen lassen.
Als klitzekleines Beispiel hier mal die Erzeugung eines Plots einer
Sinusschwingung aus 128 Samples:
# import Statements in ipython -pylab nicht notwendig, # da automatisch beim Start erfolgt. from numpy import * from matplotlib.pyplot import plot # 128 Kreiswinkel als Radians-Werte # linspace gibt ein Array mit 128 Werten zwischen # 0 und 2 * pi zurück. 'pi' wird im numpy Paket definiert a1 = linspace(0, 2 * pi, 128) # Sinus-Funktion auf jedes Element des Arrays anwenden a2 = sin(a1) # Plot anzeigen. 'ro' => Darstellung der Werte mit roten Punkten plot(a2, 'ro')
Das sieht dann so aus:
matplotlib unterstützt die Ausgabe mit mehreren GUI-Toolkits oder zahlreichen Dateiformaten. Näheres in der Dokumentation.