Andreas Kortke, Berlin 1991
Kurzreferenz des Betriebssystems MuSys für eine eigene Hardware
>MuSys ist die informatische Umsetzung der algebraischen Musiktheorie von R. Nowotny. Die darin enthaltenen Konstruktionen sind als Datenstrukturen und Funktionen in der Programmiersprache "C" ausgeführt. Nachfolgend wird das Programmsystem strukturell und inhaltlich beschrieben.
Das System gliedert sich in folgende Programmdateien:
MusicDef.h - Definition grundlegender Konstanten und Datenstrukturen, sowie
Deklaration systemübergreifender Variablen.
MuSys.c - enthält Funktionen für die Behandlung von Noten,
Notenfolgen und Motiven.
Brueche.c - enthält Funktionen für das Rechnen mit "echten
Brüchen" und arithmetische Hilfsmittel.
Tonarten.c - enthält Funktionen für die Arbeit mit Tonarten,
Tonartfolge, Tonartverwandtschaften und Motiven.
MusicIo.c - enthält Funktionen für die Ein- und Ausgabe von
Notenfolgen und Musikstücken.
Oktaven.c - Behandlung von Oktaven.
Phrasen.c - Behandlung rhythmischer Phrasen und Folgen rhythmischer Phrasen.
Skalen.c - Funktionen zur Behandlung der Skalenlehre, sowie zur Arbeit mit
Akkorden, Akkordfolgen und Figuration.
Stilist.c - genrespezifische Funktionen zur Beachtung musikästhetischer
Grundsätze.
Analyse.c - beinhaltet eine Test- und Analysefunktion zur Begutachtung von
Zwischenergebnissen.
Demonstraton:
Vierstim.c - komponiert einen vierstimmigen Satz.
Fuge.c - komponiert eine zweistimmige Fuge in strenger Form.
JazzPar.c - komponiert zweistimmige Jazz- Etüden.
Cantus.c - komponiert einen "cantus firmus".
Weiterhin existieren verschiedene Datenstrukturen - "musikalische
Elemente".
Alle Elemente der Musiktheorie sind in speziellen C-Variablen, Datenstrukturen
oder Funktionen realisiert.
1. Noten
Zur Darstellung von Noten ist in "MusicDef.h" die Struktur
"Note" deklariert. Sie enthält eine weitere Struktur
"Br". Mit einer Struktur "Br" lässt sich ein echter
Bruch aus Zähler- und Nennerkomponente darstellen. In der Struktur
"Note" repräsentiert der Bruch den Notenwert. Weiter
enthält die Notenstruktur ein Element "N" für die Angabe
der Tonhöhe (Nummer des Halbtons: 0 entspricht c) und das Element
"O", die Oktavnummer der Note.
Diese drei Elemente beschreiben eine einzelne Note vollständig.
2.Notenfolgen
Um nun Sequenzen von Noten (Melodien u.s.w.) bilden zu können ist eine weitere C- Konstruktion erforderlich. Es handelt sich um eine Struktur, die man allgemein als Kettenglied bezeichnen kann. Diese Struktur "Notenfolge" enthält drei Zeiger auf Objekte des selben Typs, zwei "short" Elemente und ein Feld von Notenstrukturen, dessen Elementanzahl durch den Konstantwert "SEG" bestimmt wird.
Diese Art der Verkettung von Einzelelementen oder Segmenten (Feldern) von
Einzelelementen wird im System noch wiederholt auftreten. Die im Kettenglied
(Struktur Notenfolge) enthaltenen Zeigerelemente zeigen auf das vorhergehende Kettenglied
(*Prev), das nachfolgende Kettenglied (*Next) und das letzte Kettenglied
(*Last). Der Zeiger "*Last" hat nur im ersten Kettenglied einen
gültigen Wert. Im ersten Kettenglied hat "*Prev" und im letzten
Glied "*Next" den Wert Null.
In einer eingliedrigen Kette ist *Next und *Prev gleich Null und *Last zeigt
auf dieses, erste Glied. Operiert wird mit solchen Ketten immer durch den
Zeiger auf das erste Glied, in unserem Fall: "struct Notenfolge *".
Das "short" Element "First" der Struktur Notenfolge gibt
die Nummer der 1. Note des Kettengliedes
innerhalb der Kette an. Im ersten Kettenglied hat es den Wert Null.
Das Element "Len" gibt die Anzahl der im Kettenglied gültigen
Noteneintragungen an. Die Addition von "First" und "Len"
des letzten Kettengliedes ergibt die Anzahl der in der Kette vorhandenen
Elemente (Noten). Für die Arbeit mit Notenfolge existieren in der
Programmdatei "MuSys.c" einige Grundfunktionen,
die sinngemäß bei allen Kettentypen (Tonartfolge, Phrasenfolge
u.s.w.) Anwendung finden.
1. OpenNf() Öffnen einer Notenfolgen-Kette.
Ist der Übergabeparameter gleich Null, so wird eine neue Notenfolgenkette
eingerichtet und ein Zeiger auf diese zurückgegeben. Ist der Parameter ein
gültiger Zeiger auf eine Notenfolgen-Struktur, so wird diese um ein Glied
verlängert. Im Fehlerfall wird ein Nullpointer zurück
gegeben.
2. CloseNf() Schließt die spezifizierte Notenfolge.
Speicher wird
freigegeben, die Notenfolge existiert nach Aufruf dieser Funktion nicht mehr!
3. NfSegment() Systeminterne Funktion, vom Anwender normalerweise nicht
benötigt. Sie liefert den Zeiger des Kettengliedes der spezifizierten
Note.
4. AddNote() An die spezifizierte Notenfolge wird eine Note angefügt.
Sollte kein Platz im letzten Kettenglied sein, so wird die Kette um ein Glied
verlängert. Normalerweise wird der Zeiger auf die Notenstruktur
zurückgegeben, in die eine neue Note eingetragen wurde. Im Fehlerfall wird
ein Nullpointer zurückgegeben.
5. LastNote() Liefert die Anzahl der Noten in einer Notenfolge.
6. GetNote() Liefert den Zeiger auf die spezifizierte Note der Notenfolge, im
Fehlerfall einen Nullpointer.
7. PutNote() Überschreibt die spezifizierte Note der Notenfolge mit den
Werten der übergebenen Notenstruktur. Existiert die spezifizierte Note
nicht in der Notenfolge, so wird diese entsprechend verlängert.
3. Scores
Komplette Musikstücke werden durch die Datenstruktur "Score"
dargestellt. Diese Struktur ist ebenfalls ein Kettenglied, das heißt, sie
enthält die nötigen Zeigerelemente. Jedes Kettenglied stellt eine
zeitlich verzögerte Melodie, oder eine Stimme einer Polyphonie dar. Hierzu
enthält jede Struktur "Score" einen Zeiger auf eine Notenfolge,
die Struktur eines Bruches als zeitlichen Anfangsoffset und eine Tonartstruktur
"Haupttonart". Des weiteren existieren die
Variablen "Tempo" (Spieltempo [0...255]), "MidiKanal"
x*[1...16] für Midiausgabe, "Attack" - Anschlagzeit [0...127],
"Release"- Abklingzeit [0...127], "Volume"-
Gesamtlautstärke [0...255]. Für den Umgang mit Score- Strukturen
existieren die Funktionen:
1. AddScore() Eröffnen oder Erweitern einer Score- Kette.
2. CloseScore() Schließen einer Score- Kette.
Insbesondere bei Ein-/Ausgabefunktionen sind die Parameter vom Typ "struct
Score *".
4.Tonarten
Ähnlich wie für Noten existieren Datenstrukturen für Tonarten
und Tonartfolgen. Die Elemente einer Tonartstruktur sind vier Variable:
"Gt"- Grundton (c,cis,...,h) und
"Tg"- Tongeschlecht (Dur,moll,...).
Der Grundton ist analog zu den entsprechenden Noten codiert.
Tonartverwandtschaften sind als Funktionen mit Operanden vom Typ "struct
Tonart" in "Tonarten.c" definiert. Die Komponenten
"Ia" und "Ie" sind Indizes, die den Abschnitt in einer
korrespondierenden Notenfolge bestimmen, in dem diese Tonart gültig ist.
Der Index "Ie" zeigt jedoch nicht auf die letzte Note der jeweiligen
Tonart, sondern auf die erste Note der nächsten Tonart. So ist
"Ie" einer Tonart gleich "Ia" der nächsten Tonart. Das
hat Konsequenzen bei der Gestaltung von Programmschleifen und
Abbruchbedingungen.
Eine Tonartfolge- Struktur beinhaltet wie die Notenfolge- Struktur auch, drei
Zeigervariablen und zwei "short" Variablen "First" und
"Len", sowie ein Feld von Tonartstrukturen mit "SEG"
Elementen. Für den Umgang mit Tonartstrukturen und Tonartfolgen existieren
in "Tonarten.c" folgende Funktionen, deren Funktion
sinngemäß den Funktionen für Noten und Notenfolgen entspricht:
OpenTf(),
CloseTf(), TfSegment(), AddTonart(), GetTonart(), LastTonart().
Weiterhin gibt es Funktionen für die Tonartanalyse von Notenfolgen
(Tonarten(), Tonartzahl(), GetTonartTabelle(), Rnd_Tonart(), Tonart1(),
Tonart2(), Tonartanalyse()), sowie fr die Arbeit mit
Tonartverwandtschaften (RndTonartverwandtschaft(), Verwandtonart(),
Verwandtschaft()) und die Funktion GetTonartI(), die die Tonart zu einem bestimmten
Notenindex liefert.
Die Funktion "Leiterton()" liefert die Leitertonnummer einer Note bei
gegebener Tonart, die Funktion "Note()" liefert zu gegebenem
Leiterton und Tonart die entsprechende Note. Diese Funktionen benutzen das
zweidimensionale integer- Feld "TonartSteps[][]", welches zu jedem
Tongeschlecht die Folge der Halbtonschritte
enthält, um die Tonleitern korrekt zu bilden. In das zweidimensionale
integer- Feld "TonartTest[][]" werden, durch einen Aufruf der
Funktion "Tonarten()", die für einen Notenfolgenabschnitt in
Frage kommenden Tonarten eingetragen. Das Feld enthält ein Element
für jede Tonart. Hat ein Element einen Wert größer 0, so ist
diese Tonart fr den untersuchten Notenfolgenabschnitt möglich.
Aus den möglichen Tonarten kann dann mit weiteren Funktionen
(Tonart1().Tonart2()...)eine ausgewählt werden. Die Funktion
"GetTonartTabelle(n)" liefert die n.te gültige Tonart aus der
Tabelle. Funktionen, deren Rückgabewert vom Typ "struct Tonart"
ist, signalisieren einen Fehler als Rückgabe: Tonart- Grundton gleich
"note_p".
5. Rhythmische Phrasen
Rhythmische Elemente stellen die "Phrasen" dar. Es handelt sich ganz
allgemein um Folgen von Noten, bei denen die wesentlichen Informationen im
Notenwert liegen und die nur den Zustand "Pause" oder
"reguläre Note" kennen. In der Programmdatei
"Phrasen.c" sind wieder die bekannten Funktionen: OpenPf(),
ClosePf(), PfSegment(), AddPhrase(), GetPhrase(), LastPhrase(), PutPhrase()
und GetPhraseI() realisiert. Weiterhin enth"lt sie eine Tabelle
"Standard Phrasen" (StdPhrasen[]) mit vordefinierten Rhythmen, eine
Tabelle für den Austausch von Phrasen (Kasten) und dazugehörige
Funktionen (Kasten_Nr(), MakeSammelKasten(), NeuPhrase() und
Phrasenaustausch()). Die Funktionen für die
Phrasenanalyse von Notenfolgen heißen: Phrasentest() und
Phrasenanalyse(). Außerdem existiert eine Funktion Motivwahl(), die zu
einer gegebenen rhythmischen Phrase ein Motiv in der angegebenen Tonart
wählt.
6. Oktaven
Die Programmdatei "Oktaven.c" enthält Funktionen für die
Bestimmung von Oktavwerten nach einfachen Kriterien.
7. Ein-/Ausgabe von Notenfolgen und Musikstücken (Scores)
Für die Ein-/Ausgabe von Notenfolgen und Scores gibt es mehrere
Möglichkeiten, die je nach Verwendung des Systems zur Anwendung kommen,
bzw. noch um weitere Arten ergänzt werden müssen. Realisiert sind die
Ein-/Ausgabe in einer unstandardisierten Textnotation (InMelodie(),
PrMelodie(), LoadAscii() und SaveScore()) die folgendermaßen beschrieben
ist: [n/m]N[O][, oder .]
wobei [n/m] ein Notenwert bedeutet, der, wenn er weggelassen wird gleich dem
Notenwert der vorhergehenden Note bzw. "1/1" gesetzt wird.
"N" repräsentiert die eigentliche Note als Textkürzel
("c", "cis","d","dis","e",
"f", "fis", "g",
"gis","a","b","h","p").
Schließlich [O] ein optionaler Oktavwert, der, wenn er weggelassen wird,
gleich dem Oktavwert der vorhergehenden Note bzw. "1" gesetzt wird.
Mehrere Noten werden durch Kommata getrennt, ein Punkt beendet die Notenfolge.
Eine weitere Ein-/Ausgabe Möglichkeit ist die Arbeit mit standardisierten
Dateiformaten für Musikstücke. Dabei stehen je nach Rechnersystem
unterschiedliche Formate zur Verfügung.
Je nach Verfügbarkeit einer Midi- Schnittstelle kann man ein
Musikstück direkt über ein angeschlossenes Midi- Instrument spielen,
die entsprechende Funktion heißt "Play()".
8. Test- und Analysefunktion
Die Programmdatei "Analyse.c" enthält eine Funktion
"Analyse()", mit der es möglich ist, Notenfolgen,
dazugehörige Tonart- und Rhythmusphrasenabschnitte in einer Datei
abzulegen. Die Datei wird mit einem Filepointer spezifiziert.
Im Programm muss ein Filepointer "fp_prot" global deklariert sein und
einer Datei zugewiesen werden (bzw. Nullpointer). In dieser Datei werden alle
signifikanten Zwischenergebnisse abgelegt, um nach dem Programmlauf eventuell
den Kompositionsvorgang zu überprüfen.
9. Kompositionsprogramme
Die oben beschriebenen Funktionen und Datenstrukturen sind die Grundlage
für Programme die spezielle Kompositionen ausführen können.
Bisher wurden die Programme "vierstimmiger Satz (Vierstim.c)",
"zweistimmige Fuge in strenger Form (Fuge.c", "Jazzparnaß
(Jazzpar.c, Skalen.c)" und "Cantus Firmus (Cantus.c)"
realisiert.


