Xenakis: RW Simulator

Iannis Xenakis N’Shima: Interactive Random Walk Simulator.

Interaktiver Random Walk Generator

Um die statistischen Gestalten von Xenakis`s Random Walks nachzumodellieren programmierte ich eine interaktive Versuchsumgebung in Processing. Durch die Modifikation der stochastischen Verteilungsfüntionen für die Parameter Dauer, Intervall und elastische Grenzen lassen sich charakteristische Gestalten der Random Walks, wie sie in N’Shima und anderen Werken Xenakis‘ auftreten visuell generieren.

Xenakis’ Glissandi

Das Glissando hat in den Werken von Xenakis eine besondere Bedeutung. Es ist bereits in METASTASEIS ein zentraler Bestandteil und blieb in immer wieder veränderten Detailgestalten über Xenakis‘ gesamtes Schaffen eine seiner wichtigsten und am häufigsten komponierten Klanggestalten.
Grundsätzlich legt ein Glissando die Geschwindigkeit und den Verlauf der Bewegung von einer Tonhöhe zur nächsten fest. Die Kurve der Glissandolinie ist dabei durch das Tonhöhen- Intervall und die Zeitdauer, die für seine Ausführung festgelegt wurde, bestimmt (vgl. Sluchin, 2010, S. 17). Xenakis definiert das Glissando G durch den Differentialquotienten der Tonhöhe in der Zeit, also durch die Steigungs- beziehungsweise Fallgeschwindigkeit, die auf einen Ausgangspunkt P {f/t} zur Zeit t mit Frequenz f bezogen wird. Die gleichförmige kontinuierliche Geschwindigkeit v des Glissandos ist somit durch ∆f/∆t bestimmt. Xenakis will die Geschwindigkeit seiner Glissandi innerhalb von Ober- und Untergrenzen (die durch den möglichen Ambitus eines Instruments oder durch das Hörvermögen gesetzt sind) durch den Zufall bestimmen. Um Zufallsverteilung und Geschwindigkeit zu berechnen und als mathematische Formulierung als

normalverteilter Zufallsprozess für seine Musik nutzbar zu machen, bezieht sich Xenakis auf Modelle der kinetischen Gastheorie24. Diese entwickelte Modelle zur durchschnittlichen Geschwindigkeit von Molekülen. Xenakis behandelt nun, indem er ihre Wahrscheinlichkeitsverteilung um einen Mittelwert berechnet, Geschwindigkeiten von Glissandi wie jene von Molekülen von Gasen zwischen zwei Zeitpunkten (vgl. Baltensperger, 1996, S. 451– 452).
Dabei setzt Xenakis einige Hypothesen voraus: (1) Die Werte für die Geschwindigkeit v seien nach der Gausschen Verteilung zufällig verteilt. Somit ist v für alle Register (oder Anfangstonhöhe) gleich wahrscheinlich, es herrscht somit (2) Isotropie von Auf- und Abwärtsbewegung. (3) Für eine Sequenz aus solchen Glissandi ist die Dichte der Glissandoereignisse konstant (vgl. Baltensperger, 1996, S. 451–453; vgl. Xenakis, 1992, S. 32–33). Die so formalisierten Glissandi lassen sich durch Funktionen der Wahrscheinlichkeit berechnen, indem ∆f sowie ∆t um einen Durchschnittswert verteilt zufällig bestimmt werden. Dies bedeutet: Je größer die Abweichung einer Geschwindigkeit v vom Durchnittswert v ist, desto unwahrscheinlicher ist ihr Vorkommen.

Random Walks in Xenakis´ Instrumentalmusik

Nachdem Xenakis die theoretische Basis für die klangliche Gestaltung von Zeitabschnitten durch stochastische Methoden gelegt hatte, musste er zur Kenntnis nehmen, dass es ihm aus Gründen der beschränkten Möglichkeiten der Computertechnologie zunächst nicht möglich war, die neue Methode in der elektroakustischen Musik anzuwenden.

Wohl auch, um den Ansatz weiterverfolgen zu können, übertrug Xenakis ihn auf die Instrumentalmusik. Diesen Transfer zu vollziehen, ist kein komplizierter Prozess. Das einzige, was Xenakis bei den stochastisch erzeugten Kurven, die zunächst den Verlauf des Schalldrucks angaben, ändern musste, waren die Koordinatenachsen:

Reflektierende Grenzen

Im Vorwort zu N’SHIMA schreibt Xenakis, dass die dem Werk zugrunde liegenden Random Walks mit „elastischen“ Grenzen versehen seien (1976a). In seinem Artikel New Proposals in Microsound Structure formuliert Xenakis etwas aufschlussreicher (1992, S. 247):

Method 4. The random variable moves between two reflecting (elastic) barriers. Example: If we have a Wiener-Lévy process with two reflecting barriers a a>0 and zero, the the densitiy of this random walk will be […].

Die elastischen Grenzen werden an dieser Stelle als reflektierende Grenzen der Zufallsbewegung präzisiert. Jeder Schritt, der

über die definierte Grenze hinausgeht, wird in seinem Vorzeichen invertiert und somit in die umgekehrte Richtung reflektiert. In den Kontext der musikalischen Realisierung der Zufallsbewegung gebracht, bedeutet dies, dass die Tonhöhe zwei festgelegte Grenzen nicht unter- beziehungsweise überschreiten kann – der erreichbare Ambitus wird durch die reflektierenden Grenzen also eingeschränkt. Dies kann von Xenakis genutzt werden, um einzelne Stimmen im Register voneinander zu trennen, oder um zu gewährleisten, dass der spielbare Bereich eines Instruments nicht überschritten wird.

Baltensperger, André (1996). Iannis Xenakis und die stochastische Musik: Komposition im Spannungsfeld von Architektur und Mathematik. Bern: Verlag Paul Haupt.

Sluchin, Benny (2010). Performing Xenakis on Brass. In: Sharon Kanach (Hg.). The Iannis Xenakis Series No. 2. Performing Xenakis.(S. 11-24). New York: Pendragon Press.

Xenaksi, Iannis (1992). Formalized Music. Thought and Mathematics in Composition. Stuyvesant, NY: Pendragon Press.

Xenakis, Iannis (1976a). N’Shima. Paris: Éditions Salabert.


// ------------------------------------------------
// Random Walk Studio
// by Andreas Pirchner, 2014
// Processing
// ------------------------------------------------
import controlP5.*;
import com.nootropic.processing.layers.*;
ControlP5 cp5;
AppletLayers layers;
Slider abc, durationSlider, durationSlider2, intervallSlider, intervallSlider2;
DropdownList dropListBorder, dropListDuration, dropListIntervall;
Textlabel labelBorder, labelDuration, labelIntervalls;

float pXold;
float pYold;

float ursprung = 300;
int dauerMin;
int dauerMax;
float borderRange;
float borderTop;
float borderBottom;//100;
float borderFunction = 0;
float durationProbability = 0;
float intervallProbability = 0;
float randomProbability = 0;
float randomIntervall = 0;

int intervall;
int intervallMin;
int intervallMax;

int screenWidth = 1000;
int screenHeight = 600;

float duration;
float durationParam2;

float pX = 0;
float pY = ursprung;

float sinX = 0;
float sinY = 0;

color whiteBox = color(255, 255, 255, 20);

void setup() {
size(screenWidth, screenHeight);
smooth();
frameRate(60);
background(255);

// Setup layers for RW-borders and interface
layers = new AppletLayers(this);
layers.addLayer(new BorderLayer(this));
layers.addLayer(new InterfaceLayer(this));
}

void draw() {
if (borderFunction == 0) {
borderTop = ursprung-borderRange;
borderBottom = ursprung+borderRange;
}
if (borderFunction == 1) {

borderTop = ursprung-100-(50 * sin(sinX));
borderBottom = ursprung+100+(50 * sin(sinX));
sinX = sinX + 0.03;
}
if (durationProbability == 0) {
randomProbability = random(0, 1)*duration;
}
if (durationProbability == 1) {
randomProbability = -(log(random(0, 1))/duration);
}
if (durationProbability == 2) {
//durationSlider.setLabel("Lageparameter alpha");
float zufall = random(0, 1);
randomProbability = durationParam2 + duration * log(zufall / (1-zufall));
}

if (intervallProbability == 0) {
randomIntervall = random(-0.5, 0.5)*intervall;
}
if (intervallProbability == 2) {
float zufall = random(0, 1);
randomIntervall = 0 + intervall * log(zufall / (1-zufall));
;
println(randomIntervall);
}

pXold = pX;
pYold = pY;
if (pX < width) {
stroke(0, 150);
//pX = pX+random(1,duration);
pX = pX+randomProbability;
//pY = pY+random(-intervall, +intervall);
pY = pY+randomIntervall;
if (pY>borderBottom) {
pY = borderBottom-(pY-borderBottom);
}
if (pY<borderTop) {
pY = borderTop-(pY-borderTop);
}
line(pXold, pYold, pX, pY);
}
else {
pX = 0;
pY = ursprung;
noStroke();
fill(255);
rect(0, 0, screenWidth, screenHeight);
}
}

void paint(java.awt.Graphics g) {
// This method MUST be present in your sketch for layers to be rendered!
if (layers != null) {
layers.paint(this);
}
else {
super.paint(g);
}
}

void controlEvent(ControlEvent theEvent) {
//println(theEvent.getGroup().getValue());
if (theEvent.isGroup()) {
if (theEvent.getGroup() == dropListBorder) {
borderFunction = theEvent.getGroup().getValue();
}
if (theEvent.getGroup() == dropListDuration) {
durationProbability = theEvent.getGroup().getValue();
if (durationProbability == 0) {
noStroke();
fill(255);
rect(0, 0, screenWidth, 150);
//durationSlider.hide();
durationSlider.setRange(1, 60);
durationSlider.setValue(20);
durationSlider.setLabel("Range");
durationSlider2.hide();
}
if (durationProbability == 1) {
noStroke();
fill(255);
rect(0, 0, screenWidth, 150);
durationSlider.show();
durationSlider.setRange(0.01, 2);
durationSlider.setValue(1);
durationSlider.setLabel("Lamda");
durationSlider2.hide();
}
if (durationProbability == 2) {
noStroke();
fill(255);
rect(0, 0, screenWidth, 150);
durationSlider.show();
durationSlider.setRange(1, 30);
durationSlider.setValue(10);
durationSlider.setLabel("Alpha Lage");
durationSlider2.show();
durationSlider2.setValue(10);
durationSlider2.setLabel("Beta Scaling");
}
}
if (theEvent.getGroup() == dropListIntervall) {
intervallProbability = theEvent.getGroup().getValue();
if (intervallProbability == 0) {
intervallSlider.setRange(1, 300);
intervallSlider.setValue(100);
intervallSlider.setLabel("Range");
}
if (intervallProbability == 1) {
intervallSlider.setRange(0.01, 2);
intervallSlider.setValue(1);
intervallSlider.setLabel("Lamda");
}
if (intervallProbability == 2) {
intervallSlider.setRange(1, 30);
intervallSlider.setValue(10);
intervallSlider.setLabel("Scaling");
intervallSlider2.hide();
}
}
//println("event from group : "+theEvent.getGroup().getValue()+" from "+theEvent.getGroup());
}
}