Monatsarchiv April 6, 2024

VonAlexander Vozian

Co-Creative Melody Generator: Visual Live-Coding with OM and Supercollider

Abstract: Der Co-Creative Melody Generator ist ein System für zeitgleiches Live-Coding mit SuperCollider und OpenMusic. Während in OpenMusic die Musik auf Notenebene gestaltet wird, ist SuperCollider für die Klangerzeugung zuständig. Die Kommunikation läuft durch Austausch von Nachrichten im Open-Sound-Control Protokoll per Abfrage durch User oder automatisiert.

Verantwortliche: Alexander Vozian

Überblick:

Die Zielsetzung für das Projekt war Integration von OpenMusic (OM) in einen Live Coding Workflow. Meine erste Idee dazu war es, SuperCollider (SC) für die Klangerzeugung zu verwenden und das Setzen der Noten auf OM auszulagern. Das heißt, man kann in SC live coden und OM als Hilfstool benutzen. In der Erarbeitung wurde aber klar, dass der OM-Patch während der Soundausgabe parallel verändert werden kann. Solange das Klang erzeugende Element nicht unterbrochen wird, kann Live Coding auch in OM stattfinden. Beispielsweise ist es möglich, die Auswahl an “Instrumenten”, in dem Fall SC Synths, vorzubereiten und diese komplett in OM zu steuern. Ein anderer kooperativerer Ansatz wäre, die zwei Programme, SC und OM, auf zwei Live Codende aufzuteilen. Zum Beispiel könnte eine Person in SC die Klanggestaltung übernehmen, während eine andere in OM diese Klänge in Zeit setzt. 

OM kümmert sich um die Generierung der Noten und SC um die Klangsynthese. Diese kommunizieren über das Open Sound Control  (OSC) Protokoll. Der User (Live Codende) schickt in SC eine Anfrage per OSC-Message an den OM-Patch. Die Message enthält Parameter für die Generierung einer Melodie, in dem Fall für eine Markov Analyse und Synthese. Die Message besteht aus:

  • der maximalen Anzahl von Noten,
  • die maximale Länge eines Loops in ms,
  • die Unter- und Obergrenze des zu analysierenden Ausgangsmaterials in ms
  • Auswahl des Ausgangsmaterials.

Das Ausgangsmaterial sind etwa 1 min lange Midi Dateien.

Quellen der Midi Dateien: bitmidi.com

Nach der Synthese schickt OM automatisch eine Message mit der Anzahl der generierten Noten, der Länge der Melodie in ms, einer Liste von Frequenzen und einer Liste von Onsets. Diese werden genutzt, um die Synths in SC zu steuern.

Bei jeder Evaluierung wird Notenmaterial analysiert und eine Liste von Frequenzen und Onsets synthetisiert und dann ausgegeben.

Für die Generierung der Noten werden etwa 1 min lange Midi-Dateien verwendet. Die Pitches und die Durations der Noten werden unabhängig voneinander mit Markov Funktionen erster Ordnung der OM-Alea Bibliothek analysiert, synthetisiert und per osc-send abgeschickt. Dadurch entstehen Tonfolgen, die in den Originaldateien nicht vorkommen. (Im Patch wird sichergestellt, dass die Liste der Pitches und die der Durations gleich lang ist.) Die Eingabeargumente sind bereits oben beschrieben.

Eine OSC-Message von OM zu SC besteht aus folgenden Daten:

  • OSC Key als Identifikator,
  • Gesamtzahl der Noten,
  • Länge der Melodie in Millisekunden,
  • Liste der Frequenzen,
  • Liste der Onsets.

Die Gesamtzahl der Noten wird in dem Fall nur für die Navigation durch die unformatierte OSC Message. Die Länge der Melodie wird benötigt, um den Zeitpunkt zu bestimmen, zu welchem die nächste Melodie angefragt wird. Die Liste der Frequenzen und die der Onsets wird erst in SC zusammengesetzt.

Die osc-send Funktion ist dabei in dem Patch markov_firstorder_osc_send. Um den Patch automatisch auszuführen, wenn eine OSC-Message ankommt, sind alle Teile des übergeordneten Patches auf reactive mode gestellt. Die list Funktion kann erst evaluiert werden, wenn alle Formen ein Ergebnis liefern, das heißt, wenn die Markov-Synthese abgeschlossen und osc-send ausgeführt wurde.

Das Ergebnis ist eine Art Server, der beim Eingang einer Anfrage aus SC automatisch eine Melodie zurückschickt.

In SC wird eine neue Instanz von OSCdef erzeugt, die die erhaltenen Parameter in globale Variablen speichert. Ein Synth(\t1) wird definiert, der von Patterns gespielt werden kann. Die Pfuncn Funktion interpretiert die globalen Variablen ~freq und ~dur als Funktionen und fragt diese damit ständig neu ab. Die Pseq Funktion setzt diese in eine Sequenz um, die von Pbind in als Pattern umgesetzt wird. Somit bildet der erste Parameter von ~freq mit dem ersten Parameter von ~dur die erste Note der Melodie. Die Pdef Funktion erstellt eine Instanz, die während der Laufzeit verändert werden kann. Damit wird auch sicher gestellt, dass ein laufender Loop erst nach Ende einer Melodie eine neue spielt.

Um eine neue Melodie, einen neuen Loop, anzufragen, reicht es, eine OSC-Message mit den entsprechenden Parametern zu schicken. Um diesen Prozess zu automatisieren, benötigt man ein die Funktion Tdef. 

Genauso wie das Ausführen eines Codeblocks in SC direkt Einfluss auf den Klang nehmen kann und somit richtig eingebettet werden muss, muss die Evaluierung eines Patches zur richtigen Zeit erfolgen. Im Falle des MWE wäre nicht der Klang unterbrochen, sondern das Metrum. 

Tdef(\om) berechnet zuerst die Zeitdauer, mit der das Senden der OSC-Message verzögert wird. Die Wartezeit ist abhängig von der Gesamtlänge des Loops und der Anzahl der Loops, welche man innerhalb des Tdef setzen kann. Dabei wird sichergestellt, dass der vorhandene Loop immer zu Ende gespielt wird, bevor die Parameter für einen neue Melodie ankommen.

Der Code zu OM und SC findet sich über diesen Link.

Abschließend noch folgendes Klangbeispiel zum Projekt:

Es wird ausschließlich die maximale Länge eines Loops und die Tonanzahl verändert. Das Ausgangsmaterial wird an zwei Stellen ausgewechselt. Es fängt an mit „Mario“, wechselt bei etwa 1:39 zu „Pokemon“ und bei 2:24 zu „Tetris“. Im Beispiel wird bewusst nichts am Klang des Instruments verändert (einfache Saw-Wave), um einen Fokus auf die Wechsel des Notenmaterials zu setzen.

Mario – Main Theme Overworld:


Pokemon – Battle (vs Wild Pokémon):


Tetris Theme:


Ergebnis:

Quellen der Midi Dateien: bitmidi.com