aboutsummaryrefslogtreecommitdiff
path: root/doc/tutorials
diff options
context:
space:
mode:
Diffstat (limited to 'doc/tutorials')
-rw-r--r--doc/tutorials/externals-howto/HOWTO-externals-de.tex1802
-rw-r--r--doc/tutorials/externals-howto/HOWTO-externals-en.tex1750
-rw-r--r--doc/tutorials/externals-howto/example1/helloworld.c92
-rw-r--r--doc/tutorials/externals-howto/example2/counter.c86
4 files changed, 3730 insertions, 0 deletions
diff --git a/doc/tutorials/externals-howto/HOWTO-externals-de.tex b/doc/tutorials/externals-howto/HOWTO-externals-de.tex
new file mode 100644
index 00000000..2bd05f63
--- /dev/null
+++ b/doc/tutorials/externals-howto/HOWTO-externals-de.tex
@@ -0,0 +1,1802 @@
+% format latexg -*- latex -*-
+
+\documentclass[12pt, a4paper,austrian, titlepage]{article}
+
+
+%% HOWTO write an external for pd
+%% by IOhannes m zmölnig
+%%
+%% this document is released under the CreativeCommons Attribution-ShareAlike 2.5
+%%
+%% http://creativecommons.org/licenses/by-sa/2.5/
+
+%sprache
+\usepackage[latin1]{inputenc}
+\usepackage[T1]{fontenc}
+\usepackage{babel}
+
+% add hypertext support (fine for latex2html)
+\usepackage{html}
+
+% add landscape support (for rotating text through 90deg)
+\usepackage{lscape}
+
+
+%\begin{latexonly}
+% pdf kompatibilität
+\newif\ifpdf
+\ifx\pdfoutput\undefined
+ \pdffalse % we are not running PDFLatex
+\else
+ \pdfoutput=1 % yes, we are running PDFLatex
+ \pdftrue
+\fi
+
+\latexhtml{
+\ifpdf
+ \usepackage[pdftex]{graphicx}
+ \pdfcompresslevel=9
+\else
+ \usepackage{graphicx}
+\fi
+}{
+\usepackage{graphicx}
+}
+
+
+\title{
+HOWTO \\
+write an External \\
+for {\em puredata}
+}
+
+\author{
+johannes m zmölnig \\
+\\
+{\em
+\latexhtml{institut für elektronische musik und akustik}
+{\htmladdnormalink{institut für elektronische musik und akustik}{http://iem.at}}
+}
+}
+
+\date{}
+
+\begin {document}
+\maketitle
+
+\hyphenation{Echt-zeit}
+\hyphenation{Computer-musik-program-men}
+\hyphenation{Echt-zeit-Computer-musik-pro-gramm}
+
+\begin{abstract}
+pd ist ein graphisches Computermusiksystem in der Tradition von IRCAMs {\em ISPW-max}.
+
+Obwohl eine Fülle von Funktionen von pd selbst zur Verfügung gestellt
+werden, stößt man doch manchmal an die Grenzen dessen,
+das mit diesen Primitiven und ihren Kombinationen möglich ist.
+
+Deswegen bietet pd die Möglichkeit, eigene Primitive (``objects'', Objekte) in komplexen
+Programmiersprachen wie {\tt C/C++} zu erstellen.
+
+In diesem Dokument soll beschrieben werden, wie man solche Primitive mit Hilfe der
+Sprache {\tt C}, in der auch pd selbst realisiert wurde, schreibt.
+\end{abstract}
+
+
+\vfill
+\newpage
+
+\tableofcontents
+
+\vfill
+\newpage
+
+\section{Voraussetzungen und Begriffsbestimmungen}
+
+pd bezieht sich auf das graphische Echtzeit-Computermusikprogramm von
+Miller~S.~Puckette.
+{\em puredata}.
+
+Zum Verständnis dieses Dokumentes wird der Umgang mit pd sowie
+Verständnis von Programmiertechniken, insbesondere {\tt C} vorausgesetzt.
+
+Zum Schreiben von eigenen Primitiven wird weiters ein {\tt C}-Compiler,
+der dem {\tt ANSI-C}-Standard genügt, notwendig sein.
+Solche Compiler sind beispielsweise der {\em Gnu C-Compiler} (gcc) auf linux-Systemen oder
+{\em Visual-C++ 6.0} (vc6) auf Windows-Systemen.
+
+\subsection{Klassen, Instanzen und Objekte}
+pd ist in der Programmiersprache {\tt C} geschrieben.
+Allerdings ist pd auf Grund seiner graphischen Natur ein {\em objektorientiertes} System.
+Da {\tt C} die Verwendung von Klassen nicht sehr gut unterstützt, ist der resultierende
+Quellcode nicht so elegant wie er zum Beispiel unter {\tt C++} wäre.
+
+Der Ausdruck {\em Klasse} bezieht sich in diesem Dokument auf die Realisierung eines
+Konzeptes, bei dem Daten und Manipulatoren eine Einheit bilden.
+
+Konkrete {\em Instanzen einer Klasse} sind {\em Objekte}.
+
+\subsection{Internals, Externals und Libraries}
+Um Begriffsverwirrungen von vorneherein auszuschließen, seien hier kurz die Ausdrücke
+{\em Internal}, {\em External} und {\em Library} erklärt.
+
+\paragraph{Internal}
+Ein {\em Internal} ist eine Klasse, die in pd eingebaut ist.
+Viele Primitive wie ``+'', ``pack'' oder ``sig\~\/`` sind {\em Internals}
+
+\paragraph{External}
+Ein {\em External} ist eine Klasse, die nicht in pd eingebaut ist und erst zur Laufzeit
+nachgeladen wird.
+Sind sie einmal im Speicher von pd, so sind {\em Externals} nicht mehr von {\em Internals} zu
+unterscheiden.
+
+\paragraph{Library}
+Eine {\em Library} bezeichnet eine Sammlung von {\em Externals},
+die gemeinsam in eine Binärdatei kompiliert werden.
+
+{\em Library}-Dateien müssen eine betriebssystemabhängige Namenskonvention einhalten:
+
+\begin{tabular}{c||c|c|c}
+Bibliothek&linux&irix&Win32 \\
+\hline
+{\tt my\_lib}&{\tt my\_lib.pd\_linux}&{\tt my\_lib.pd\_irix}&
+{\tt my\_lib.dll}\\
+\end{tabular}
+
+Die einfachste Form einer {\em Library} beinhaltet genau ein {\em External},
+das den selben Name trägt, wie auch die {\em Library}
+
+Im Gegensatz zu Externals können {\em Libraries} mit bestimmten Befehlen
+von pd importiert werden.
+Ist eine {\em Library} importiert worden,
+so sind alle {\em Externals}, die sie beinhaltet,
+in den Speicher geladen und stehen als Objekte zur Verfügung.
+
+pd stellt zwei Methoden zur Verfügung, um {\em Libraries} zu laden:
+\begin{itemize}
+\item mit der commandline-Option ``{\tt -lib my\_lib}''
+\item durch Kreieren eines Objektes ``{\tt my\_lib}''
+\end{itemize}
+
+Die erste Methode lädt die {\em Library} sofort beim Starten von pd.
+Dies ist die zu bevorzugende Methode für {\em Libraries},
+die mehrere {\em Externals} beinhalten.
+
+Die zweite Methode ist für {\em Libraries} zu bevorzugen, die genau
+ein {\em External} mit dem selben Namen beinhalten.
+Bei der zweiten Methode wird zuerst geprüft, ob eine Klasse namens ``my\_lib'' bereits
+in den Speicher geladen ist.
+Ist dies nicht der Fall\footnote
+{Ist eine solche Klasse bereits im Speicher, wird ein
+Objekt namens ``my\_lib'' instanziiert und der Vorgang bricht ab.
+Es wird also keine neue {\em Library} geladen.
+Man kann daher keine {\em Libraries} mit bereits verwendeten Klassennamen,
+wie zum Beispiel ``abs'', laden.}
+so werden alle Pfade untersucht,
+ob darin eine Datei namens ``{\tt my\_lib.pd\_linux}''\footnote{
+oder einer anderen betriebssystemabhängigen Dateinamenerweiterung (s.o.)}
+existiert.
+Wird eine solche Datei gefunden, so werden alle in ihr enthaltenen {\em Externals}
+in den Speicher geladen.
+Danach wird nachgesehen, ob nun eine Klasse namens ``my\_lib''
+als (neu geladenes) {\em External} im Speicher existiert.
+Ist dies der Fall, so wird eine Instanz dieser Klasse geschaffen.
+Ansonsten wird eine Fehlermeldung ausgegeben, die Instanziierung ist gescheitert.
+
+
+\section{mein erstes External: {\tt helloworld}}
+Wie das beim Erlernen von Programmiersprachen so üblich ist,
+beginnen wir mit ``Hello world''.
+
+Ein Objekt soll geschaffen werden, dass jedesmal, wenn es
+mit ``bang'' getriggert wird, die Zeile ``Hello world!!'' auf
+die Standardausgabe schreibt.
+
+\subsection{die Schnittstelle zu pd}
+Um ein pd-External zu schreiben, braucht man eine wohldefinierte Schnittstelle.
+Diese wird in der Datei ``m\_pd.h'' zur Verfügung gestellt.
+
+\begin{verbatim}
+#include "m_pd.h"
+\end{verbatim}
+
+
+\subsection{eine Klasse und ihr Datenraum}
+Als nächstes muß eine neue Klasse vorbereitet und der
+Datenraum für diese Klasse definiert werden.
+
+\begin{verbatim}
+static t_class *helloworld_class;
+
+typedef struct _helloworld {
+ t_object x_obj;
+} t_helloworld;
+\end{verbatim}
+
+\verb+hello_worldclass+ wird der Zeiger auf die neue Klasse.
+
+Die Struktur \verb+t_helloworld+ (vom Typ \verb+_helloworld+)
+stellt den Datenraum der Klasse dar.
+Ein unverzichtbares Element ist dabei eine Variable des Type \verb+t_object+.
+In ihr werden interne Objekteigenschaften abgelegt, wie zum Beispiel
+die Größe der Objekt-Box bei der graphischen Darstellung, aber auch
+Daten über Inlets und Outlets.
+\verb+t_object+ muss der erste Eintrag in die Struktur sein !
+
+Da bei einer einfachen ``Hello world''-Anwendung keine Variablen gebraucht werden,
+ist die Struktur ansonsten leer.
+
+\subsection{Methodenraum}
+Zu einer Klasse gehören neben einem Datenraum auch ein Satz von
+Manipulatoren (Methoden) mit denen diese Daten manipuliert werden können.
+
+Wird eine Message an eine Instanz unserer Klasse geschickt,
+so wird eine Methoden aufgerufen.
+Diese Mehtoden, die die Schnittstelle zum Messagesystem von pd bilden,
+haben grundsätzlich kein Rückgabeargument, sind also vom Typ \verb+void+.
+
+\begin{verbatim}
+void helloworld_bang(t_helloworld *x)
+{
+ post("Hello world !!");
+}
+\end{verbatim}
+
+Diese Methode hat ein Übergabeargument vom Typ \verb+t_helloworld+,
+sodass wir also unseren Datenraum manipulieren könnten.
+
+Da wir nur ``Hello world!'' ausgeben wollen (und ausserdem unser Datenraum
+recht spärlich ist), verzichten wir auf eine Manipulation.
+
+Mit dem Befehl \verb+post(char *c,...)+ wird eine Meldung an die Standardausgabe
+geschickt.
+Ein Zeilenumbruch wird automatisch angehängt.
+Ansonsten funktioniert \verb+post()+ gleich wie der {\tt C}-Befehl \verb+printf()+.
+
+\subsection{Generierung einer neuen Klasse}
+Um eine neue Klasse zu generieren, müssen Angaben über
+den Datenraum und den Methodenraum dieser Klasse
+beim Laden einer Library an pd übergeben werden.
+
+Wird eine neue Library ``my\_lib'' geladen,
+so versucht pd eine Funktion ``my\_lib\_setup()'' aufzurufen.
+Diese Funktion (oder von ihr aufgerufene Funktionen) teilt pd mit,
+welche Eigenschaften die neuen Klassen haben.
+Sie wird nur einmal, beim Laden der Library aufgerufen.
+
+\begin{verbatim}
+void helloworld_setup(void)
+{
+ helloworld_class = class_new(gensym("helloworld"),
+ (t_newmethod)helloworld_new,
+ 0, sizeof(t_helloworld),
+ CLASS_DEFAULT, 0);
+
+ class_addbang(helloworld_class, helloworld_bang);
+}
+\end{verbatim}
+
+\paragraph{class\_new}
+
+Der Befehl \verb+class_new+ kreiert eine neue Klasse und gibt einen Zeiger auf diesen
+Prototyp zurück.
+
+Das erste Argument ist der symbolische Name der Klasse.
+
+Die nächsten beiden Argumente definieren Konstruktor und Destruktor der Klasse.
+Wenn in einen pd-Patch ein Objekt kreiert wird,
+instanziiert der Konstruktor \verb+(t_newmethod)helloworld_new+ diesses Objekt
+und initialisiert den Datenraum.
+Wird ein pd-Patch geschlossen oder ein Objekt daraus entfernt,
+so gibt der Destruktor, wenn notwendig, dynamisch reservierten Speicher wieder frei.
+Der Speicherplatz für den Datenraum selbst wird von pd automatisch freigegeben.
+Deshalb kann in diesem Beispiel auf einen Destruktor verzichtet werden,
+folglich wird dieses Argument auf ``0'' gesetzt.
+
+Damit pd genug Speicher für den Datenraum allozieren und wieder freigeben kann,
+wird die Größe dieser Datenstruktur als viertes Argument übergeben.
+
+Das fünfte Argument bestimmt, wie Klasseninstanzen graphisch dargestellt werden und
+ob sie mit anderen Objekten verknüpfbar sind.
+Der Standardwert \verb+CLASS_DEFAULT+ (oder einfacher: ``0'') bezieht sich auf
+ein Objekt mit mindestens einem Inlet.
+Würde man keinen Eingang wollen (wie zum Beispiel beim Internal ``receive''),
+so kann man diesen Wert auf \verb+CLASS_NOINLET+ setzen.
+
+Die restlichen Argumente definieren die Übergabeargumente eines Objektes und deren Typ.
+
+Bis zu sechs numerische und symbolische Objektargumente können in beliebiger Reihenfolge
+mit \verb+A_DEFFLOAT+ und \verb+A_DEFSYMBOL+ angegeben werden.
+Sollen mehr Argumente übergeben werden oder die Atomtyp-Reihenfolge flexibler sein,
+so bietet \verb+A_GIMME+ die Übergabe einer beliebigen Liste von Atomen.
+
+Die Objektargumentliste wird mit ``0'' terminiert.
+In unserem Beispiel sind also keine Übergabeargumente für die Klasse vorgesehen.
+
+\paragraph{class\_addbang}
+Jetzt muss zur Klasse noch ein Methodenraum hinzugefügt werden.
+
+Mit \verb+class_addbang+ wird der durch das erste Argument definierten Klasse
+eine Methode für eine ``bang''-Message hinzuzugefügt.
+Diese Methode ist das zweite Argument.
+
+
+
+\subsection{Konstruktor: Instanziierung eines Objektes}
+Jedesmal, wenn in einem pd-Patch ein Objekt einer Klasse kreiert wird,
+schafft der mit \verb+class_new+ angegebene Konstruktor eine neue Instanz der Klasse.
+
+Der Konstruktor ist immer vom Typ \verb+void *+
+
+\begin{verbatim}
+void *helloworld_new(void)
+{
+ t_helloworld *x = (t_helloworld *)pd_new(helloworld_class);
+
+ return (void *)x;
+}
+\end{verbatim}
+
+Die Übergabeargumente der Konstruktorfunktion hängen von den mit
+\verb+class_new+ angegebenen Objektargumenten ab.
+
+\begin{tabular}{l|l}
+\verb+class_new+-Argument&Konstruktorargument\\
+\hline
+\verb+A_DEFFLOAT+&\verb+t_floatarg f+ \\
+\verb+A_DEFSYMBOL+&\verb+t_symbol *s+ \\
+\verb+A_GIMME+&\verb+t_symbol *s, int argc, t_atom *argv+
+\end{tabular}
+
+Da in diesem Beispiel keine Objektargumente existieren, hat auch
+der Konstruktor keine.
+
+Die Funktion \verb+pd_new+ reserviert Speicher für den Datenraum, initialisiert
+die objektinternen Variablen und gibt einen Zeiger auf den Datenraum zurück.
+
+Der Typ-Cast auf den Datenraum ist notwendig.
+
+Normalerweise würden im Konstruktor auch die Objektvariablen initialisiert werden.
+In diesem Beispiel ist dies aber nicht notwendig.
+
+Der Konstruktor muss einen Zeiger auf den instanziierten Datenraum zurückgeben.
+
+\subsection{der Code: \tt helloworld}
+
+\begin{verbatim}
+#include "m_pd.h"
+
+static t_class *helloworld_class;
+
+typedef struct _helloworld {
+ t_object x_obj;
+} t_helloworld;
+
+void helloworld_bang(t_helloworld *x)
+{
+ post("Hello world !!");
+}
+
+void *helloworld_new(void)
+{
+ t_helloworld *x = (t_helloworld *)pd_new(helloworld_class);
+
+ return (void *)x;
+}
+
+void helloworld_setup(void) {
+ helloworld_class = class_new(gensym("helloworld"),
+ (t_newmethod)helloworld_new,
+ 0, sizeof(t_helloworld),
+ CLASS_DEFAULT, 0);
+ class_addbang(helloworld_class, helloworld_bang);
+}
+\end{verbatim}
+
+
+\section{ein komplexes External: {\tt counter}}
+
+Als nächstes soll ein einfacher Zähler als External geschrieben werden.
+Ein ``bang''-Trigger soll den aktuellen Zählerstand am Outlet ausgeben
+und anschließend um 1 erhöhen.
+
+Diese Klasse unterscheidet sich nicht sonderlich von der vorherigen,
+ausser dass nun eine interne Variable ``Zählerstand'' benötigt
+wird und das Ergebnis nicht mehr auf die Standardausgabe geschrieben sondern
+als Message zu einem Outlet geschickt wird.
+
+\subsection{Variablen eines Objektes}
+Ein Zähler braucht natürlich eine Zustandsvariable,
+in der der aktueller Zählerstand gespeichert ist.
+
+Solche zum Objekt gehörigen Zustandsvariablen werden im Datenraum abgelegt.
+
+\begin{verbatim}
+typedef struct _counter {
+ t_object x_obj;
+ t_int i_count;
+} t_counter;
+\end{verbatim}
+
+Die Ganzzahlvariable \verb+i_count+ beschreibt den Zählerstand.
+Natürlich könnte man sie auch als Gleitkommawert realisieren,
+doch traditionell werden Zähler ganzzahlig ausgeführt.
+
+\subsection{Übergabeargumente}
+Für einen Zähler ist es durchaus sinnvoll, wenn man den Startwert festlegen kann.
+Hier soll der Startwert dem Objekt bei der Kreation übergeben werden.
+
+\begin{verbatim}
+void counter_setup(void) {
+ counter_class = class_new(gensym("counter"),
+ (t_newmethod)counter_new,
+ 0, sizeof(t_counter),
+ CLASS_DEFAULT,
+ A_DEFFLOAT, 0);
+
+ class_addbang(counter_class, counter_bang);
+}
+\end{verbatim}
+
+Es ist also ein Argument zur Funktion \verb+class_new+ hinzugekommen:
+
+\verb+A_DEFFLOAT+ teilt mit, dass das Objekt ein Übergabeargument
+vom Typ \verb+t_floatarg+ hat.
+
+
+
+\subsection{Konstruktor}
+Dem Konstruktor kommen nun mehrere neue Aufgaben zu.
+Zum ersten muss eine Variable initialisiert werden,
+zum anderen muss auch ein Outlet für das Objekt geschaffen werden.
+\begin{verbatim}
+void *counter_new(t_floatarg f)
+{
+ t_counter *x = (t_counter *)pd_new(counter_class);
+
+ x->i_count=f;
+ outlet_new(&x->x_obj, &s_float);
+
+ return (void *)x;
+}
+\end{verbatim}
+
+Die Konstruktorfunktion hat jetzt ein Argument fom Typ \verb+t_floatarg+, wie es in
+der Setup-Routine \verb+class_new+ deklariert worden ist.
+Dieses Argument initialisiert den Zähler.
+
+Einer neuer Outlet wird mit der Funktion \verb+outlet_new+ geschaffen.
+Das erste Argument ist ein Zeiger auf die Objektinterna,
+in denen der neue Ausgang geschaffen wird.
+
+Das zweite Argument ist eine symbolische Typbeschreibung des Ausgangs.
+Da der Zähler numerische Werte ausgeben soll, ist er vom Typ ``float''.
+Sollte der Ausgang für Messages mit verschiedenen Selectoren verwendet werden,
+so ist dieser Wert ``0''.
+
+\verb+outlet_new+ gibt einen Zeiger auf den neuen Outlet zurück und speichert diesen
+Zeiger in der \verb+t_object+-Variablen \verb+x_obj.ob_outlet+.
+Wird nur ein Outlet verwendet, muss daher der Zeiger nicht extra im Datenraum gespeichert
+werden.
+Werden mehrere Outlets verwendet, so müssen diese Zeiger im Datenraum gespeichert werden.
+
+\subsection{die Zählermethode}
+Bei einem Triggerevent soll der alte Zählerstand ausgegeben und um eins inkrementiert werden.
+
+\begin{verbatim}
+void counter_bang(t_counter *x)
+{
+ t_float f=x->i_count;
+ x->i_count++;
+ outlet_float(x->x_obj.ob_outlet, f);
+}
+\end{verbatim}
+
+Die Funktion \verb+outlet_float+ gibt an dem Outlet, auf den das erste Argument verweist,
+eine Gleitkommazahl (zweites Argument) aus.
+
+Hier wird zuerst der Zählerstand in eine Gleitkomma-Buffervariable gespeichert.
+Danach wird er inkrementiert und dann wird erst die Buffervariable ausgegeben.
+
+Was auf den ersten Blick unnötig erscheint, macht bei näherer Betrachtung Sinn:
+Die Buffervariable wurde gleich als \verb+t_float+ realisiert,
+da sich \verb+outlet_float+ sowieso einen Gleitkommawert erwartet
+und ein Cast unvermeidlich ist.
+
+Würde der Zählerstand zuerst an den Outlet geschickt werden und
+danach erst inkrementiert werden, würde dies unter Umständen zu einem etwas seltsamen
+Verhalten führen.
+Wenn nämlich der Zählerausgang wieder an den Inlet zurückgeführt würde, der
+Zähler sich also selbst triggerte, so würde die Zählermethode erneut
+aufgerufen, ohne dass der Zählerstand inkrementiert worden wäre.
+Dies ist im Allgemeinen aber unerwünscht.
+
+Man kann übrigens das gleiche Ergebnis wie hier mit nur einer einzigen Zeile erreichen,
+doch sieht man das {\em Reentrant}-Problem dann nicht sehr gut.
+
+\subsection{der Code: \tt counter}
+
+\begin{verbatim}
+#include "m_pd.h"
+
+static t_class *counter_class;
+
+typedef struct _counter {
+ t_object x_obj;
+ t_int i_count;
+} t_counter;
+
+void counter_bang(t_counter *x)
+{
+ t_float f=x->i_count;
+ x->i_count++;
+ outlet_float(x->x_obj.ob_outlet, f);
+}
+
+void *counter_new(t_floatarg f)
+{
+ t_counter *x = (t_counter *)pd_new(counter_class);
+
+ x->i_count=f;
+ outlet_new(&x->x_obj, &s_float);
+
+ return (void *)x;
+}
+
+void counter_setup(void) {
+ counter_class = class_new(gensym("counter"),
+ (t_newmethod)counter_new,
+ 0, sizeof(t_counter),
+ CLASS_DEFAULT,
+ A_DEFFLOAT, 0);
+
+ class_addbang(counter_class, counter_bang);
+}
+\end{verbatim}
+
+
+\section{ein komplexeres External: \tt counter}
+
+Man kann natürlich auch einen einfache Zähler ein bißchen komplexer gestalten.
+Es wäre zum Beispiel sinnvoll,
+wenn der Zählerstand auf einen Startwert zurückgesetzt werden könnte,
+wenn man Start- und Endwert bestimmen könnte und auch die Schrittweite variabel wäre.
+
+Bei jedem Zählerüberlauf soll ein zweiter Outlet eine ``bang''-Message schicken und der
+Zähler auf den Startwert zurückgesetzt werden.
+
+\subsection{erweiterter Datenraum}
+
+\begin{verbatim}
+typedef struct _counter {
+ t_object x_obj;
+ t_int i_count;
+ t_float step;
+ t_int i_down, i_up;
+ t_outlet *f_out, *b_out;
+} t_counter;
+\end{verbatim}
+
+Der Datenraum wurde also erweitert um Variablen für Schrittweite und Start- bzw. Stopwert.
+Weiters werden Zeiger auf zwei Outlets zur Verfügung gestellt.
+
+\subsection{Erweiterung der Klasse}
+Da nun die Klassenobjekte verschiedene Messages, wie ``set'' und ``reset'',
+verstehen können sollen, mussen der Methodenraum entsprechend erweitert werden.
+
+\begin{verbatim}
+ counter_class = class_new(gensym("counter"),
+ (t_newmethod)counter_new,
+ 0, sizeof(t_counter),
+ CLASS_DEFAULT,
+ A_GIMME, 0);
+\end{verbatim}
+
+Der Klassengenerator \verb+class_new+ ist um das Objektübergabeargument
+\verb+A_GIMME+ erweitert.
+Damit kann eine dynamische Anzahl von Argumenten bei der Objektinstanziierung
+verwaltet werden.
+
+\begin{verbatim}
+ class_addmethod(counter_class,
+ (t_method)counter_reset,
+ gensym("reset"), 0);
+\end{verbatim}
+
+\verb+class_addmethod+ fügt einer Klasse eine Methode mit für einen
+beliebigen Selector hinzu.
+
+Das erste Argument ist die Klasse,
+zu der die Methode (zweites Argument) hinzugefügt wird.
+
+Das dritte Argument ist der symbolische Selector,
+der mit der Methode assoziiert wird.
+
+Die restlichen ``0''-terminierten Argumente
+beschreiben die Atomliste, die dem Selector folgt.
+
+\begin{verbatim}
+ class_addmethod(counter_class,
+ (t_method)counter_set, gensym("set"),
+ A_DEFFLOAT, 0);
+ class_addmethod(counter_class,
+ (t_method)counter_bound, gensym("bound"),
+ A_DEFFLOAT, A_DEFFLOAT, 0);
+\end{verbatim}
+
+Eine Methode für den Selector ``set'', gefolgt von einem numerischen Wert,
+wird hinzugefügt.
+
+Für den Selector ``bound'', gefolgt von zwei numerischen Werten,
+wird ebenfalls eine Methode zur Klasse hinzugefügt.
+
+\begin{verbatim}
+ class_sethelpsymbol(counter_class, gensym("help-counter"));
+\end{verbatim}
+
+Clickt man mit der rechten Maustaste auf ein pd-Objekt,
+so kann man sich einen Hilfe-Patch für die zugehörige Objektklasse anzeigen lasse.
+Standardmäßig wird ist dies ein Patch mit dem symbolischen Klassennamen
+im Verzeichnis ``{\em doc/5.reference/}'' gesucht.
+Mit dem Befehl \verb+class_sethelpsymbol+ kann ein alternativer Patch angegeben werden.
+
+\subsection{Konstruktion von In- und Outlets}
+
+Bei der Objektkreation sollten dem Objekt verschiedene Argumente übergeben
+werden.
+
+\begin{verbatim}
+void *counter_new(t_symbol *s, int argc, t_atom *argv)
+\end{verbatim}
+Durch die Argumentendeklaration in der \verb+class_new+-Funktion
+mit \verb+A_GIMME+, werden dem Konstruktor folgende Argumente
+übergeben:
+
+\begin{tabular}{c|l}
+\verb+t_symbol *s+ & der symbolische Namen,\\
+& mit dem das Objekt kreiert wurde \\
+\verb+int argc+ & die Anzahl, der dem Objekt übergebenen Argumente\\
+\verb+t_atom *argv+ & ein Zeiger auf eine Liste von {\tt argc} Atomen
+\end{tabular}
+
+\begin{verbatim}
+ t_float f1=0, f2=0;
+
+ x->step=1;
+ switch(argc){
+ default:
+ case 3:
+ x->step=atom_getfloat(argv+2);
+ case 2:
+ f2=atom_getfloat(argv+1);
+ case 1:
+ f1=atom_getfloat(argv);
+ break;
+ case 0:
+ }
+ if (argc<2)f2=f1;
+ x->i_down = (f1<f2)?f1:f2;
+ x->i_up = (f1>f2)?f1:f2;
+
+ x->i_count=x->i_down;
+\end{verbatim}
+
+Werden drei Argumente übergeben, so sollten dies {\em untere Zählergrenze},
+{\em obere Zählergrenze} und {\em Schrittgröße} sein.
+Werden nur zwei Argumente übergeben,
+so wird die Schrittgröße standardmäßig auf ``1'' gesetzt.
+Bei nur einem Argument, sei dies der {\em Startwert} des Zählers,
+die {\em Schrittgröße} sei ``1''.
+
+\begin{verbatim}
+ inlet_new(&x->x_obj, &x->x_obj.ob_pd,
+ gensym("list"), gensym("bound"));
+\end{verbatim}
+Die Funktion \verb+inlet_new+ erzeugt einen neuen ``aktiven'' Inlet.
+``Aktiv'' heißt, dass eine Klassenmethode ausgeführt wird,
+wenn eine Message in den einen ``aktiven'' Inlet geschickt wird.
+
+Von der Software-Architektur her ist der erste Inlet immer ``aktiv''.
+
+Die ersten beiden Argumente der \verb+inlet_new+-Funktion
+sind Zeiger auf die Objektinterna und die graphische Darstellung des Objektes.
+
+Der symbolische Selector, der durch das dritte Argument spezifiziert wird,
+wird für diesen Inlet durch einen anderen symbolischen Selector (viertes Argument)
+substituiert.
+
+Durch die Substitution von Selectoren kann eine Message
+an einem bestimmten rechten Eingang wie eine Message mit einem bestimmten Selector
+am linken Eingang betrachtet werden.
+
+Dies bedeutet
+\begin{itemize}
+\item Der substituierende Selector muss mit \verb+class_addmethod+ angegeben werden.
+\item Man kann einen bestimmten rechten Eingang simulieren,
+indem man dem ersten Eingang eine Message mit dem Selector dieses Eingangs schickt.
+\item Es ist nicht möglich, einem rechten Eingang Methoden für mehr als einen Selector
+zuzuweisen. Insbesondere ist es nicht möglich, ihm eine allgemeine Methode
+für einen beliebigen Selector zuzuweisen.
+\end{itemize}
+
+\begin{verbatim}
+ floatinlet_new(&x->x_obj, &x->step);
+\end{verbatim}
+\verb+floatinlet_new+ generiert einen ``passiven'' Inlet für numerische Werte.
+``Passive'' Eingänge erlauben, dass ein Speicherplatz bestimmten Typs im
+Variablenraum des Objektes von außen direkt beschrieben werden kann.
+Dadurch ist zum Beispiel eine Abfrage nach illegalen Eingaben nicht möglich.
+Das erste Argument ist dabei ein Zeiger auf die interne Objektinfrastruktur.
+Das zweite Argument ist ein Zeiger auf den Speicherplatz, auf den geschrieben wird.
+
+Es können ``passive'' Eingänge für numerische (Gleitkomma\footnote{
+Deswegen ist der {\tt step}-Wert des Klassendatenraums als {\tt t\_float} realisiert.})
+-Werte, symbolische Werte und Pointer geschaffen werden.
+
+\begin{verbatim}
+ x->f_out = outlet_new(&x->x_obj, &s_float);
+ x->b_out = outlet_new(&x->x_obj, &s_bang);
+\end{verbatim}
+
+Die von \verb+outlet_new+ zurückgegebenen Zeiger auf die geschaffenen Outlets,
+müssen im Klassendatenraum gespeichert werden,
+damit sie später von den Ausgaberoutinen angesprochen werden.
+
+Die Reihenfolge der Generierung von In- und Outlets ist wichtig,
+da sie der Reihenfolge der Ein- und Ausgänge der graphischen Repräsentation
+des Objektes entsprechen.
+
+\subsection{erweiterter Methodenraum}
+
+Der Methode für die ``bang''-Message muss natürlich der komplexeren Zählerstruktur
+genüge tun.
+
+
+\begin{verbatim}
+void counter_bang(t_counter *x)
+{
+ t_float f=x->i_count;
+ t_int step = x->step;
+ x->i_count+=step;
+ if (x->i_down-x->i_up) {
+ if ((step>0) && (x->i_count > x->i_up)) {
+ x->i_count = x->i_down;
+ outlet_bang(x->b_out);
+ } else if (x->i_count < x->i_down) {
+ x->i_count = x->i_up;
+ outlet_bang(x->b_out);
+ }
+ }
+ outlet_float(x->f_out, f);
+}
+\end{verbatim}
+
+Die einzelnen Outlets werden von den \verb+outlet_...+-Funktionen über
+die Zeiger auf diese Ausgänge identifiziert.
+
+Die übrigen Methoden müssen noch implementiert werden:
+
+\begin{verbatim}
+void counter_reset(t_counter *x)
+{
+ x->i_count = x->i_down;
+}
+
+void counter_set(t_counter *x, t_floatarg f)
+{
+ x->i_count = f;
+}
+
+void counter_bound(t_counter *x, t_floatarg f1, t_floatarg f2)
+{
+ x->i_down = (f1<f2)?f1:f2;
+ x->i_up = (f1>f2)?f1:f2;
+}
+\end{verbatim}
+
+\subsection{der Code: \tt counter}
+
+\begin{verbatim}
+#include "m_pd.h"
+
+static t_class *counter_class;
+
+typedef struct _counter {
+ t_object x_obj;
+ t_int i_count;
+ t_float step;
+ t_int i_down, i_up;
+ t_outlet *f_out, *b_out;
+} t_counter;
+
+void counter_bang(t_counter *x)
+{
+ t_float f=x->i_count;
+ t_int step = x->step;
+ x->i_count+=step;
+
+ if (x->i_down-x->i_up) {
+ if ((step>0) && (x->i_count > x->i_up)) {
+ x->i_count = x->i_down;
+ outlet_bang(x->b_out);
+ } else if (x->i_count < x->i_down) {
+ x->i_count = x->i_up;
+ outlet_bang(x->b_out);
+ }
+ }
+
+ outlet_float(x->f_out, f);
+}
+
+void counter_reset(t_counter *x)
+{
+ x->i_count = x->i_down;
+}
+
+void counter_set(t_counter *x, t_floatarg f)
+{
+ x->i_count = f;
+}
+
+void counter_bound(t_counter *x, t_floatarg f1, t_floatarg f2)
+{
+ x->i_down = (f1<f2)?f1:f2;
+ x->i_up = (f1>f2)?f1:f2;
+}
+
+void *counter_new(t_symbol *s, int argc, t_atom *argv)
+{
+ t_counter *x = (t_counter *)pd_new(counter_class);
+ t_float f1=0, f2=0;
+
+ x->step=1;
+ switch(argc){
+ default:
+ case 3:
+ x->step=atom_getfloat(argv+2);
+ case 2:
+ f2=atom_getfloat(argv+1);
+ case 1:
+ f1=atom_getfloat(argv);
+ break;
+ case 0:
+ }
+ if (argc<2)f2=f1;
+
+ x->i_down = (f1<f2)?f1:f2;
+ x->i_up = (f1>f2)?f1:f2;
+
+ x->i_count=x->i_down;
+
+ inlet_new(&x->x_obj, &x->x_obj.ob_pd,
+ gensym("list"), gensym("bound"));
+ floatinlet_new(&x->x_obj, &x->step);
+
+ x->f_out = outlet_new(&x->x_obj, &s_float);
+ x->b_out = outlet_new(&x->x_obj, &s_bang);
+
+ return (void *)x;
+}
+
+void counter_setup(void) {
+ counter_class = class_new(gensym("counter"),
+ (t_newmethod)counter_new,
+ 0, sizeof(t_counter),
+ CLASS_DEFAULT,
+ A_GIMME, 0);
+
+ class_addbang (counter_class, counter_bang);
+ class_addmethod(counter_class,
+ (t_method)counter_reset, gensym("reset"), 0);
+ class_addmethod(counter_class,
+ (t_method)counter_set, gensym("set"),
+ A_DEFFLOAT, 0);
+ class_addmethod(counter_class,
+ (t_method)counter_bound, gensym("bound"),
+ A_DEFFLOAT, A_DEFFLOAT, 0);
+
+ class_sethelpsymbol(counter_class, gensym("help-counter"));
+}
+\end{verbatim}
+
+
+\section{ein Signal-External: {\tt pan\~\/}}
+Signalklassen sind normale Klassen, die zusätzlich Methoden
+für Signale bereitstellen.
+
+Alle Methoden und Konzepte die mit normalen Objektklassen realisierbar sind,
+sind also auch mit Signalklassen zuverwirklichen.
+
+Per Konvention enden die symbolischen Namen mit einer Tilde \~\/.
+
+Anhand einer Klasse ``pan\~\/`` soll demonstriert werden wie Signalklassen geschrieben
+werden können.
+
+Ein Signal am linken Inlet wird mit einem Signal am zweiten Inlet gemischt.
+Der Mischungsgrad wird als \verb+t_float+-Message an einen dritten Eingang festgelegt.
+
+\subsection{Variablen einer Signalklasse}
+Da eine Signalklasse nur eine erweiterte normale Klasse ist,
+gibt es keine prinzipielle Unterschiede zwischen den Datenräumen.
+
+\begin{verbatim}
+typedef struct _pan_tilde {
+ t_object x_obj;
+
+ t_sample f_pan;
+ t_float f;
+} t_pan_tilde;
+\end{verbatim}
+
+Es wird nur eine Variable für den {\em Mischfaktor} der Panningfunktion benötigt.
+
+Die Variable \verb+f+ wird gebraucht, falls kein Signal am Signalinlet liegt.
+Wird dann an diesen Signalinlet ein numerischer Wert als Message geschickt,
+so ersetzt dieser das Signal und wird in der Variable \verb+f+ gespeichert.
+
+\subsection{Signalklassen}
+
+\begin{verbatim}
+void pan_tilde_setup(void) {
+ pan_tilde_class = class_new(gensym("pan~"),
+ (t_newmethod)pan_tilde_new,
+ 0, sizeof(t_pan_tilde),
+ CLASS_DEFAULT,
+ A_DEFFLOAT, 0);
+
+ class_addmethod(pan_tilde_class,
+ (t_method)pan_tilde_dsp, gensym("dsp"), 0);
+ CLASS_MAINSIGNALIN(pan_tilde_class, t_pan_tilde, f);
+}
+\end{verbatim}
+
+Jeder Signalklasse muss eine Methode für die Signalverarbeitung zugeordnet werden.
+Wenn die Audioengine von pd gestartet wird, wird allen Objekten eine
+Message mit dem Selector ``\verb+dsp+'' geschickt.
+Alle Klassen, die eine Methode für die ``dsp''-Message haben, sind Signalklassen.
+
+Signalklassen, die Signal-Inlets zur Verfügung stellen wollen,
+müssen dies mit dem \verb+CLASS_MAINSIGNALIN+-Makro anmelden.
+Dadurch ist der erste Inlet als Signalinlet deklariert.
+\verb+t_float+-Messages können nicht mehr an einen solchen Eingang
+gesendet werden.
+
+Das erste Argument des Makros ist ein Zeiger auf die Signalklasse.
+Das zweite Argument ist der Typ des Datenraums der Klasse.
+Das dritte Argument ist eine Dummy-Variable aus dem Datenraum, die gebraucht wird,
+um bei nicht vorhandenen Signalen am Signalinlet diese durch \verb+t_float+-Messages
+einfach ersetzen zu können.
+
+\subsection{Konstruktion von Signal-In- und Outlets}
+
+\begin{verbatim}
+void *pan_tilde_new(t_floatarg f)
+{
+ t_pan_tilde *x = (t_pan_tilde *)pd_new(pan_tilde_class);
+
+ x->f_pan = f;
+
+ inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal);
+ floatinlet_new (&x->x_obj, &x->f_pan);
+
+ outlet_new(&x->x_obj, &s_signal);
+
+ return (void *)x;
+}
+\end{verbatim}
+
+Zusätzliche Signal-Eingänge werden normal mit der Routine \verb+inlet_new+
+hinzugefügt.
+Die letzen beiden Argumente sind dann jeweils ein Verweis auf den symbolischen Selector
+``signal'' in der lookup-Tabelle.
+
+Signal-Outlets werden ebenfalls wie Message-Outlets generiert, deren Outlet mit dem
+Selector ``signal'' versehen ist.
+
+
+\subsection{DSP-Methode}
+Wenn die Audio-Engine von pd eingeschalten wird,
+so teilen ihr alle Signal-Objekte mit,
+welche Methode von ihrer Klasse zur digitalen Signalverarbeitung herangezogen werden soll.
+
+Die ``DSP''-Methode hat als Argumente einen Zeiger auf den Klassendatenraum und
+einen Zeiger auf ein Array von Signalen.
+
+Die Signale im Array sind so angeordnet, dass sie am graphischen Objekt
+im Uhrzeigersinn gelesen werden.\footnote{
+Sofern linke und rechte Ein- und Ausgangssignale vorhanden sind, gilt also:
+Zuerst kommt das linke Eingangssignal, danach die rechten Eingangssignale;
+nach den rechten Ausgangssignalen kommt das linke Ausgangssignal.
+}
+
+\begin{verbatim}
+void pan_tilde_dsp(t_pan_tilde *x, t_signal **sp)
+{
+ dsp_add(pan_tilde_perform, 5, x,
+ sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[0]->s_n);
+}
+\end{verbatim}
+
+\verb+dsp_add+ fügt eine ``Perform''-Routine (erstes Argument) zum DSP-Baum hinzu.
+Das zweite Argument ist die Anzahl der nachfolgenden Zeiger auf diverse Variablen.
+Welche Zeiger auf welche Variablen übergeben werden, unterliegt keiner Beschränkung.
+
+sp[0] bezeichnet hier das erste Eingangssignal, sp[1] das zweite Eingangssignal,
+sp[3] das Ausgangssignal.
+
+Die Struktur \verb+t_signal+ enthält einen Zeiger auf den
+zugehörigen Signalvektor \verb+.s_vec+ (ein Array von Samples \verb+t_sample+),
+sowie die Länge dieses Signalvektors \verb+.s_n+.
+Da innerhalb eines Patches alle Signalvektoren die gleiche Länge haben,
+genügt es, die Länge eines dieser Vektoren abzufragen.
+
+\subsection{perform-Routine}
+Die perform-Routine ist das eigentliche DSP-Herzstück einer Signalklasse.
+
+Ihr wird ein Zeiger auf ein Integer-Array übergeben.
+In diesem Array sind die Zeiger gespeichert, die mit \verb+dsp_add+ übergeben wurden.
+Sie müssen auf ihren ursprünglichen Typ zurückgecastet werden.
+
+Die perform-Routine muß einen Zeiger auf Integer zurückgeben, der hinter den
+Speicherplatz zeigt, in dem die eigenen Zeiger gespeichert sind.
+Dies bedeutet, dass das Rückgabeargument gleich dem Übergabeargument plus der
+Anzahl der eigenen Zeigervariablen (wie sie als zweites Argument in
+\verb+dsp_add+ angegeben wurde) plus eins.
+
+\begin{verbatim}
+t_int *pan_tilde_perform(t_int *w)
+{
+ t_pan_tilde *x = (t_pan_tilde *)(w[1]);
+ t_sample *in1 = (t_sample *)(w[2]);
+ t_sample *in2 = (t_sample *)(w[3]);
+ t_sample *out = (t_sample *)(w[4]);
+ int n = (int)(w[5]);
+
+ t_sample f_pan = (x->f_pan<0)?0.0:(x->f_pan>1)?1.0:x->f_pan;
+
+ while (n--) *out++ = (*in1++)*(1-f_pan)+(*in2++)*f_pan;
+
+ return (w+6);
+}
+\end{verbatim}
+
+In der \verb+while+-Schleife wird jedes Sample der Signalvektoren einzeln
+abgearbeitet.
+
+Eine Optimierungsroutine bei der Erstellung des DSP-Baumes wird darauf geachtet,
+keine unnötigen Kopieroperationen durchzuführen.
+Es kann daher geschehen, dass ein Eingangs- und ein Ausgangssignal an der
+gleichen Stelle im Speicher stehen.
+Es ist daher in solchem Falle darauf zu achten,
+dass nicht in das Ausgangssignal geschrieben wird,
+bevor dort das Eingangssignal ausgelesen wurde.
+
+\subsection{der Code: \tt pan\~\/}
+
+\begin{verbatim}
+#include "m_pd.h"
+
+static t_class *pan_tilde_class;
+
+typedef struct _pan_tilde {
+ t_object x_obj;
+ t_sample f_pan;
+ t_sample f;
+} t_pan_tilde;
+
+t_int *pan_tilde_perform(t_int *w)
+{
+ t_pan_tilde *x = (t_pan_tilde *)(w[1]);
+ t_sample *in1 = (t_sample *)(w[2]);
+ t_sample *in2 = (t_sample *)(w[3]);
+ t_sample *out = (t_sample *)(w[4]);
+ int n = (int)(w[5]);
+ t_sample f_pan = (x->f_pan<0)?0.0:(x->f_pan>1)?1.0:x->f_pan;
+
+ while (n--) *out++ = (*in1++)*(1-f_pan)+(*in2++)*f_pan;
+
+ return (w+6);
+}
+
+void pan_tilde_dsp(t_pan_tilde *x, t_signal **sp)
+{
+ dsp_add(pan_tilde_perform, 5, x,
+ sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[0]->s_n);
+}
+
+void *pan_tilde_new(t_floatarg f)
+{
+ t_pan_tilde *x = (t_pan_tilde *)pd_new(pan_tilde_class);
+
+ x->f_pan = f;
+
+ inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal);
+ floatinlet_new (&x->x_obj, &x->f_pan);
+ outlet_new(&x->x_obj, &s_signal);
+
+ return (void *)x;
+}
+
+void pan_tilde_setup(void) {
+ pan_tilde_class = class_new(gensym("pan~"),
+ (t_newmethod)pan_tilde_new,
+ 0, sizeof(t_pan_tilde),
+ CLASS_DEFAULT,
+ A_DEFFLOAT, 0);
+
+ class_addmethod(pan_tilde_class,
+ (t_method)pan_tilde_dsp, gensym("dsp"), 0);
+ CLASS_MAINSIGNALIN(pan_tilde_class, t_pan_tilde, f);
+}
+\end{verbatim}
+
+
+
+
+\vfill
+\newpage
+\begin{appendix}
+
+\section{das Message-System von \em pd}
+Nicht-Audio-Daten werden über ein Message-System verteilt.
+Jede Message besteht aus einem ``Selector'' und einer Liste von Atomen.
+
+\subsection{Atome}
+
+Es gibt drei Arten von Atomen:
+\begin{itemize}
+\item {\em A\_FLOAT}: ein numerischer Wert (Gleitkommazahl)
+\item {\em A\_SYMBOL}: ein symbolischer Wert (String)
+\item {\em A\_POINTER}: ein Zeiger
+\end{itemize}
+
+Numerische Werte werden immer als Floating-Point-Werte (\verb+double+) dargestellt,
+auch wenn es sich um Ganzzahlwerte handelt.
+
+Jedes Symbol wird aus Performancegründen in einer lookup-Tabelle abgelegt.
+Der Befehl \verb+gensym+ speichert, wenn nötig,
+einen String in dieser Symboltabelle und gibt seine Addresse in der Tabelle zurück.
+
+Atome vom Typ {\em A\_POINTER} haben in der Praxis
+(für einfache Externals) eher untergeordnete Bedeutung.
+
+Der Typ eines Atoms \verb+a+ wird im Strukturelement \verb+a.a_type+ gespeichert.
+
+\subsection{Selectoren}
+
+Der Selector ist ein Symbol und bestimmt, welchen Typ eine Message hat.
+Es gibt fünf vordefinierte Selectoren:
+\begin{itemize}
+\item ``{\tt bang}'' bezeichnet ein Triggerevent.
+Die Message besteht nur aus dem Selector und enthält keine Liste von Atomen.
+\item ``{\tt float}'' bezeichnet einen numerischen Wert. Die Liste enthält nur ein Atom.
+\item ``{\tt symbol}'' bezeichnet einen symbolischen Wert. Die Liste enthält nur ein Atom.
+\item ``{\tt pointer}'' bezeichnet einen Zeiger. Die Liste enthält nur ein Atom.
+\item ``{\tt list}'' bezeichnet eine Liste von mehreren Atomen.
+\end{itemize}
+
+Da die Symbole für diese Selectoren relativ häufig verwendet werden,
+kann man deren Symboltabellen-Adresse auch direkt,
+ohne den Umweg über \verb+gensym+ abfragen:
+
+\begin{tabular}{l||l|l}
+Selector&lookup-Routine&lookup-Addresse\\
+\hline
+\tt bang &\verb+gensym("bang")+ & \verb+&s_bang+ \\
+\tt float &\verb+gensym("float")+ & \verb+&s_float+ \\
+\tt symbol &\verb+gensym("symbol")+ & \verb+&s_symbol+ \\
+\tt pointer &\verb+gensym("pointer")+ & \verb+&s_pointer+ \\
+\tt list &\verb+gensym("list")+ & \verb+&s_list+ \\
+--- (Signal) &\verb+gensym("signal")+&\verb+&s_symbol+
+\end{tabular}
+
+Es können auch andere Selectoren verwendet werden,
+doch muss dann die Empfängerklasse entweder selbst eine Methode
+für diesen Selector zur verfügung stellen,
+oder eine Methode für ``anything'', also jeden beliebigen Selector, anbieten.
+
+Messages die ohne Selector sofort mit einem Zahlenwert beginnen, werden automatisch
+entweder als numerischer Wert (nur ein Atom) oder als Liste (mehrere Atome) erkannt.
+
+Zum Beispiel sind also die Messages ``\verb+12.429+'' und ``\verb+float 12.429+'' ident.
+Ebenfalls ident sind auch die Listen-Messages
+``\verb+list 1 kleines Haus+'' und ``\verb+1 kleines Haus+''.
+
+\section{pd-Typen}
+Da pd auf mehreren Plattformen benutzt wird,
+werden viele gewöhnliche Variablentypen, wie \verb|int|, neu definiert.
+Um portablen Code zu schreiben ist es daher angebracht, die von pd bereitgestellten
+Typen zu verwenden.
+
+Weiters gibt es viele vordefinierte Typen,
+die das Leben des Programmierers vereinfachen sollten.
+pd-Typen beginnen im Allgemeinen mit \verb|t_|.
+
+\begin{tabular}{c|l}
+pd-Type & Beschreibung \\
+\hline\hline
+\verb+t_atom+& Atom \\
+\verb+t_float+ & Gleitkomma-Zahl \\
+\verb+t_symbol+ & Symbol \\
+\verb+t_gpointer+ & Zeiger (auf graphische Objekte) \\
+\hline
+\verb+t_int+ & Ganzzahl \\
+\verb+t_signal+ & Struktur auf ein Signal \\
+\verb+t_sample+ & Audio-Signalwert (Gleitkomma)\\
+\verb+t_outlet+ & Outlet eines Objekts \\
+\verb+t_inlet+ & Inlet eines Objekts \\
+\verb+t_object+ & Objekt-Interna \\
+\hline
+\verb+t_class+ & eine pd-Klasse \\
+\verb+t_method+ & Zeiger auf Klassenmethode \\
+\verb+t_newmethod+ & Zeiger auf Klasseninstanziierungsmethode (new-Routine) \\
+\end{tabular}
+
+
+\section{Wichtige Funktionen aus ``m\_pd.h''}
+\subsection{Funktionen: Atome}
+
+\subsubsection{SETFLOAT}
+\begin{verbatim}
+SETFLOAT(atom, f)
+\end{verbatim}
+Dieses Makro setzt den Typ von \verb+atom+ auf \verb+A_FLOAT+
+und setzt den numerischen Wert dieses Atoms auf \verb+f+.
+
+\subsubsection{SETSYMBOL}
+\begin{verbatim}
+SETSYMBOL(atom, s)
+\end{verbatim}
+Dieses Makro setzt den Typ von \verb+atom+ auf \verb+A_SYMBOL+
+und setzt den symbolischen Wert dieses Atoms auf \verb+s+.
+
+\subsubsection{SETPOINTER}
+\begin{verbatim}
+SETPOINTER(atom, pt)
+\end{verbatim}
+Dieses Makro setzt den Typ von \verb+atom+ auf \verb+A_POINTER+
+und setzt den Zeiger-Wert dieses Atoms auf \verb+pt+.
+
+\subsubsection{atom\_getfloat}
+\begin{verbatim}
+t_float atom_getfloat(t_atom *a);
+\end{verbatim}
+Wenn der Typ des Atoms \verb+a+ \verb+A_FLOAT+ ist, wird dessen numerischer Wert,
+ansonsten ``0.0'' zurückgegeben.
+
+\subsubsection{atom\_getfloatarg}
+\begin{verbatim}
+t_float atom_getfloatarg(int which, int argc, t_atom *argv)
+\end{verbatim}
+Wenn das Atom,
+das in der Atomliste \verb+argv+ mit der Länge \verb+argc+ an der Stelle \verb+which+
+zu finden ist,
+vom Typ \verb+A_FLOAT+ ist, wird dessen numerischer Wert,
+ansonsten ``0.0'' zurückgegeben.
+
+\subsubsection{atom\_getint}
+\begin{verbatim}
+t_int atom_getint(t_atom *a);
+\end{verbatim}
+Wenn der Typ des Atoms \verb+a+ \verb+A_FLOAT+ ist, wird dessen numerischer
+Wert als Ganzzahlwert, ansonsten ``0'' zurückgegeben.
+
+\subsubsection{atom\_getsymbol}
+\begin{verbatim}
+t_symbol atom_getsymbol(t_atom *a);
+\end{verbatim}
+Wenn der Typ des Atoms \verb+a+ \verb+A_SYMBOL+ ist, wird ein Zeiger
+auf dessen Symbol ansonsten auf das Symbol ``float'' zurückgegeben.
+
+\subsubsection{atom\_gensym}
+\begin{verbatim}
+t_symbol *atom_gensym(t_atom *a);
+\end{verbatim}
+Wenn der Typ des Atoms \verb+a+ \verb+A_SYMBOL+ ist, wird ein Zeiger
+auf dessen Symbol zurückgegeben.
+
+Atome anderen Typs werden zuerst ``sinnvoll'' in Strings umgewandelt.
+Diese Strings werden, falls nötig, in die Symbol-Tabelle eingetragen.
+Die Zeiger auf das Symbol wird zurückgegeben.
+
+
+\subsubsection{atom\_string}
+\begin{verbatim}
+void atom_string(t_atom *a, char *buf, unsigned int bufsize);
+\end{verbatim}
+Konvertiert ein Atom \verb+a+ in einen {\tt C}-String \verb+buf+.
+Der char-Buffer muss selbst reserviert und seine Länge in \verb+bufsize+ angegeben werden.
+
+\subsubsection{gensym}
+\begin{verbatim}
+t_symbol *gensym(char *s);
+\end{verbatim}
+Prüft, ob für den C-String \verb+*s+ bereits ein Eintrag in der Symbol-lookup-Tabelle
+vorhanden ist.
+Ist noch kein Eintrag vorhanden, so wird einer angelegt.
+Ein Zeiger auf das Symbol in der Tabelle wird zurückgegeben.
+
+
+\subsection{Funktionen: Klassen}
+\subsubsection{class\_new}
+\begin{verbatim}
+t_class *class_new(t_symbol *name,
+ t_newmethod newmethod, t_method freemethod,
+ size_t size, int flags,
+ t_atomtype arg1, ...);
+\end{verbatim}
+Generiert eine neue Klasse mit dem symbolischen Namen \verb+name+.
+
+\verb+newmethod+ ist eine Konstruktorfunktion,
+die eine Instanz der Klasse konstruiert und einen Zeiger auf diese Instanz zurückgibt.
+
+Wird manuell dynamischer Speicher reserviert,
+so muss dieser bei Zerstörung eines Objektes
+mit der Destruktormethode \verb+freemethod+ (kein Rückgabeargument)
+wieder freigegeben werden.
+
+\verb+size+ ist statische die Größe des Klassendatenraumes,
+die mit der Funktion \verb+sizeof(t_mydata)+ berechnet werden kann.
+
+\verb+flags+ bestimmen das Aussehen des graphischen Objektes.
+Eine beliebige Kombination folgender Flags ist möglich:
+
+\begin{tabular}{l|l}
+Flag&Bedeutung\\
+\hline
+\verb+CLASS_DEFAULT+ &Ein normales Objekt mit einem Inlet \\
+\verb+CLASS_PD+ & \em Objekte ohne Graphikdarstellung\\
+\verb+CLASS_GOBJ+ & \em reine Graphikobjekte (wie Arrays, Graphen,...)\\
+\verb+CLASS_PATCHABLE+ & \em normales Objekt (mit einem Inlet) \\
+\verb+CLASS_NOINLET+ & Der standardmäßige Inlet wird unterdrückt \\
+\end{tabular}
+
+Flags, deren Bedeutung {\em kursiv} gedruckt ist,
+haben geringe Bedeutung beim Schreiben von Externals.
+
+Die restlichen Argumente \verb+arg1,...+ definieren
+die Typen die Übergabeargumente bei der Objektkreation.
+Höchstens sechs typgeprüfte Argumente können einem Objekt übergeben werden.
+Die Argumententypeliste wird ``0'' terminiert.
+
+Mögliche Argumententypen sind:
+
+\begin{tabular}{l|l}
+\verb+A_DEFFLOAT+ & ein numerischer Wert \\
+\verb+A_DEFSYMBOL+ & ein symbolischer Wert \\
+\verb+A_GIMME+ & eine Atomliste beliebiger Länge und Typen \\
+\end{tabular}
+
+Sollten mehr als sechs Argumente übergeben werden, muss man
+\verb+A_GIMME+ verwenden und eine händische Typprüfung durchführen.
+
+\subsubsection{class\_addmethod}
+\begin{verbatim}
+void class_addmethod(t_class *c, t_method fn, t_symbol *sel,
+ t_atomtype arg1, ...);
+\end{verbatim}
+Fügt der Klasse, auf die \verb+c+ zeigt, die Methode \verb+fn+ für
+eine Message mit dem Selector \verb+sel+ hinzu.
+
+Die restlichen Argumente \verb+arg1,...+ definieren
+die Typen der Atomliste die dem Selector folgt.
+Höchstens sechs typgeprüfte Argumente angegeben werden.
+Sollten mehr als sechs Argumente übergeben werden, muss man
+\verb+A_GIMME+ verwenden und eine händische Typprüfung durchführen.
+
+Die Argumententypeliste wird ``0'' terminiert.
+
+Mögliche Argumententypen sind:
+
+\begin{tabular}{l|l}
+\verb+A_DEFFLOAT+ & ein numerischer Wert \\
+\verb+A_DEFSYMBOL+ & ein symbolischer Wert \\
+\verb+A_POINTER+ & eine Zeiger \\
+\verb+A_GIMME+ & eine Atomliste beliebiger Länge und Typen \\
+\end{tabular}
+
+\subsubsection{class\_addbang}
+\begin{verbatim}
+void class_addbang(t_class *c, t_method fn);
+\end{verbatim}
+Fügt der Klasse, auf die \verb+c+ zeigt, die Methode \verb+fn+
+für eine ``bang''-Message hinzu.
+Die ``bang''-Methode hat als Übergabeargument einen Zeiger auf den Klassendatenraum:
+
+\verb+void my_bang_method(t_mydata *x);+
+
+\subsubsection{class\_addfloat}
+\begin{verbatim}
+void class_addfloat(t_class *c, t_method fn);
+\end{verbatim}
+Fügt der Klasse, auf die \verb+c+ zeigt, die Methode \verb+fn+
+für eine ``float''-Message hinzu.
+Die ``float''-Methode hat als Übergabeargument einen Zeiger auf den Klassendatenraum und
+ein Gleitkommaargument:
+
+\verb+void my_float_method(t_mydata *x, t_floatarg f);+
+
+\subsubsection{class\_addsymbol}
+\begin{verbatim}
+void class_addsymbol(t_class *c, t_method fn);
+\end{verbatim}
+Fügt der Klasse, auf die \verb+c+ zeigt, die Methode \verb+fn+
+für eine ``symbol''-Message hinzu.
+Die ``symbol''-Methode hat als Übergabeargument einen Zeiger auf den Klassendatenraum und
+einen Zeiger auf das übergebene Symbol:
+
+\verb+void my_symbol_method(t_mydata *x, t_symbol *s);+
+
+\subsubsection{class\_addpointer}
+\begin{verbatim}
+void class_addpointer(t_class *c, t_method fn);
+\end{verbatim}
+Fügt der Klasse, auf die \verb+c+ zeigt, die Methode \verb+fn+
+für eine ``pointer''-Message hinzu.
+Die ``pointer''-Methode hat als Übergabeargument einen Zeiger
+auf den Klassendatenraum und einen Zeiger auf einen Pointer:
+
+\verb+void my_pointer_method(t_mydata *x, t_gpointer *pt);+
+
+\subsubsection{class\_addlist}
+\begin{verbatim}
+void class_addlist(t_class *c, t_method fn);
+\end{verbatim}
+Fügt der Klasse, auf die \verb+c+ zeigt, die Methode \verb+fn+
+für eine ``list''-Message hinzu.
+Die ``list''-Methode hat als Übergabeargument neben einem Zeiger
+auf den Klassendatenraum einen Zeiger auf das Selectorsymbol
+(immer \verb+&s_list+),
+die Anzahl der Atome in der Liste sowie einen Zeiger auf die Atomliste:
+
+\verb+void my_list_method(t_mydata *x,+
+
+\verb+ t_symbol *s, int argc, t_atom *argv);+
+
+
+%\begin{verbatim}
+%void my_list_method(t_mydata *x,
+% t_symbol *s, int argc, t_atom *argv);
+%\end{verbatim}
+
+
+
+\subsubsection{class\_addanything}
+\begin{verbatim}
+void class_addanything(t_class *c, t_method fn);
+\end{verbatim}
+Fügt der Klasse, auf die \verb+c+ zeigt, die Methode \verb+fn+
+für eine beliebige Message hinzu.
+Die anything-Methode hat als Übergabeargument neben einem Zeiger
+auf den Klassendatenraum einen Zeiger auf das Selectorsymbol,
+die Anzahl der Atome in der Liste sowie einen Zeiger auf die Atomliste:
+
+
+\verb+void my_any_method(t_mydata *x,+
+
+\verb+ t_symbol *s, int argc, t_atom *argv);+
+
+
+%\begin{verbatim}
+%void my_any_method(t_mydata *x,
+% t_symbol *s, int argc, t_atom *argv);
+%\end{verbatim}
+
+\subsubsection{class\_addcreator}
+\begin{verbatim}
+ void class_addcreator(t_newmethod newmethod, t_symbol *s,
+ t_atomtype type1, ...);
+\end{verbatim}
+Fügt zu einem Konstruktor \verb+newmethod+ ein zum Klassennamen alternatives
+Kreatorsymbol \verb+s+ hinzu.
+Dadurch können Objekte mit dem richtigen Klassennamen und einem Aliasnamen
+(zum Beispiel eine Abkürzung, wie das Internal ``float'' bzw. ``f'') kreiert werden.
+
+Die ``0''-terminierte Typenliste entspricht der von \verb+class_new+.
+
+\subsubsection{class\_sethelpsymbol}
+\begin{verbatim}
+void class_sethelpsymbol(t_class *c, t_symbol *s);
+\end{verbatim}
+
+Clickt man mit der rechten Maustaste auf ein pd-Objekt,
+so kann man sich einen Hilfe-Patch für die zugehörige Objektklasse anzeigen lasse.
+Standardmäßig wird ist dies ein Patch mit dem symbolischen Klassennamen
+im Verzeichnis ``{\em doc/5.reference/}'' gesucht.
+
+Für die Klasse, auf die \verb+c+ zeigt, wird der Name des Hilfepatches auf den
+symbolischen Wert \verb+s+ geändert.
+
+Dadurch können sich mehrere verwandte Klassen einen Hilfepatch teilen.
+
+Pfadangaben erfolgen relativ zum Standardhilfepfad {\em doc/5.reference/}.
+
+\subsubsection{pd\_new}
+\begin{verbatim}
+t_pd *pd_new(t_class *cls);
+\end{verbatim}
+Generiert eine neue Instanz der Klasse \verb+cls+ und gibt einen Zeiger auf diese
+Instanz zurück.
+
+\subsection{Funktionen: In- und Outlets}
+Alle Inlet- und Outletroutinen benötigen eine Referenz auf die Objektinterna
+der Klasseninstanz.
+Die notwendige Variable vom Typ \verb+t_object+ im Datenraum wird bei der
+Objektinstanziierung initialisiert.
+Diese Variable muß als \verb+owner+-Objekt den Inlet- und Outletroutinen übergeben werden.
+
+\subsubsection{inlet\_new}
+\begin{verbatim}
+t_inlet *inlet_new(t_object *owner, t_pd *dest,
+ t_symbol *s1, t_symbol *s2);
+\end{verbatim}
+Generiert einen zusätzlichen ``aktiven'' Inlet des Objektes, auf das \verb+owner+ zeigt.
+\verb+dest+ zeigt im Allgemeinen auf ``\verb+owner.ob_pd+''.
+
+Der Selector \verb+s1+ am neuen Inlet, wird durch den Selector \verb+s2+ substituiert.
+
+Tritt also eine Message mit dem Selector \verb+s1+ am neuen Inlet auf,
+wird die Klassenmethode für den Selector \verb+s2+ ausgeführt.
+
+Dies bedeutet
+\begin{itemize}
+\item Der substituierende Selector muss mit \verb+class_addmethod+ angegeben werden.
+\item Man kann einen bestimmten rechten Eingang simulieren,
+indem man dem ersten Eingang eine Message mit dem Selector dieses Eingangs schickt.
+
+Verwendet man ein leeres Symbol (\verb+gensym("")+) als Selector,
+so erreicht man, dass der rechte Eingang nicht über den ersten angesprochen werden kann.
+\item Es ist nicht möglich, einem rechten Eingang Methoden für mehr als einen Selector
+zuzuweisen. Insbesondere ist es nicht möglich, ihm eine allgemeine Methode
+für einen beliebigen Selector zuzuweisen.
+\end{itemize}
+
+\subsubsection{floatinlet\_new}
+\begin{verbatim}
+t_inlet *floatinlet_new(t_object *owner, t_float *fp);
+\end{verbatim}
+Schafft einen neuen ``passiven'' Eingang für das Objekt, auf das \verb+owner+ zeigt,
+der es erlaubt, einen numerischen Wert von außen direkt auf einen
+Speicherplatz \verb+fp+ zu schreiben, ohne eine eigene Methode aufzurufen.
+
+\subsubsection{symbolinlet\_new}
+\begin{verbatim}
+t_inlet *symbolinlet_new(t_object *owner, t_symbol **sp);
+\end{verbatim}
+Schafft einen neuen ``passiven'' Eingang für das Objekt, auf das \verb+owner+ zeigt,
+der es erlaubt, einen symbolischen Wert von außen direkt auf einen
+Speicherplatz \verb+sp+ zu schreiben, ohne eine eigene Methode aufzurufen.
+
+\subsubsection{pointerinlet\_new}
+\begin{verbatim}
+t_inlet *pointerinlet_new(t_object *owner, t_gpointer *gp);
+\end{verbatim}
+Schafft einen neuen ``passiven'' Eingang für das Objekt, auf das \verb+owner+ zeigt,
+der es erlaubt, einen Zeigerwert von außen direkt auf einen
+Speicherplatz \verb+gp+ zu schreiben, ohne eine eigene Methode aufzurufen.
+
+\subsubsection{outlet\_new}
+\begin{verbatim}
+t_outlet *outlet_new(t_object *owner, t_symbol *s);
+\end{verbatim}
+Generiert einen neuen Ausgang für das Objekt, auf das \verb+owner+ zeigt.
+Das Symbol, auf das \verb+s+ zeigt, zeigt den Typ des Ausgangs an.
+
+\begin{tabular}{c|l||l}
+Symbolwert & Symboladresse & Outlet-Typus \\
+\hline\hline
+``bang'' & \verb+&s_bang+ & Message (Bang)\\
+``float'' & \verb+&s_float+ & Message (Float)\\
+``symbol'' & \verb+&s_symbol+ & Message (Symbol) \\
+``pointer'' & \verb+&s_gpointer+ & Message (List)\\
+``list'' & \verb+&s_list+ & Message \\
+--- & 0 & Message \\
+\hline
+``signal'' & \verb+&s_signal+ & Signal \\
+\end{tabular}
+
+Zwischen den verschiedenen Message-Outlet-Typen gibt es keinen Unterschied.
+Allerdings macht es den Code leichter lesbar,
+wenn schon bei der Outlet-Generierung angezeigt wird, wozu der Ausgang verwendet wird.
+Für allgemeine Message-Outlets verwendet man einen ``0''-Pointer.
+
+Variablen vom Typ \verb+t_object+ stellen einen Zeiger auf einen Outlet zur Verfügung.
+Bei der Generierung eines neuen Outlets,
+wird seine Addresse in der Objektvariablen \verb+(*owner).ob_outlet+ gespeichert.
+
+Werden mehrere Message-Ausgänge benötigt, müssen die Outletzeiger,
+die von \verb+outlet_new+ zurückgegeben werden, manuell im Datenraum gespeichert werden,
+um die jeweiligen Ausgänge ansprechen zu können.
+
+\subsubsection{outlet\_bang}
+\begin{verbatim}
+void outlet_bang(t_outlet *x);
+\end{verbatim}
+Gibt am Outlet, auf den \verb+x+ zeigt, eine ``bang''-Message aus.
+
+\subsubsection{outlet\_float}
+\begin{verbatim}
+void outlet_float(t_outlet *x, t_float f);
+\end{verbatim}
+Gibt am Outlet, auf den \verb+x+ zeigt, eine ``float''-Message mit dem
+numerischen Wert \verb+f+ aus.
+
+\subsubsection{outlet\_symbol}
+\begin{verbatim}
+void outlet_symbol(t_outlet *x, t_symbol *s);
+\end{verbatim}
+Gibt am Outlet, auf den \verb+x+ zeigt, eine ``symbol''-Message mit dem
+symbolischen Wert von \verb+s+ aus.
+
+\subsubsection{outlet\_pointer}
+\begin{verbatim}
+void outlet_pointer(t_outlet *x, t_gpointer *gp);
+\end{verbatim}
+Gibt am Outlet, auf den \verb+x+ zeigt, eine ``pointer''-Message mit dem
+Zeiger \verb+gp+ aus.
+
+\subsubsection{outlet\_list}
+\begin{verbatim}
+void outlet_list(t_outlet *x,
+ t_symbol *s, int argc, t_atom *argv);
+\end{verbatim}
+Gibt am Outlet, auf den \verb+x+ zeigt, eine ``list''-Message mit
+\verb+argc+ Atomen aus.
+\verb+argv+ zeigt auf das erste Atom der Liste.
+
+Unabhängig davon, auf welches Symbol \verb+s+ zeigt, wird der Selector
+``list'' der Liste vorangestellt.
+
+Aus Lesbarkeitsgründen sollte man aber trotzdem einen Zeiger auf das
+Symbol ``list'' (\verb+gensym("list")+ oder \verb+&s_list+) angeben.
+
+\subsubsection{outlet\_anything}
+\begin{verbatim}
+void outlet_anything(t_outlet *x,
+ t_symbol *s, int argc, t_atom *argv);
+\end{verbatim}
+Gibt am Outlet, auf den \verb+x+ zeigt, eine Message mit
+dem Selector, auf den \verb+s+ zeigt, aus.
+Dem Selector folgen \verb+argc+ Atome.
+\verb+argv+ zeigt auf das erste Atom dieser Liste.
+
+
+\subsection{Funktionen: DSP}
+Soll eine Klasse Methoden zur digitalen Signalsverarbeitung zur Verfügung stellen,
+so muss ihr eine Methode für den Selector ``dsp'' hinzugefügt werden.
+
+Wird die Audio-Engine gestartet, so werden alle Objekte, die eine ``dsp''-Methode
+zur Verfügung stellen, als Instanzen von Signalklassen identifiziert.
+
+\paragraph{DSP-Methode}
+
+\begin{verbatim}
+void my_dsp_method(t_mydata *x, t_signal **sp)
+\end{verbatim}
+
+In der ``dsp''-Methode wird mit der Funktion \verb+dsp_add+ die
+Klassenroutine für Signalverarbeitung in den DSP-Baum eingebunden.
+
+Neben dem eigenen Datenraum \verb+x+, wird auch ein Array von Signalen übergeben.
+Die Signale im Array sind so angeordnet, dass sie am graphischen Objekt
+im Uhrzeigersinn gelesen werden.
+
+Sofern je zwei Ein- und Ausgangssignale vorhanden sind, gilt also:
+
+\begin{tabular}{c|r}
+Zeiger & auf Signal \\
+\hline\hline
+sp[0] & linkes Eingangssignal \\
+sp[1] & rechtes Eingangssignal \\
+sp[2] & rechtes Ausgangssignal \\
+sp[3] & linkes Ausgangssignal \\
+\end{tabular}
+
+Die Signalstruktur enthält unter anderem:
+
+\begin{tabular}{c|l}
+Strukturelement & Bedeutung \\
+\hline
+\verb+s_n+ & Länge des Signalvektors \\
+\verb+s_vec+ & Zeiger auf den Signalvektor \\
+\end{tabular}
+
+Der Signalvektor ist ein Array auf Samples vom Typ \verb+t_sample+.
+
+\paragraph{Perform-Routine}
+\begin{verbatim}
+t_int *my_perform_routine(t_int *w)
+\end{verbatim}
+
+Der Perform-Routine die mit \verb+class_add+ in den DSP-Baum eingefügt wurde,
+wird ein Zeiger \verb+w+ auf ein (Integer-)Array übergeben.
+In diesem Array sind die Zeiger gespeichert, die mit \verb+dsp_add+ übergeben wurden.
+Sie müssen auf ihren ursprünglichen Typ zurückgecastet werden.
+Der erste Zeiger ist an der Stelle \verb+w[1]+ gespeichert !!!
+
+Die perform-Routine muß einen Zeiger auf Integer zurückgeben, der hinter den
+Speicherplatz zeigt, in dem die eigenen Zeiger gespeichert sind.
+Dies bedeutet, dass das Rückgabeargument gleich dem Übergabeargument plus der
+Anzahl der eigenen Zeigervariablen (wie sie als zweites Argument in
+\verb+dsp_add+ angegeben wurde) plus eins.
+
+
+
+
+\subsubsection{CLASS\_MAINSIGNALIN}
+\begin{verbatim}
+CLASS_MAINSIGNALIN(<class_name>, <class_data>, <f>);
+\end{verbatim}
+Das Makro \verb+CLASS_MAINSIGNALIN+ meldet an, dass die Klasse
+Signal-Inlets brauchts.
+
+Das erste Argument des Makros ist ein Zeiger auf die Signalklasse.
+Das zweite Argument ist der Typ des Datenraums der Klasse.
+Das dritte Argument ist eine (Dummy-)Gleitkomma-Variable aus dem Datenraum,
+die gebraucht wird, um bei nicht vorhandenen Signalen am Signalinlet,
+``float''-Messages wie Signale behandeln zu können.
+
+An so kreierten Signaleingängen können daher keine zusätzlichen ``float''-Messages
+geschickt werden.
+
+\subsubsection{dsp\_add}
+\begin{verbatim}
+void dsp_add(t_perfroutine f, int n, ...);
+\end{verbatim}
+Fügt dem DSP-Baum eine Perform-Routine \verb+f+ hinzu,
+die jeden DSP-Zyklus neu aufgerufen wird.
+
+Das zweite Argument \verb+n+ legt die Anzahl der nachfolgenden Zeigerargumente fest.
+
+Welche Zeiger auf welche Variablen übergeben werden, unterliegt keiner Beschränkung.
+Sinnvoll sind im Allgemeinen Zeiger auf den Datenraum und auf die Signalvektoren.
+Auch die Länge der Signalvektoren sollte übergeben werden,
+um effektiv Signale manipulieren zu können.
+
+\subsubsection{sys\_getsr}
+\begin{verbatim}
+float sys_getsr(void);
+\end{verbatim}
+Gibt die Abtastrate des Systems zurück.
+
+\subsection{Funktion: Memory}
+\subsubsection{getbytes}
+\begin{verbatim}
+void *getbytes(size_t nbytes);
+\end{verbatim}
+Reserviert \verb+nbytes+ Bytes und gibt einen Zeiger auf den reservierten Speicher zurück.
+
+\subsubsection{copybytes}
+\begin{verbatim}
+void *copybytes(void *src, size_t nbytes);
+\end{verbatim}
+Kopiert \verb+nbytes+ Bytes von \verb+*src+ in einen neu alloziierten Speicher.
+Die Addresse dieses Speichers wird zurückgegeben.
+
+\subsubsection{freebytes}
+\begin{verbatim}
+void freebytes(void *x, size_t nbytes);
+\end{verbatim}
+Gibt \verb+nbytes+ Bytes an der Addresse \verb+*x+ frei.
+
+\subsection{Funktionen: Ausgabe}
+\subsubsection{post}
+\begin{verbatim}
+void post(char *fmt, ...);
+\end{verbatim}
+
+Schreibt einen {\tt C}-String auf den Standarderror (Shell).
+
+\subsubsection{error}
+\begin{verbatim}
+void error(char *fmt, ...);
+\end{verbatim}
+
+Schreibt einen {\tt C}-String als Fehlermeldung auf den Standarderror (Shell).
+Das Objekt, das die Fehlermeldung ausgegeben hat, wird markiert und
+ist über das pd-Menü {\em Find->Find last error} identifizierbar.
+
+\end{appendix}
+
+\end{document}
+
diff --git a/doc/tutorials/externals-howto/HOWTO-externals-en.tex b/doc/tutorials/externals-howto/HOWTO-externals-en.tex
new file mode 100644
index 00000000..8c77d3c6
--- /dev/null
+++ b/doc/tutorials/externals-howto/HOWTO-externals-en.tex
@@ -0,0 +1,1750 @@
+% format latexg -*- latex -*-
+
+\documentclass[12pt, a4paper,austrian, titlepage]{article}
+
+%% HOWTO write an external for pd
+%% by IOhannes m zmölnig, 2001
+%%
+%% this document is released under the following license
+%% CreativeCommons Attribution-ShareAlike 2.5
+%%
+%% http://creativecommons.org/licenses/by-sa/2.5/
+
+\usepackage[latin1]{inputenc}
+\usepackage[T1]{fontenc}
+\usepackage{babel}
+
+\title{
+HOWTO \\
+write an External \\
+for {\em puredata}
+}
+
+\author{
+johannes m zmölnig \\
+\\
+{\em institut for electronic music and acoustics\footnote{http://iem.at}}
+}
+
+\date{}
+
+\begin{document}
+\maketitle
+
+\hyphenation{Echt-zeit}
+\hyphenation{Computer-musik-program-men}
+\hyphenation{Echt-zeit-Computer-musik-pro-gramm}
+
+\begin{abstract}
+pd is a graphical realtime-computermusicsystem that follows the tradition of
+IRCAMs {\em ISPW-max}.
+
+Although plenty of functions are built into pd,
+it is sometimes a pain or simply impossible to create a patch with a certain
+functionality out of the given primitives and combinations of these.
+
+Therefore, pd can be extended with selfmade primitives (``objects'')
+that are written in complex programming-languages, like {\tt C/C++}.
+
+This document aims to explain, how to write such primitives in {\tt C},
+the popular language that was used to realize pd.
+\end{abstract}
+
+
+\vfill
+\newpage
+
+\tableofcontents
+
+\vfill
+\newpage
+
+\section{definitions and prerequisites}
+pd refers to the graphical realtime-computermusicprogramme {\em puredata}
+by Miller~S.~Puckette.
+
+To fully understand this document, it is necessary to
+be acquainted with pd and to
+have a general understanding of programming techniques especially in {\tt C}.
+
+To write externals yourself, a {\tt C}-compiler that supports the
+{\tt ANSI-C}-Standard, like the {\em Gnu C-compiler} (gcc) on linux-systems or
+{\em Visual-C++ 6.0} (vc6) on windos-plattforms, will be necessary.
+
+\subsection{classes, instances, objects}
+pd is written in the programming-language {\tt C}.
+Due to its graphical nature, pd ist a {\em object-oriented} system.
+Unfortunately {\tt C} does not support very well the use of classes.
+Thus the resulting source-code is not as elegant as {\tt C++}-code would be, for instance.
+
+In this document, the expression {\em class} refers to the realisation of a concept
+combining data and manipulators on this data.
+
+Concrete {\em instances of a class} are called {\em objects}.
+
+\subsection{internals, externals und libraries}
+
+To avoid confusion of ideas, the expressions {\em internal}, {\em external} and
+{\em library} should be explained here.
+
+\paragraph{Internal}
+An {\em internal} is a class that is built into pd.
+Plenty of primitives, such as ``+'', ``pack'' or ``sig\~\/'' are {\em internals}.
+
+\paragraph{External}
+An {\em external} is a class that is not built into pd but is loaded at runtime.
+Once loaded into pd's memory, {\em externals} cannot be distinguished from
+{\em internals} any more.
+
+\paragraph{Library}
+A {\em library} is a collection of {\em externals} that are compiled into a
+single binary-file.
+
+{\em Library}-files have to follow a systemdependent naming convention:
+
+\begin{tabular}{c||c|c|c}
+library & linux&irix&Win32 \\
+\hline
+{\tt my\_lib}&{\tt my\_lib.pd\_linux}&{\tt my\_lib.pd\_irix}&
+{\tt my\_lib.dll}\\
+\end{tabular}
+
+The simplest form of a {\em library} includes exactly one {\em external}
+bearing the same name as the {\em library}.
+
+Unlike {\em externals}, {\em libraries} can be imported by pd with special operations.
+After a {\em library} has been imported,
+all included {\em externals} have been loaded into memory and are available as objects.
+
+pd supports to modes to import {\em libraries}:
+
+\begin{itemize}
+\item via the commandline-option ``{\tt -lib my\_lib}''
+\item by creating an object ``{\tt my\_lib}''
+\end{itemize}
+
+The first method loads a {\em library} when pd is started.
+This method is preferably used for {\em libraries} that contain several {\em externals}.
+
+The other method should be used for {\em libraries} that contain exactly
+one {\em external} bearing the same name.
+pd checks first, whether a class named ``my\_lib'' is already loaded.
+If this is not the case\footnote{
+If a class ``my\_lib'' is already existent, an object ``my\_lib'' will be instantiated
+and the procedure is done.
+Thus, no {\em library} has been loaded.
+Therefore no {\em library} that is named like an already used class-name like, say, ``abs'',
+can be loaded.}, all paths are searched for a file called
+``{\tt my\_lib.pd\_linux}''\footnote{or another system-dependent filename-extensions (s.a.)}.
+If such file is found, all included {\em externals} are loaded into memory by calling a
+routine \verb+my_lib_setup()+.
+After loading, a class ``my\_lib'' is (again) looked for as a (newly loaded) {\em external}.
+If so, an instance of this class is created, else the instantiation fails and an error is
+printed.
+Anyhow, all {\em external}-classes declared in the {\em library} are loaded by now.
+
+
+\section{my first external: {\tt helloworld}}
+Usually the first attempt learning a programming-language is a ``hello world''-application.
+
+In our case, an objectclass should be created, that prints the line ``hello world!!'' to
+the standarderror everytime it is triggered witha ``bang''-message.
+
+
+
+\subsection{the interface to pd}
+To write a pd-external a well-defined interface is needed.
+This is provided in the header-file ``m\_pd.h''.
+
+\begin{verbatim}
+#include "m_pd.h"
+\end{verbatim}
+
+\subsection{a class and its dataspace}
+First a new class has to be prepared and the dataspace for this class has to be defined.
+
+\begin{verbatim}
+static t_class *helloworld_class;
+
+typedef struct _helloworld {
+ t_object x_obj;
+} t_helloworld;
+\end{verbatim}
+
+\verb+hello_worldclass+ is going to be a pointer to the new class.
+
+The structure \verb+t_helloworld+ (of the type \verb+_helloworld+) is
+the dataspace of the class.
+
+An absolutely necessary element of the dataspace is a variable of the type
+\verb+t_object+, which is used to store internal object-properties like
+the graphical presentation of the object or data about inlets and outlets.
+
+\verb+t_object+ has to be the first entry in the structure !
+
+Because a simple ``hello world''-application needs no variables,
+the structure is empty apart from the \verb+t_object+.
+
+
+\subsection{methodspace}
+Apart from the dataspace, a class needs a set of manipulators (methods) to
+manipulate the data with.
+
+If a message is sent to an instance of our class, a method is called.
+These methods are the interfaces to the messagesystem of pd.
+On principal they have no return argument and are therefore are of the
+type \verb+void+.
+
+\begin{verbatim}
+void helloworld_bang(t_helloworld *x)
+{
+ post("Hello world !!");
+}
+\end{verbatim}
+
+
+This method has an argument of the type \verb+t_helloworld+,
+which would enable us to manipulate the dataspace.
+
+Since we only want to output ``Hello world!''
+(and, by the way, our dataspace is quite sparse),
+we renounce a manipulation.
+
+The command \verb+post(char *c,...)+ sends a string to the standarderror.
+A carriage return is added automatically.
+Apart from this, the \verb+post+-command works like the {\tt C}-command \verb+printf()+.
+
+\subsection{generation of a new class}
+To generate a new class, information of the dataspace and the methodspace of this class,
+have to be passed to pd when a library is loaded.
+
+On loading a new library ``my\_lib'',
+pd tries to call a function ``my\_lib\_setup()''.
+This function (or functions called by it)
+declares the new classes and their properties.
+It is only called once, when the library is loaded.
+If the function-call fails (e.g., because no functionn of the specified name is present)
+no external of the library will be loaded.
+
+\begin{verbatim}
+void helloworld_setup(void)
+{
+ helloworld_class = class_new(gensym("helloworld"),
+ (t_newmethod)helloworld_new,
+ 0, sizeof(t_helloworld),
+ CLASS_DEFAULT, 0);
+
+ class_addbang(helloworld_class, helloworld_bang);
+}
+\end{verbatim}
+
+\paragraph{class\_new}
+
+The function \verb+class_new+ creates a new class and returns a pointer to this prototype.
+
+The first argument is the symbolic name of the class.
+
+Das erste Argument ist der symbolische Name der Klasse.
+
+The next two arguments define the constructor and dstructor of the class.
+
+Whenever a classobject is created in a pd-patch,
+the class-constructor \verb+(t_newmethod)helloworld_new+ instantiates the object
+and initializes the dataspace.
+
+Whenever an object is destroyed
+(either by closing the containing patch or by deleting the object from the patch)
+the destructor frees the dynamically reserved memory.
+The allocated memory for the static dataspace is automatically reserved and freed.
+
+Therefore we do not have to provide a destructor in this example, the argument
+is set to ``0''.
+
+To enable pd to reserve and free enough memory for the static dataspace,
+the size of the datastructure has to be passed as the fourth argument.
+
+The fifth argument has influence on the graphical representaion of the classobjects.
+The default-value is \verb+CLASS_DEFAULT+ or simply ``0''.
+
+The remaining arguments define the arguments of an object and its type.
+
+Up to six numeric and symbolic object-arguments can be defined via
+\verb+A_DEFFLOAT+ and \verb+A_DEFSYMBOL+.
+If more arguments are to be passed to the object
+or if the order of atomtypes should by more flexible,
+\verb+A_GIMME+ can be used for passing an arbitrary list of atoms.
+
+The list of object-arguments is terminated by ``0''.
+In this example we have no object-arguments at all for the class.
+
+\paragraph{class\_addbang}
+We still have to add a methodspace to the class.
+
+\verb+class_addbang+ adds a method for a ``bang''-message to the class that is
+defined in the first argument.
+The added method is defined in the second argument.
+
+
+\subsection{constructor: instantiation of an object}
+Each time, an object is created in a pd-patch, the
+constructor that is defined with the \verb+class_new+-command,
+generates a new instance of the class.
+
+The constructor has to be of type \verb+void *+.
+
+\begin{verbatim}
+void *helloworld_new(void)
+{
+ t_helloworld *x = (t_helloworld *)pd_new(helloworld_class);
+
+ return (void *)x;
+}
+\end{verbatim}
+
+
+The arguments of the constructor-method depend on the object-arguments
+defined with \verb+class_new+.
+
+\begin{tabular}{l|l}
+\verb+class_new+-argument&constructor-argument\\
+\hline
+\verb+A_DEFFLOAT+&\verb+t_floatarg f+ \\
+\verb+A_DEFSYMBOL+&\verb+t_symbol *s+ \\
+\verb+A_GIMME+&\verb+t_symbol *s, int argc, t_atom *argv+
+\end{tabular}
+
+Because there are no object-arguments for our ``hello world''-class,
+the constructor has anon too.
+
+The function \verb+pd_new+ reserves memory for the dataspace,
+initializes the variables that are internal to the object and
+returns a pointer to the dataspace.
+
+The type-cast to the dataspace is necessary.
+
+Normally, the constructor would initialize the object-variables.
+However, since we have none, this is not necessary.
+
+
+The constructor has to return a pointer to the instantiated dataspace.
+
+\subsection{the code: \tt helloworld}
+
+\begin{verbatim}
+#include "m_pd.h"
+
+static t_class *helloworld_class;
+
+typedef struct _helloworld {
+ t_object x_obj;
+} t_helloworld;
+
+void helloworld_bang(t_helloworld *x)
+{
+ post("Hello world !!");
+}
+
+void *helloworld_new(void)
+{
+ t_helloworld *x = (t_helloworld *)pd_new(helloworld_class);
+
+ return (void *)x;
+}
+
+void helloworld_setup(void) {
+ helloworld_class = class_new(gensym("helloworld"),
+ (t_newmethod)helloworld_new,
+ 0, sizeof(t_helloworld),
+ CLASS_DEFAULT, 0);
+ class_addbang(helloworld_class, helloworld_bang);
+}
+\end{verbatim}
+
+
+\section{a simple external: {\tt counter}}
+
+Now we want to realize a simple counter as an external.
+A ``bang''-trigger outputs the counter-value on the outlet and
+afterwards increases the counter-value by 1.
+
+This class is similar to the previous one,
+but the dataspace is extended by a variable ``counter'' and the
+result is written as a message to an outlet instead of
+a string to the standarderror.
+
+\subsection{object-variables}
+Of course, a counter needs a state-variable to store the actual counter-value.
+
+State-variables that belong to classinstances belong to the dataspace.
+
+\begin{verbatim}
+typedef struct _counter {
+ t_object x_obj;
+ t_int i_count;
+} t_counter;
+\end{verbatim}
+
+The integer variable \verb+i_count+ stores the counter-value.
+
+\subsection{object-arguments}
+It is quite usefull for a counter, if a initial value can be defined by the user.
+Therefore this initial value should be passed to the object at creation-time.
+
+\begin{verbatim}
+void counter_setup(void) {
+ counter_class = class_new(gensym("counter"),
+ (t_newmethod)counter_new,
+ 0, sizeof(t_counter),
+ CLASS_DEFAULT,
+ A_DEFFLOAT, 0);
+
+ class_addbang(counter_class, counter_bang);
+}
+\end{verbatim}
+
+So we have an additional argument in the function \verb+class_new+:
+\verb+A_DEFFLOAT+ tells pd, that the object needs one argument of the
+type \verb+t_floatarg+.
+If no argument is passed, this will default to ``0''.
+
+\subsection{constructor}
+The constructor has some new tasks.
+On the one hand, a variable value has to be initialized,
+on the other hand, an outlet for the object has to be created.
+
+\begin{verbatim}
+void *counter_new(t_floatarg f)
+{
+ t_counter *x = (t_counter *)pd_new(counter_class);
+
+ x->i_count=f;
+ outlet_new(&x->x_obj, &s_float);
+
+ return (void *)x;
+}
+\end{verbatim}
+
+The constructor-method has one argument of type \verb+t_floatarg+ as declared
+in the setup-routine by \verb+class_new+.
+This argument is used to initialize the counter.
+
+A new outlet is created with the function \verb+outlet_new+.
+The first argument is a pointer to the interna of the object
+the new outlet is created for.
+
+The second argument is a symbolic description of the outlet-type.
+Since out counter should output numeric values it is of type ``float''.
+
+\verb+outlet_new+ returns a pointer to the new outlet and saves this very pointer
+in the \verb+t_object+-variable \verb+x_obj.ob_outlet+.
+If only one outlet is used, the pointer need not additionally be stored in the dataspace.
+If more than one outlets are used, the pointers have to be stored in the dataspace,
+because the \verb+t_object+-variable can only hold one outletpointer.
+
+\subsection{the countermethod}
+When triggered, the countervalue should be sent to the outlet
+and afterwards be incremented by 1.
+
+\begin{verbatim}
+void counter_bang(t_counter *x)
+{
+ t_float f=x->i_count;
+ x->i_count++;
+ outlet_float(x->x_obj.ob_outlet, f);
+}
+\end{verbatim}
+
+The function \verb+outlet_float+ sends a floating-point-value (second argument) to the outlet
+that is specified by the first argument.
+
+We first store the counter in a floatingpoint-buffer.
+Afterwards the counter is incremented and not before that the buffervariable is sent
+to the outlet.
+
+What appears to be unnecessary on the first glance, makes sense after further
+inspection:
+The buffervariable has been realized as \verb+t_float+,
+since \verb+outlet_float+ expects a floatingpoint-value and a typecast is
+inevitable.
+
+If the countervalue was sent to the outlet before being incremented,
+this could result in an unwanted (though welldefined) behaviour:
+If the counter-outlet directly triggered its own inlet,
+the counter-method would be called although the countervalue was not yet incremented.
+Normally this is not what we want.
+
+The same (correct) result could of course be obtained with a single line,
+but this would obscure the {\em reentrant}-problem.
+
+\subsection{the code: \tt counter}
+
+\begin{verbatim}
+#include "m_pd.h"
+
+static t_class *counter_class;
+
+typedef struct _counter {
+ t_object x_obj;
+ t_int i_count;
+} t_counter;
+
+void counter_bang(t_counter *x)
+{
+ t_float f=x->i_count;
+ x->i_count++;
+ outlet_float(x->x_obj.ob_outlet, f);
+}
+
+void *counter_new(t_floatarg f)
+{
+ t_counter *x = (t_counter *)pd_new(counter_class);
+
+ x->i_count=f;
+ outlet_new(&x->x_obj, &s_float);
+
+ return (void *)x;
+}
+
+void counter_setup(void) {
+ counter_class = class_new(gensym("counter"),
+ (t_newmethod)counter_new,
+ 0, sizeof(t_counter),
+ CLASS_DEFAULT,
+ A_DEFFLOAT, 0);
+
+ class_addbang(counter_class, counter_bang);
+}
+\end{verbatim}
+
+
+\section{a complex external: \tt counter}
+
+The simple counter of the previous chapter can easily be extended to more complexity.
+It might be quite usefull to be able to reset the counter to an initial value,
+to set upper and lower boudaries and to control the step-width.
+Each overrun should send a ``bang''-Message to a second outlet and reset the counter to
+the initial value.
+
+\subsection{extended dataspace}
+
+\begin{verbatim}
+typedef struct _counter {
+ t_object x_obj;
+ t_int i_count;
+ t_float step;
+ t_int i_down, i_up;
+ t_outlet *f_out, *b_out;
+} t_counter;
+\end{verbatim}
+
+The dataspace has been extended to hold variables for stepwidth and
+upper and lower boundaries.
+Furthermore pointers for two outlets have been added.
+
+\subsection{extension of the class}
+The new classobjects should have methods for different messages,
+like ``set'' and ``reset''.
+Therefore the methodspace has to be extended too.
+
+\begin{verbatim}
+ counter_class = class_new(gensym("counter"),
+ (t_newmethod)counter_new,
+ 0, sizeof(t_counter),
+ CLASS_DEFAULT,
+ A_GIMME, 0);
+\end{verbatim}
+
+The classgenerator \verb+class_new+ has been extended by the argument \verb+A_GIMME+.
+This enables a dynamic number of arguments to be passed at the instantiation of the object.
+
+\begin{verbatim}
+ class_addmethod(counter_class,
+ (t_method)counter_reset,
+ gensym("reset"), 0);
+\end{verbatim}
+
+\verb+class_addmethod+ adds a method for an arbitrary selector to an class.
+
+The first argument is the class the method (second argument) will be added to.
+
+The third argument is the symbolic selector that should be associated with the method.
+
+The remaining ``0''-terminated arguments describe the list of atoms that
+follows the selector.
+
+\begin{verbatim}
+ class_addmethod(counter_class,
+ (t_method)counter_set, gensym("set"),
+ A_DEFFLOAT, 0);
+ class_addmethod(counter_class,
+ (t_method)counter_bound, gensym("bound"),
+ A_DEFFLOAT, A_DEFFLOAT, 0);
+\end{verbatim}
+
+A method for ``set'' followed by a numerical value is added,
+as well as a method for the selector ``bound'' followed by two numerical values.
+
+\begin{verbatim}
+ class_sethelpsymbol(counter_class, gensym("help-counter"));
+\end{verbatim}
+
+If a pd-object is right-clicked, a help-patch describing the object-class can be opened.
+By default, this patch is located in the directory ``{\em doc/5.reference/}'' and
+is named like the symbolic classname.
+
+An alternative help-patch can be defined with the
+\verb+class_sethelpsymbol+-command.
+
+\subsection{construction of in- and outlets}
+
+When creating the object, several arguments should be passed by the user.
+
+\begin{verbatim}
+void *counter_new(t_symbol *s, int argc, t_atom *argv)
+\end{verbatim}
+Because of the declaration of arguments in the \verb+class_new+-function
+with \verb+A_GIMME+,
+the constructor has following arguments:
+
+\begin{tabular}{c|l}
+\verb+t_symbol *s+ & the symbolic name,\\
+& that was used for object creation \\
+\verb+int argc+ & the numer of arguments passed to the object\\
+\verb+t_atom *argv+ & a pointer to a list of {\tt argc} atoms
+\end{tabular}
+
+\begin{verbatim}
+ t_float f1=0, f2=0;
+
+ x->step=1;
+ switch(argc){
+ default:
+ case 3:
+ x->step=atom_getfloat(argv+2);
+ case 2:
+ f2=atom_getfloat(argv+1);
+ case 1:
+ f1=atom_getfloat(argv);
+ break;
+ case 0:
+ }
+ if (argc<2)f2=f1;
+ x->i_down = (f1<f2)?f1:f2;
+ x->i_up = (f1>f2)?f1:f2;
+
+ x->i_count=x->i_down;
+\end{verbatim}
+
+If three arguments are passed, these should be the {\em lower boundary},
+the {\em upper boundary} and the {\em step width}.
+
+If only two arguments are passed, the step-width defaults to ``1''.
+If only one argument is passed, this should be the {\em initial value} of the counter with
+step-width of ``1''.
+
+\begin{verbatim}
+ inlet_new(&x->x_obj, &x->x_obj.ob_pd,
+ gensym("list"), gensym("bound"));
+\end{verbatim}
+
+The function \verb+inlet_new+ creates a new ``active'' inlet.
+``Active'' means, that a class-method is called each time
+a message is sent to an ``active'' inlet.
+
+Due to the software-architecture, the first inlet is always ``active''.
+
+The first two arguments of the \verb+inlet_new+-function are
+pointers to the interna of the object and to the graphical presentation of the object.
+
+The symbolic selector that is specified by the third argument is to be
+substituted by another symbolic selector (fourth argument) for this inlet.
+
+Because of this substitution of selectors,
+a message on a certain right inlet can be treated as a message with
+a certain selector on the leftmost inlet.
+
+This means:
+\begin{itemize}
+\item The substituting selector has to be declared by \verb+class_addmethod+
+in the setup-routine.
+\item It is possible to simulate a certain right inlet, by sending a message with
+this inlet's selector to the leftmost inlet.
+\item It is not possible to add methods for more than one selector to a right inlet.
+Particularly it is not possible to add a universal method for arbitrary selectors to
+a right inlet.
+\end{itemize}
+
+\begin{verbatim}
+ floatinlet_new(&x->x_obj, &x->step);
+\end{verbatim}
+\verb+floatinlet_new+ generates a new ``passive'' inlet for numerical values.
+``Passive'' inlets allow parts of the dataspace-memory to be written directly
+from outside.
+Therefore it is not possible to check for illegal inputs.
+
+The first argument is a pointer to the internal infrastructure of the object.
+The second argument is the address in the dataspace-memory,
+where other objects can write too.
+
+``Passive'' inlets can be created for pointers, symbolic or
+numerical (floatingpoint\footnote{
+That's why the {\tt step}-width of the class\/dataspace is realized as {\tt t\_float}.})
+values.
+
+
+\begin{verbatim}
+ x->f_out = outlet_new(&x->x_obj, &s_float);
+ x->b_out = outlet_new(&x->x_obj, &s_bang);
+\end{verbatim}
+
+The pointers returned by \verb+outlet_new+ have to be saved in the class\/dataspace
+to be used later by the outlet-routines.
+
+The order of the generation of inlets and outlets is important,
+since it corresponds to the order of inlets and outlets in the
+graphical representation of the object.
+
+\subsection{extended methodspace}
+
+The method for the ``bang''-message has to fullfill the more complex tasks.
+
+\begin{verbatim}
+void counter_bang(t_counter *x)
+{
+ t_float f=x->i_count;
+ t_int step = x->step;
+ x->i_count+=step;
+ if (x->i_down-x->i_up) {
+ if ((step>0) && (x->i_count > x->i_up)) {
+ x->i_count = x->i_down;
+ outlet_bang(x->b_out);
+ } else if (x->i_count < x->i_down) {
+ x->i_count = x->i_up;
+ outlet_bang(x->b_out);
+ }
+ }
+ outlet_float(x->f_out, f);
+}
+\end{verbatim}
+
+Each outlet is identified by the \verb+outlet_...+-functions via the
+pointer to this outlets.
+
+The remaining methods still have to be implemented:
+
+\begin{verbatim}
+void counter_reset(t_counter *x)
+{
+ x->i_count = x->i_down;
+}
+
+void counter_set(t_counter *x, t_floatarg f)
+{
+ x->i_count = f;
+}
+
+void counter_bound(t_counter *x, t_floatarg f1, t_floatarg f2)
+{
+ x->i_down = (f1<f2)?f1:f2;
+ x->i_up = (f1>f2)?f1:f2;
+}
+\end{verbatim}
+
+\subsection{the code: \tt counter}
+
+\begin{verbatim}
+#include "m_pd.h"
+
+static t_class *counter_class;
+
+typedef struct _counter {
+ t_object x_obj;
+ t_int i_count;
+ t_float step;
+ t_int i_down, i_up;
+ t_outlet *f_out, *b_out;
+} t_counter;
+
+void counter_bang(t_counter *x)
+{
+ t_float f=x->i_count;
+ t_int step = x->step;
+ x->i_count+=step;
+
+ if (x->i_down-x->i_up) {
+ if ((step>0) && (x->i_count > x->i_up)) {
+ x->i_count = x->i_down;
+ outlet_bang(x->b_out);
+ } else if (x->i_count < x->i_down) {
+ x->i_count = x->i_up;
+ outlet_bang(x->b_out);
+ }
+ }
+
+ outlet_float(x->f_out, f);
+}
+
+void counter_reset(t_counter *x)
+{
+ x->i_count = x->i_down;
+}
+
+void counter_set(t_counter *x, t_floatarg f)
+{
+ x->i_count = f;
+}
+
+void counter_bound(t_counter *x, t_floatarg f1, t_floatarg f2)
+{
+ x->i_down = (f1<f2)?f1:f2;
+ x->i_up = (f1>f2)?f1:f2;
+}
+
+void *counter_new(t_symbol *s, int argc, t_atom *argv)
+{
+ t_counter *x = (t_counter *)pd_new(counter_class);
+ t_float f1=0, f2=0;
+
+ x->step=1;
+ switch(argc){
+ default:
+ case 3:
+ x->step=atom_getfloat(argv+2);
+ case 2:
+ f2=atom_getfloat(argv+1);
+ case 1:
+ f1=atom_getfloat(argv);
+ break;
+ case 0:
+ }
+ if (argc<2)f2=f1;
+
+ x->i_down = (f1<f2)?f1:f2;
+ x->i_up = (f1>f2)?f1:f2;
+
+ x->i_count=x->i_down;
+
+ inlet_new(&x->x_obj, &x->x_obj.ob_pd,
+ gensym("list"), gensym("bound"));
+ floatinlet_new(&x->x_obj, &x->step);
+
+ x->f_out = outlet_new(&x->x_obj, &s_float);
+ x->b_out = outlet_new(&x->x_obj, &s_bang);
+
+ return (void *)x;
+}
+
+void counter_setup(void) {
+ counter_class = class_new(gensym("counter"),
+ (t_newmethod)counter_new,
+ 0, sizeof(t_counter),
+ CLASS_DEFAULT,
+ A_GIMME, 0);
+
+ class_addbang (counter_class, counter_bang);
+ class_addmethod(counter_class,
+ (t_method)counter_reset, gensym("reset"), 0);
+ class_addmethod(counter_class,
+ (t_method)counter_set, gensym("set"),
+ A_DEFFLOAT, 0);
+ class_addmethod(counter_class,
+ (t_method)counter_bound, gensym("bound"),
+ A_DEFFLOAT, A_DEFFLOAT, 0);
+
+ class_sethelpsymbol(counter_class, gensym("help-counter"));
+}
+\end{verbatim}
+
+
+\section{a signal-external: {\tt pan\~\/}}
+Signalclasses are normal pd-classes, that offer additional methods for signals.
+
+
+All methods and concepts that can be realized with normal objectclasses can
+therefore be realized with signalclasses too.
+
+Per agreement, the symbolic names of signalclasses end with a tilde \~\/.
+
+The class ``pan\~\/'' shall demonstrate, how signalclasses are written.
+
+A signal on the left inlet is mixed with a signal on the second inlet.
+Der mixing-factor between 0 and 1 is defined via a \verb+t_float+-message
+on a third inlet.
+
+\subsection{variables of a signalclass}
+Since a signal-class is only an extended normal class,
+there are no principal differences between the dataspaces.
+
+\begin{verbatim}
+typedef struct _pan_tilde {
+ t_object x_obj;
+
+ t_sample f_pan;
+ t_float f;
+} t_pan_tilde;
+\end{verbatim}
+
+Only one variable \verb+f_pan+ for the {\em mixing-factor} of the panning-function is needed.
+
+The other variable \verb+f+ is needed whenever a signal-inlet is needed too.
+If no signal but only a float-message is present at a signal-inlet, this
+variable is used to automatically convert the float to signal.
+
+\subsection{signal-classes}
+
+\begin{verbatim}
+void pan_tilde_setup(void) {
+ pan_tilde_class = class_new(gensym("pan~"),
+ (t_newmethod)pan_tilde_new,
+ 0, sizeof(t_pan_tilde),
+ CLASS_DEFAULT,
+ A_DEFFLOAT, 0);
+
+ class_addmethod(pan_tilde_class,
+ (t_method)pan_tilde_dsp, gensym("dsp"), 0);
+ CLASS_MAINSIGNALIN(pan_tilde_class, t_pan_tilde, f);
+}
+\end{verbatim}
+
+A method for signal-processing has to be provided by each signalclass.
+
+Whenever pd's audioengine is started, a message with the selector ``dsp''
+is sent to each object.
+Each class that has a method for the ``dsp''-message is recognized as signalclass.
+
+Signalclasses that want to provide signal-inlets have to
+declare this via the \verb+CLASS_MAINSIGNALIN+-macro.
+This enables signals at the first (default) inlet.
+If more than one signal-inlet is needed, they have to be created explicitly
+in the constructor-method.
+
+Inlets that are declared as signal-inlets cannot provide
+methods for \verb+t_float+-messages any longer.
+
+The first argument of the macro is a pointer to the signalclass.
+The second argument is the type of the class's dataspace.
+
+The last argument is a dummy-variable out of the dataspace that is needed
+to replace non-existing signal at the signal-inlet(s) with \verb+t_float+-messages.
+
+\subsection{construction of signal-inlets and -outlets}
+
+\begin{verbatim}
+void *pan_tilde_new(t_floatarg f)
+{
+ t_pan_tilde *x = (t_pan_tilde *)pd_new(pan_tilde_class);
+
+ x->f_pan = f;
+
+ inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal);
+ floatinlet_new (&x->x_obj, &x->f_pan);
+
+ outlet_new(&x->x_obj, &s_signal);
+
+ return (void *)x;
+}
+\end{verbatim}
+
+Additional signal-inlets are added like other inlets with the routine \verb+inlet_new+.
+The last two arguments are references to the symbolic selector ``signal''
+in the lookup-table.
+
+Signal-outlets are also created like normal (message-)outlets,
+by setting the outlet-selector to ``signal''.
+
+\subsection{DSP-methods}
+Whenever pd's audioengine is turned on,
+all signal-objects declare their perform-routines that are to be added to the DSP-tree.
+
+The ``dsp''-method has two arguments, the pointer to the class-dataspace, and
+a pointer to an array of signals.
+
+The signals are arranged in the array in such way,
+that they are ordered in a clockwise way in the graphical representation of the
+object.\footnote{
+If both left and right in- and out-signals exist, this means:
+First is the leftmost in-signal followed by the right in-signals;
+after the right out-signals, finally there comes the leftmost out-signal.}
+
+\begin{verbatim}
+void pan_tilde_dsp(t_pan_tilde *x, t_signal **sp)
+{
+ dsp_add(pan_tilde_perform, 5, x,
+ sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[0]->s_n);
+}
+\end{verbatim}
+
+\verb+dsp_add+ adds a {\em perform}-routine (as declared in the first argument)
+to the DSP-tree.
+
+The second argument is the number of the following pointers to diverse variables.
+Which pointers to which variables are passed is not limited.
+
+Here, sp[0] is the first in-signal, sp[1] represents the second in-signal and
+sp[3] points to the out-signal.
+
+The structure \verb+t_signal+ contains a pointer to the
+its signal-vector \verb+().s_vec+ (an array of samples of type \verb+t_sample+),
+and the length of this signal-vector \verb+().s_n+.
+
+Since all signalvectors of a patch (not including it's sub-patches) are of the same length,
+it is sufficient to get the length of one of these vectors.
+
+\subsection{perform-routine}
+The perform-routine is the DSP-heart of each signalclass.
+
+A pointer to an integer-array is passed to it.
+This array contains the pointers, that were passed via \verb+dsp_add+,
+which must be casted back to their real type.
+
+The perform-routine has to return a pointer to integer,
+that points to the address behind the stored pointers of the routine.
+This means, that the return argument equals the
+argument of the perform-routine plus
+the number of pointervariables (as declared as the second argument
+of \verb+dsp_add+) plus one.
+
+\begin{verbatim}
+t_int *pan_tilde_perform(t_int *w)
+{
+ t_pan_tilde *x = (t_pan_tilde *)(w[1]);
+ t_sample *in1 = (t_sample *)(w[2]);
+ t_sample *in2 = (t_sample *)(w[3]);
+ t_sample *out = (t_sample *)(w[4]);
+ int n = (int)(w[5]);
+
+ t_sample f_pan = (x->f_pan<0)?0.0:(x->f_pan>1)?1.0:x->f_pan;
+
+ while (n--) *out++ = (*in1++)*(1-f_pan)+(*in2++)*f_pan;
+
+ return (w+6);
+}
+\end{verbatim}
+
+Each sample of the signalvectors is read and manipulated in the \verb+while+-loop.
+
+
+Optimization of the DSP-tree tries to avoid unnecessary copy-operations.
+Therefore it is possible, that in- and out-signal are located
+at the same address in the memory.
+In this case, the programmer has to be careful not to write into the out-signal
+before having read the in-signal to avoid overwriting data that is not yet saved.
+
+\subsection{the code: \tt pan\~\/}
+
+\begin{verbatim}
+#include "m_pd.h"
+
+static t_class *pan_tilde_class;
+
+typedef struct _pan_tilde {
+ t_object x_obj;
+ t_sample f_pan;
+ t_sample f;
+} t_pan_tilde;
+
+t_int *pan_tilde_perform(t_int *w)
+{
+ t_pan_tilde *x = (t_pan_tilde *)(w[1]);
+ t_sample *in1 = (t_sample *)(w[2]);
+ t_sample *in2 = (t_sample *)(w[3]);
+ t_sample *out = (t_sample *)(w[4]);
+ int n = (int)(w[5]);
+ t_sample f_pan = (x->f_pan<0)?0.0:(x->f_pan>1)?1.0:x->f_pan;
+
+ while (n--) *out++ = (*in1++)*(1-f_pan)+(*in2++)*f_pan;
+
+ return (w+6);
+}
+
+void pan_tilde_dsp(t_pan_tilde *x, t_signal **sp)
+{
+ dsp_add(pan_tilde_perform, 5, x,
+ sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[0]->s_n);
+}
+
+void *pan_tilde_new(t_floatarg f)
+{
+ t_pan_tilde *x = (t_pan_tilde *)pd_new(pan_tilde_class);
+
+ x->f_pan = f;
+
+ inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal);
+ floatinlet_new (&x->x_obj, &x->f_pan);
+ outlet_new(&x->x_obj, &s_signal);
+
+ return (void *)x;
+}
+
+void pan_tilde_setup(void) {
+ pan_tilde_class = class_new(gensym("pan~"),
+ (t_newmethod)pan_tilde_new,
+ 0, sizeof(t_pan_tilde),
+ CLASS_DEFAULT,
+ A_DEFFLOAT, 0);
+
+ class_addmethod(pan_tilde_class,
+ (t_method)pan_tilde_dsp, gensym("dsp"), 0);
+ CLASS_MAINSIGNALIN(pan_tilde_class, t_pan_tilde, f);
+}
+\end{verbatim}
+
+\vfill
+\newpage
+\begin{appendix}
+
+\section{pd's message-system}
+Non-audio-data are distributed via a message-system.
+Each message consists of a ``selector'' and a list of atoms.
+
+\subsection{atoms}
+
+There are three kinds of atoms:
+\begin{itemize}
+\item {\em A\_FLOAT}: a numerical value (floatingpoint)
+\item {\em A\_SYMBOL}: a symbolic value (string)
+\item {\em A\_POINTER}: a pointer
+\end{itemize}
+
+Numerical values are always floatingpoint-values (\verb+t_float+),
+even if they could be displayed as integer values.
+
+Each symbol is stored in a lookup-table for reasons of performance.
+The command \verb+gensym+ looks up a string in the lookup-table and
+returns the address of the symbol.
+If the string is not yet to be found in the table,
+a new symbol is added.
+
+Atoms of type {\em A\_POINTER} are not very important (for simple externals).
+
+The type of an atom \verb+a+ is stored in the structure-element \verb+a.a_type+.
+
+\subsection{selectors}
+The selector is a symbol that defines the type of a message.
+There are five predefined selectors:
+\begin{itemize}
+\item ``{\tt bang}'' labels a triggerevent.
+A ``bang''-message consists only of the selector and contains no lists of atoms.
+\item ``{\tt float}'' labels a numerical value.
+The list of a ``float''-Message contains one single atom of type {\em A\_FLOAT}
+\item ``{\tt symbol}'' labels a symbolic value.
+The list of a ``symbol''-Message contains one single atom of type {\em A\_SYMBOL}
+\item ``{\tt pointer}'' labels a pointer value.
+The list of a ``pointer''-Message contains one single atom of type {\em A\_POINTER}
+\item ``{\tt list}'' labels a list of one or more atoms of arbitrary type.
+\end{itemize}
+
+Since the symbols for these selectors are used quite often,
+their address in the lookup-table can be queried directly,
+without having to use \verb+gensym+:
+
+\begin{tabular}{l||l|l}
+selector&lookup-routine&lookup-address\\
+\hline
+\tt bang &\verb+gensym("bang")+ & \verb+&s_bang+ \\
+\tt float &\verb+gensym("float")+ & \verb+&s_float+ \\
+\tt symbol &\verb+gensym("symbol")+ & \verb+&s_symbol+ \\
+\tt pointer &\verb+gensym("pointer")+ & \verb+&s_pointer+ \\
+\tt list &\verb+gensym("list")+ & \verb+&s_list+ \\
+--- (signal) &\verb+gensym("signal")+&\verb+&s_symbol+
+\end{tabular}
+
+Other selectors can be used as well.
+The receiving class has to provide a method for a specifique selector
+or for ``anything'', which is any arbitrary selector.
+
+Messages that have no explicit selector and start with a numerical value,
+are recognized automatically either as ``float''-message (only one atom) or as
+``list''-message (several atoms).
+
+For example, messages ``\verb+12.429+'' and ``\verb+float 12.429+'' are identical.
+Likewise, the messages ``\verb+list 1 for you+'' is identical to ``\verb+1 for you+''.
+
+\section{pd-types}
+Since pd is used on several plattforms,
+many ordinary types of variables, like \verb|int|, are re-defined.
+To write portable code, it is reasonable to use types provided by pd.
+
+Apart from this there are many predefined types,
+that should make the life of the programmer simpler.
+
+Generally, pd-types start with \verb|t_|.
+
+\begin{tabular}{c|l}
+pd-type & description \\
+\hline\hline
+\verb+t_atom+& atom \\
+\verb+t_float+ & floatingpoint value\\
+\verb+t_symbol+ & symbol \\
+\verb+t_gpointer+ & pointer (to graphical objects) \\
+\hline
+\verb+t_int+ & integer value \\
+\verb+t_signal+ & structure of a signal \\
+\verb+t_sample+ & audiosignal-value (floatingpoint)\\
+\verb+t_outlet+ & outletof an object \\
+\verb+t_inlet+ & inlet of an object \\
+\verb+t_object+ & object-interna \\
+\hline
+\verb+t_class+ & a pd-class \\
+\verb+t_method+ & class-method \\
+\verb+t_newmethod+ & pointer to a constructor (new-routine) \\
+\end{tabular}
+
+
+\section{important functions in ``m\_pd.h''}
+
+\subsection{functions: atoms}
+
+\subsubsection{SETFLOAT}
+\begin{verbatim}
+SETFLOAT(atom, f)
+\end{verbatim}
+This macro sets the type of \verb+atom+ to \verb+A_FLOAT+
+and stores the numerical value \verb+f+ in this atom.
+
+\subsubsection{SETSYMBOL}
+\begin{verbatim}
+SETSYMBOL(atom, s)
+\end{verbatim}
+This macro sets the type of \verb+atom+ to \verb+A_SYMBOL+
+and stores the symbolic pointer \verb+s+ in this atom.
+
+\subsubsection{SETPOINTER}
+\begin{verbatim}
+SETPOINTER(atom, pt)
+\end{verbatim}
+This macro sets the type of \verb+atom+ to \verb+A_POINTER+
+and stores the pointer \verb+pt+ in this atom.
+
+\subsubsection{atom\_getfloat}
+\begin{verbatim}
+t_float atom_getfloat(t_atom *a);
+\end{verbatim}
+If the type of the atom \verb+a+ is \verb+A_FLOAT+,
+the numerical value of this atom else ``0.0'' is returned.
+
+\subsubsection{atom\_getfloatarg}
+\begin{verbatim}
+t_float atom_getfloatarg(int which, int argc, t_atom *argv)
+\end{verbatim}
+If the type of the atom -- that is found at in the atom-list
+\verb+argv+ with the length \verb+argc+ at the place \verb+which+ --
+is \verb+A_FLOAT+, the numerical value of this atom else ``0.0'' is returned.
+
+\subsubsection{atom\_getint}
+\begin{verbatim}
+t_int atom_getint(t_atom *a);
+\end{verbatim}
+If the type of the atom \verb+a+ is \verb+A_FLOAT+,
+its numerical value is returned as integer else ``0'' is returned.
+
+\subsubsection{atom\_getsymbol}
+\begin{verbatim}
+t_symbol atom_getsymbol(t_atom *a);
+\end{verbatim}
+If the type of the atom \verb+a+ is \verb+A_SYMBOL+,
+a pointer to this symbol is returned, else a null-pointer ``0'' is returned.
+
+\subsubsection{atom\_gensym}
+\begin{verbatim}
+t_symbol *atom_gensym(t_atom *a);
+\end{verbatim}
+If the type of the atom \verb+a+ is \verb+A_SYMBOL+,
+a pointer to this symbol is returned.
+
+Atoms of a different type, are ``reasonably'' converted into a string.
+This string is -- on demand -- inserted into the symbol-table.
+A pointer to this symbol is returned.
+
+\subsubsection{atom\_string}
+\begin{verbatim}
+void atom_string(t_atom *a, char *buf, unsigned int bufsize);
+\end{verbatim}
+Converts an atom \verb+a+ into a {\tt C}-string \verb+buf+.
+The memory to this char-Buffer has to be reserved manually and
+its length has to be declared in \verb+bufsize+.
+
+\subsubsection{gensym}
+\begin{verbatim}
+t_symbol *gensym(char *s);
+\end{verbatim}
+Checks, whether the C-string \verb+*s+ has already been inserted into the symbol-table.
+If no entry exists, it is created.
+A pointer to the symbol is returned.
+
+\subsection{functions: classes}
+\subsubsection{class\_new}
+\begin{verbatim}
+t_class *class_new(t_symbol *name,
+ t_newmethod newmethod, t_method freemethod,
+ size_t size, int flags,
+ t_atomtype arg1, ...);
+\end{verbatim}
+Generates a class with the symbolic name \verb+name+.
+\verb+newmethod+ is the constructor that creates an instance of the class and
+returns a pointer to this instance.
+
+If memory is reserved dynamically, this memory has to be freed by the
+destructor-method \verb+freemethod+ (without any return argument),
+when the object is destroyed.
+
+\verb+size+ is the static size of the class-dataspace,
+that is returned by \verb+sizeof(t_mydata)+.
+
+\verb+flags+ define the presentation of the graphical object.
+A (more or less arbitrary) combination of following objects is possible:
+
+\begin{tabular}{l|l}
+flag&description\\
+\hline
+\verb+CLASS_DEFAULT+ & a normal object with one inlet \\
+\verb+CLASS_PD+ & \em object (without graphical presentation) \\
+\verb+CLASS_GOBJ+ & \em pure graphical object (like arrays, graphs,...)\\
+\verb+CLASS_PATCHABLE+ & \em a normal object (with one inlet) \\
+\verb+CLASS_NOINLET+ & the default inlet is suppressed \\
+\end{tabular}
+
+Flags the description of which is printed in {\em italic}
+are of small importance for writing externals.
+
+The remaining arguments \verb+arg1,...+ define the
+types of object-arguments passed at the creation of a class-object.
+A maximum of six typechecked arguments can be passed to an object.
+The list of argument-types are terminated by ``0''.
+
+Possible types of arguments are:
+
+\begin{tabular}{l|l}
+\verb+A_DEFFLOAT+ & a numerical value \\
+\verb+A_DEFSYMBOL+ & a symbolical value \\
+\verb+A_GIMME+ & a list of atoms of arbitrary length and types \\
+\end{tabular}
+
+If more than six arguments are to be passed,
+\verb+A_GIMME+ has to be used and a manual type-check has to be made.
+
+\subsubsection{class\_addmethod}
+\begin{verbatim}
+void class_addmethod(t_class *c, t_method fn, t_symbol *sel,
+ t_atomtype arg1, ...);
+\end{verbatim}
+Adds a method \verb+fn+ for a selector \verb+sel+ to a class \verb+c+.
+
+The remaining arguments \verb+arg1,...+ define the
+types of the list of atoms that follow the selector.
+A maximum of six type-checked arguments can be passed.
+If more than six arguments are to be passed,
+\verb+A_GIMME+ has to be used and a manual type-check has to be made.
+
+The list of arguments is terminated by ``0''.
+
+
+Possible types of arguments are:
+
+\begin{tabular}{l|l}
+\verb+A_DEFFLOAT+ & a numerical value \\
+\verb+A_DEFSYMBOL+ & a symbolical value \\
+\verb+A_POINTER+ & a pointer \\
+\verb+A_GIMME+ & a list of atoms of arbitrary length and types \\
+\end{tabular}
+
+\subsubsection{class\_addbang}
+\begin{verbatim}
+void class_addbang(t_class *c, t_method fn);
+\end{verbatim}
+Adds a method \verb+fn+ for ``bang''-messages to the class \verb+c+.
+
+The argument of the ``bang''-method is a pointer to the class-dataspace:
+
+\verb+void my_bang_method(t_mydata *x);+
+
+\subsubsection{class\_addfloat}
+\begin{verbatim}
+void class_addfloat(t_class *c, t_method fn);
+\end{verbatim}
+Adds a method \verb+fn+ for ``float''-messages to the class \verb+c+.
+
+The arguments of the ``float''-method is a pointer to the class-dataspace and
+a floatingpoint-argument:
+
+\verb+void my_float_method(t_mydata *x, t_floatarg f);+
+
+\subsubsection{class\_addsymbol}
+\begin{verbatim}
+void class_addsymbol(t_class *c, t_method fn);
+\end{verbatim}
+Adds a method \verb+fn+ for ``symbol''-messages to the class \verb+c+.
+
+The arguments of the ``symbol''-method is a pointer to the class-dataspace and
+a pointer to the passed symbol:
+
+\verb+void my_symbol_method(t_mydata *x, t_symbol *s);+
+
+\subsubsection{class\_addpointer}
+\begin{verbatim}
+void class_addpointer(t_class *c, t_method fn);
+\end{verbatim}
+Adds a method \verb+fn+ for ``pointer''-messages to the class \verb+c+.
+
+The arguments of the ``pointer''-method is a pointer to the class-dataspace and
+a pointer to a pointer:
+
+\verb+void my_pointer_method(t_mydata *x, t_gpointer *pt);+
+
+\subsubsection{class\_addlist}
+\begin{verbatim}
+void class_addlist(t_class *c, t_method fn);
+\end{verbatim}
+Adds a method \verb+fn+ for ``list''-messages to the class \verb+c+.
+
+The arguments of the ``list''-method are -- apart from a pointer to the class-dataspace --
+a pointer to the selector-symbol (always \verb+&s_list+),
+the number of atoms and a pointer to the list of atoms:
+
+\verb+void my_list_method(t_mydata *x,+
+
+\verb+ t_symbol *s, int argc, t_atom *argv);+
+
+\subsubsection{class\_addanything}
+\begin{verbatim}
+void class_addanything(t_class *c, t_method fn);
+\end{verbatim}
+Adds a method \verb+fn+ for an arbitrary message to the class \verb+c+.
+
+The arguments of the anything-method are -- apart from a pointer to the class-dataspace --
+a pointer to the selector-symbol,
+the number of atoms and a pointer to the list of atoms:
+
+\verb+void my_any_method(t_mydata *x,+
+
+\verb+ t_symbol *s, int argc, t_atom *argv);+
+
+\subsubsection{class\_addcreator}
+\begin{verbatim}
+ void class_addcreator(t_newmethod newmethod, t_symbol *s,
+ t_atomtype type1, ...);
+\end{verbatim}
+Adds a creator-symbol \verb+s+, alternative to the symbolic classname,
+to the constructor \verb+newmethod+.
+Thus, objects can be created either by their ``real'' classname or
+an alias-name (p.e. an abbreviation, like the internal ``float'' resp. ``f'').
+
+The ``0''-terminated list of types corresponds to that of \verb+class_new+.
+
+\subsubsection{class\_sethelpsymbol}
+\begin{verbatim}
+void class_sethelpsymbol(t_class *c, t_symbol *s);
+\end{verbatim}
+
+If a pd-object is right-clicked, a help-patch for the corresponding objectclass
+can be opened.
+By default this is a patch with the symbolic classname in the
+directory ``{\em doc/5.reference/}''.
+
+The name of the help-patch for the class that is pointed to by \verb+c+
+is changed to the symbol \verb+s+.
+
+Therefore, several similar classes can share a single help-patch.
+
+Path-information is relative to the default helppath {\em doc/5.reference/}.
+
+\subsubsection{pd\_new}
+\begin{verbatim}
+t_pd *pd_new(t_class *cls);
+\end{verbatim}
+Generates a new instance of the class \verb+cls+ and
+returns a pointer to this instance.
+
+\subsection{functions: inlets and outlets}
+All routines for inlets and outlets need a reference to the object-interna of
+the class-instance.
+When instantiating a new object,
+the necessary dataspace-variable of the \verb+t_object+-type is initialized.
+This variable has to be passed as the \verb+owner+-object to the
+various inlet- and outlet-routines.
+
+\subsubsection{inlet\_new}
+\begin{verbatim}
+t_inlet *inlet_new(t_object *owner, t_pd *dest,
+ t_symbol *s1, t_symbol *s2);
+\end{verbatim}
+Generates an additional ``active'' inlet for the object
+that is pointed at by \verb+owner+.
+Generally, \verb+dest+ points at ``\verb+owner.ob_pd+''.
+
+The selector \verb+s1+ at the new inlet is substituted by the selector \verb+s2+.
+
+If a message with selector \verb+s1+ appears at the new inlet,
+the class-method for the selector \verb+s2+ is called.
+
+This means
+\begin{itemize}
+\item The substituting selector has to be declared by \verb+class_addmethod+
+in the setup-routine.
+\item It is possible to simulate a certain right inlet, by sending a message with
+this inlet's selector to the leftmost inlet.
+
+Using an empty symbol (\verb+gensym("")+) as selector
+makes it impossible to address a right inlet via the leftmost one.
+
+\item It is not possible to add methods for more than one selector to a right inlet.
+Particularly it is not possible to add a universal method for arbitrary selectors to
+a right inlet.
+\end{itemize}
+
+\subsubsection{floatinlet\_new}
+\begin{verbatim}
+t_inlet *floatinlet_new(t_object *owner, t_float *fp);
+\end{verbatim}
+Generates a new ``passive'' inlet for the object that is pointed at by \verb+owner+.
+This inlet enables numerical values to be written directly into the
+memory \verb+fp+, without calling a dedicated method.
+
+\subsubsection{symbolinlet\_new}
+\begin{verbatim}
+t_inlet *symbolinlet_new(t_object *owner, t_symbol **sp);
+\end{verbatim}
+Generates a new ``passive'' inlet for the object that is pointed at by \verb+owner+.
+This inlet enables symbolic values to be written directly into the
+memory \verb+*sp+, without calling a dedicated method.
+
+
+\subsubsection{pointerinlet\_new}
+\begin{verbatim}
+t_inlet *pointerinlet_new(t_object *owner, t_gpointer *gp);
+\end{verbatim}
+Generates a new ``passive'' inlet for the object that is pointed at by \verb+owner+.
+This inlet enables pointer to be written directly into the
+memory \verb+gp+, without calling a dedicated method.
+
+\subsubsection{outlet\_new}
+\begin{verbatim}
+t_outlet *outlet_new(t_object *owner, t_symbol *s);
+\end{verbatim}
+Generates a new outlet for the object that is pointed at by \verb+owner+.
+The Symbol \verb+s+ indicates the type of the outlet.
+
+\begin{tabular}{c|l||l}
+symbol & symbol-addresse & outlet-type \\
+\hline\hline
+``bang'' & \verb+&s_bang+ & message (bang)\\
+``float'' & \verb+&s_float+ & message (float)\\
+``symbol'' & \verb+&s_symbol+ & message (symbol) \\
+``pointer'' & \verb+&s_gpointer+ & message (pointer)\\
+``list'' & \verb+&s_list+ & message (list) \\
+--- & 0 & message \\
+\hline
+``signal'' & \verb+&s_signal+ & signal \\
+\end{tabular}
+
+There are no real differences between outlets of the various message-types.
+At any rate, it makes code more easily readable,
+if the use of outlet is shown at creation-time.
+For outlets for any messages a null-pointer is used.
+Signal-outlet must be declared with \verb+&s_signal+.
+
+Variables if the type \verb+t_object+ provide pointer to one outlet.
+Whenever a new outlet is generated, its address is stored in the
+objectvariable \verb+(*owner).ob_outlet+.
+
+If more than one message-outlet is needed,
+the outlet-pointers that are returned by \verb+outlet_new+
+have to be stored manually in the dataspace
+to address the given outlets.
+
+\subsubsection{outlet\_bang}
+\begin{verbatim}
+void outlet_bang(t_outlet *x);
+\end{verbatim}
+Outputs a ``bang''-message at the outlet specified by \verb+x+.
+
+\subsubsection{outlet\_float}
+\begin{verbatim}
+void outlet_float(t_outlet *x, t_float f);
+\end{verbatim}
+Outputs a ``float''-message with the numeric value \verb+f+
+at the outlet specified by \verb+x+.
+
+\subsubsection{outlet\_symbol}
+\begin{verbatim}
+void outlet_symbol(t_outlet *x, t_symbol *s);
+\end{verbatim}
+Outputs a ``symbol''-message with the symbolic value \verb+s+
+at the outlet specified by \verb+x+.
+
+\subsubsection{outlet\_pointer}
+\begin{verbatim}
+void outlet_pointer(t_outlet *x, t_gpointer *gp);
+\end{verbatim}
+Outputs a ``pointer''-message with the pointer \verb+gp+
+at the outlet specified by \verb+x+.
+
+\subsubsection{outlet\_list}
+\begin{verbatim}
+void outlet_list(t_outlet *x,
+ t_symbol *s, int argc, t_atom *argv);
+\end{verbatim}
+Outputs a ``list''-message at the outlet specified by \verb+x+.
+The list contains \verb+argc+ atoms.
+\verb+argv+ points to the first element of the atom-list.
+
+Independet of the symbol \verb+s+, the selector ``list'' will precede
+the list.
+
+To make the code more readable,
+\verb+s+ should point to the symbol list
+(either via \verb+gensym("list")+ or via \verb+&s_list+)
+
+\subsubsection{outlet\_anything}
+\begin{verbatim}
+void outlet_anything(t_outlet *x,
+ t_symbol *s, int argc, t_atom *argv);
+\end{verbatim}
+Outputs a message at the outlet specified by \verb+x+.
+
+The message-selector is specified with \verb+s+.
+It is followed by \verb+argc+ atoms.
+\verb+argv+ points to the first element of the atom-list.
+
+\subsection{functions: DSP}
+If a class should provide methods for digital signal-processing,
+a method for the selector ``dsp'' (followed by no atoms)
+has to be added to this class
+
+Whenever pd's audioengine is started,
+all objects that provide a ``dsp''-method are identified as instances of signalclasses.
+
+\paragraph{DSP-method}
+
+\begin{verbatim}
+void my_dsp_method(t_mydata *x, t_signal **sp)
+\end{verbatim}
+
+In the ``dsp''-method a classmethod for signal-processing
+is added to the DSP-tree by the function \verb+dsp_add+.
+
+Apart from the dataspace \verb+x+ of the object,
+an array of signals is passed.
+The signals in the array are arranged in such a way,
+that they can be read in the graphical representation of the object
+clockwisely.
+
+In case there are both two in- and out-signals, this means:
+
+\begin{tabular}{c|r}
+pointer & to signal \\
+\hline\hline
+sp[0] & left in-signal \\
+sp[1] & right in-signal \\
+sp[2] & right out-signal \\
+sp[3] & left out-signal \\
+\end{tabular}
+
+The signalstructure contains apart from other things:
+
+\begin{tabular}{c|l}
+structure-element & description \\
+\hline
+\verb+s_n+ & length of the signalvector \\
+\verb+s_vec+ & pointer to the signalvector \\
+\end{tabular}
+
+The signalvector is an array of samples of type \verb+t_sample+.
+
+\paragraph{perform-routine}
+\begin{verbatim}
+t_int *my_perform_routine(t_int *w)
+\end{verbatim}
+
+
+A pointer \verb+w+ to an array (of integer) is passed to
+the perform-routine that is inserted into the DSP-tree by \verb+class_add+.
+
+In this array the pointers that are passed via \verb+dsp_add+ are stored.
+These pointers have to be casted back to their original type.
+
+The first pointer is stored at \verb+w[1]+ !!!
+
+The perform-routine has to return a pointer to integer,
+that points directly behind the memory, where the object's pointers are stored.
+This means, that the return-argument equals the routine's argument \verb+w+
+plus the number of used pointers
+(as defined in the second argument of \verb+dsp_add+) plus one.
+
+\subsubsection{CLASS\_MAINSIGNALIN}
+\begin{verbatim}
+CLASS_MAINSIGNALIN(<class_name>, <class_data>, <f>);
+\end{verbatim}
+The macro \verb+CLASS_MAINSIGNALIN+ declares,
+that the class will use signal-inlets.
+
+The first macro-argument is a pointer to the signal-class.
+The second argument is the type of the class-dataspace.
+The third argument is a (dummy-)floatingpoint-variable of the dataspace,
+that is needed to automatically convert ``float''-messages into signals
+if no signal is present at the signal-inlet.
+
+No ``float''-methods can be used for signal-inlets, that are created this way.
+
+\subsubsection{dsp\_add}
+\begin{verbatim}
+void dsp_add(t_perfroutine f, int n, ...);
+\end{verbatim}
+Adds the perform-routine \verb+f+ to the DSP-tree.
+The perform-routine is called at each DSP-cycle.
+
+The second argument\verb+n+ defines the number of following pointer-arguments
+
+Which pointers to which data are passes is not limited.
+Generally, pointers to the dataspace of the object and to the
+signal-vectors are reasonable.
+The length of the signal-vectors should also be passed to manipulate signals effectively.
+
+\subsubsection{sys\_getsr}
+\begin{verbatim}
+float sys_getsr(void);
+\end{verbatim}
+Returns the samplerate of the system.
+
+\subsection{functions: memory}
+\subsubsection{getbytes}
+\begin{verbatim}
+void *getbytes(size_t nbytes);
+\end{verbatim}
+Reserves \verb+nbytes+ bytes and returns a pointer to the allocated memory.
+
+\subsubsection{copybytes}
+\begin{verbatim}
+void *copybytes(void *src, size_t nbytes);
+\end{verbatim}
+Copies \verb+nbytes+ bytes from \verb+*src+ into a newly allocated memory.
+The address of this memory is returned.
+
+\subsubsection{freebytes}
+\begin{verbatim}
+void freebytes(void *x, size_t nbytes);
+\end{verbatim}
+Frees \verb+nbytes+ bytes at address \verb+*x+.
+
+\subsection{functions: output}
+\subsubsection{post}
+\begin{verbatim}
+void post(char *fmt, ...);
+\end{verbatim}
+
+Writes a {\tt C}-string to the standarderror (shell).
+
+\subsubsection{error}
+\begin{verbatim}
+void error(char *fmt, ...);
+\end{verbatim}
+
+Writes a {\tt C}-string as an error-message to the standarderror (shell).
+
+The object that has output the error-message is marked and
+can be identified via the pd-menu {\em Find->Find last error}.
+
+\end{appendix}
+
+\end{document}
+
diff --git a/doc/tutorials/externals-howto/example1/helloworld.c b/doc/tutorials/externals-howto/example1/helloworld.c
new file mode 100644
index 00000000..43682997
--- /dev/null
+++ b/doc/tutorials/externals-howto/example1/helloworld.c
@@ -0,0 +1,92 @@
+/*
+ * HOWTO write an External for Pure data
+ * (c) 2001-2006 IOhannes m zmölnig zmoelnig[AT]iem.at
+ *
+ * this is the source-code for the first example in the HOWTO
+ * it creates an object that prints "Hello world!" whenever it
+ * gets banged.
+ *
+ * this file is released under Pd's license (BSD-like)
+ */
+
+
+
+/**
+ * include the interface to Pd
+ */
+#include "m_pd.h"
+
+/**
+ * define a new "class"
+ */
+static t_class *helloworld_class;
+
+
+/**
+ * this is the dataspace of our new object
+ * we don't need to store anything,
+ * however the first (and only) entry in this struct
+ * is mandatory and of type "t_object"
+ */
+typedef struct _helloworld {
+ t_object x_obj;
+} t_helloworld;
+
+
+/**
+ * this method is called whenever a "bang" is sent to the object
+ * the name of this function is arbitrary and is registered to Pd in the
+ * helloworld_setup() routine
+ */
+void helloworld_bang(t_helloworld *x)
+{
+ /*
+ * post() is Pd's version of printf()
+ * the string (which can be formatted like with printf()) will be
+ * output to wherever Pd thinks it has too (pd's console, the stderr...)
+ * it automatically adds a newline at the end of the string
+ post("Hello world !!");
+}
+
+
+/**
+ * this is the "constructor" of the class
+ * this method is called whenever a new object of this class is created
+ * the name of this function is arbitrary and is registered to Pd in the
+ * helloworld_setup() routine
+ */
+void *helloworld_new(void)
+{
+ /*
+ * call the "constructor" of the parent-class
+ * this will reserve enough memory to hold "t_helloworld"
+ */
+ t_helloworld *x = (t_helloworld *)pd_new(helloworld_class);
+
+ /*
+ * return the pointer to the class - this is mandatory
+ * if you return "0", then the object-creation will fail
+ */
+ return (void *)x;
+}
+
+
+/**
+ * define the function-space of the class
+ * within a single-object external the name of this function is special
+ */
+void helloworld_setup(void) {
+ /* create a new class */
+ helloworld_class = class_new(gensym("helloworld"), /* the object's name is "helloworld" */
+ (t_newmethod)helloworld_new, /* the object's constructor is "helloworld_new()" */
+ 0, /* no special destructor */
+ sizeof(t_helloworld), /* the size of the data-space */
+ CLASS_DEFAULT, /* a normal pd object */
+ 0); /* no creation arguments */
+
+ /* attach functions to messages */
+ /* here we bind the "helloworld_bang()" function to the class "helloworld_class()" -
+ * it will be called whenever a bang is received
+ */
+ class_addbang(helloworld_class, helloworld_bang);
+}
diff --git a/doc/tutorials/externals-howto/example2/counter.c b/doc/tutorials/externals-howto/example2/counter.c
new file mode 100644
index 00000000..afc72335
--- /dev/null
+++ b/doc/tutorials/externals-howto/example2/counter.c
@@ -0,0 +1,86 @@
+/*
+ * HOWTO write an External for Pure data
+ * (c) 2001-2006 IOhannes m zmölnig zmoelnig[AT]iem.at
+ *
+ * this is the source-code for the second example in the HOWTO
+ * it creates an object that increments and outputs a counter
+ * whenever it gets banged.
+ *
+ * this file is released under Pd's license (BSD-like)
+ */
+
+
+
+/**
+ * include the interface to Pd
+ */
+#include "m_pd.h"
+
+/**
+ * define a new "class"
+ */
+static t_class *counter_class;
+
+
+
+/**
+ * this is the dataspace of our new object
+ * the first (mandatory) "t_object"
+ * and a variable that holds the current counter value
+ */
+typedef struct _counter {
+ t_object x_obj;
+ t_int i_count;
+} t_counter;
+
+
+/**
+ * this method is called whenever a "bang" is sent to the object
+ * a reference to the class-dataspace is given as argument
+ * this enables us to do something with the data (e.g. increment the counter)
+ */
+void counter_bang(t_counter *x)
+{
+ /*
+ * convert the current counter value to floating-point to output it later
+ */
+ t_float f=x->i_count;
+ /* increment the counter */
+ x->i_count++;
+ /* send the old counter-value to the 1st outlet of the object */
+ outlet_float(x->x_obj.ob_outlet, f);
+}
+
+
+/**
+ * this is the "constructor" of the class
+ * we have one argument of type floating-point (as specified below in the counter_setup() routine)
+ */
+void *counter_new(t_floatarg f)
+{
+ t_counter *x = (t_counter *)pd_new(counter_class);
+
+ /* set the counter value to the given argument */
+ x->i_count=f;
+
+ /* create a new outlet for floating-point values */
+ outlet_new(&x->x_obj, &s_float);
+
+ return (void *)x;
+}
+
+
+/**
+ * define the function-space of the class
+ */
+void counter_setup(void) {
+ counter_class = class_new(gensym("counter"),
+ (t_newmethod)counter_new,
+ 0,
+ sizeof(t_counter),
+ CLASS_DEFAULT,
+ A_DEFFLOAT, 0); /* the object takes one argument which is a floating-point and defaults to 0 */
+
+ /* call a function when object gets banged */
+ class_addbang(counter_class, counter_bang);
+}