Springe zum Hauptinhalt

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' =&gt; Darstellung der Werte mit roten Punkten
plot(a2, 'ro')

Das sieht dann so aus:

Plot einer Sinuswelle

matplotlib unterstützt die Ausgabe mit mehreren GUI-Toolkits oder zahlreichen Dateiformaten. Näheres in der Dokumentation.