Bayati Dragon

Artist Statement:
Bayati Dragon is an experimental work that integrates microtonal music with algorithmic art, employing generative design principles to create a multi-sensory experience. This piece, made in Processing, explores the intersection of sound and visual representation through the application of Lindenmayer systems (L-systems), a class of recursive formal grammars initially introduced by Aristid Lindenmayer for simulating plant growth. Here, the L-system generates a fractal-based structure inspired by the dragon curve, a self-similar geometric pattern that serves as both a visual and conceptual foundation for the work. Each iteration in the L-system's development corresponds to a note from the Bayati scale, a traditional Arabic maqam, establishing a synchronisation between the visual and auditory domains.

The visual component unfolds dynamically, with each segment of the L-system rendered in a palette of camouflage-inspired hues. This chromatic approach evokes organic complexity, mirroring the interplay between visibility and concealment. In this sense, the work aligns with broader cultural and philosophical inquiries into migration and identity, where individuals navigate the liminal space between recognition and anonymity. The adaptation of the Bayati scale further reinforces this theme, as microtonal music itself oscillates between established traditions and contemporary reinventions, reflecting a fluid negotiation between historical and emergent cultural forms (Pelé, 2007).

Sonically, the work employs a triangle wave oscillator to generate frequencies corresponding to the Samaii Bayati Qadim, a classical Arabic musical form. The composition is based on the score Samaii Bayati Qadim by Ibrahim Al-Masri (available at Arabic Musical Scores), a 10/8 Samaii piece characteristic of the maqam tradition. The triangle wave, with its distinctive timbral characteristics, approximates the resonance of plucked string instruments, thus preserving a link to traditional musical aesthetics while situating the composition within the computational domain. This synthesis of algorithmic precision and historical form underscores Pierre Barbaud’s assertion that algorithmic music enables an alternative compositional paradigm—one in which deterministic rule-based processes facilitate complex emergent structures (Barbaud, 1993).

Structurally, the piece originates from a simple axiom ("FX"), with recursive transformation rules iteratively expanding the generative sequence. The resulting command string dictates both visual and auditory outputs: directional shifts define the evolving fractal geometry while corresponding notes shape the unfolding melodic progression. Although the L-system operates within a deterministic framework, stochastic variations in colour selection introduce an element of unpredictability, evoking the dialectic between order and randomness—a tension fundamental to both algorithmic aesthetics and improvisatory musical traditions.

This project draws inspiration from the research of Haiyun Yu and Mark Reid at Microtonal Music Studios in Helsinki, a program directed by Dr Timo Tuhkanen. Their engagement with microtonality and cross-cultural sonic practices has been instrumental in shaping this experiment. Bayati Dragon serves as a preliminary study within a broader inquiry into the confluences of sound, form, and cultural expression, with the potential for further development through collaboration and expanded algorithmic strategies.

Ultimately, this work contributes to ongoing discussions at the intersection of computational creativity, musical semiotics, and cultural identity. It invites audiences to consider the generative potential of structured systems—where aesthetic forms emerge from precise yet flexible rulesets—and to reflect on the evolving dialogue between tradition and technological innovation. The recursive logic of the L-system and the layered harmonic structures of the maqam embody a shared principle: complexity arises from iteration, transformation, and reinterpretation. In this sense, Bayati Dragon is not only a visual-sonic composition but a meditation on the generative interplay between constraints and possibilities in artistic creation.

Bibliography:
Barbaud, Pierre. Vademecum de l'ingénieur en musique. Paris: Springer-Verlag, 1993.
Deshays, Daniel. De l'écriture sonore. Marseille: Entre vues, 1999.
Pelé, Gérard. Inesthétiques musicales au XXe siècle. Arts et sciences de l'art. Paris: l'Harmattan, 2007.
Xinran, and Esther Tyldesley. The Good Women of China: Hidden Voices. London: Chatto & Windus, 2002.

Audio rendering: BlackHole by Existential Audio.

 

Sheet music of Samaii Bayati Qadim by Ibrahim Al-Masri – سماعي بياتي قديم
A Classical Arabic Samaii 10/8 piece of music by Ibrahim Al-Masri.


Processing Code:

/* This code is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License (CC BY-SA 4.0).
You are free to:
- Share: Copy and redistribute the material in any medium or format.
- Adapt: Remix, transform, and build upon the material for any purpose, even commercially.
Under the following terms:
- Attribution: You must give appropriate credit, provide a link to the license, and indicate if changes were made.
- ShareAlike: If you remix, transform, or build upon the material, you must distribute your contributions under the same license as the original.
For more details, visit: https://creativecommons.org/licenses/by-sa/4.0/

Debugging assistance is provided by DeepSeek, an AI developed by DeepSeek company.

*/

import ddf.minim.*;
import ddf.minim.ugens.*;
Minim minim;
AudioOutput out;

Oscil osc1;
// Frequencies for the transposed Bayati scale (D, E-half-flat, F, G, A, B-half-flat, C, High D)

float[] bayatiScale = {
293.66f, // D
318.95f, // E-half-flat
348.02f, // F
391.54f, // G
419.40f, // A
489.34f, // B-half-flat
522.04f, // C
587.33f // High D
};

// Full note sequence for all 13 measures of Samaii Bayati Qadim

int[] noteSequence = {
0, 0, 0, 2, 3, 3, 2, 1, 0, 1, 3, 2, 0, 4, 4, 4, 3, 2, 2, 1, 0,
0, 0, 0, 2, 3, 3, 2, 1, 0, 1, 4, 2, 0, 4, 5, 4, 3, 2, 1, 0,
3, 2, 1, 0, 1, 3, 2, 0, 0, 4, 4, 5, 4, 2, 3, 0, 3, 2, 0, 4, 1,
2, 2, 3, 1, 2, 1, 0, 2, 4, 3, 2, 0, 1, 3, 2, 4,
0, 0, 4, 4, 5, 3, 4, 2, 3, 1, 0, 3, 2, 4, 3, 0, 4, 2, 1, 3,
0, 4, 5, 4, 3, 2, 1, 0, 1, 4, 2, 0, 3, 1, 2, 3, 0, 4, 4,
1, 0, 3, 2, 3, 4, 0, 1, 4, 2, 1, 0, 2, 3, 0, 5, 4, 3,
1, 2, 3, 0, 1, 4, 3, 2, 0, 1, 3, 4, 5, 4, 0,
0, 2, 4, 1, 0, 3, 2, 1, 0, 1, 4, 2, 5, 4, 0,
0, 2, 4, 1, 0, 3, 2, 1, 0, 1, 4, 2, 5, 4, 0,
1, 2, 3, 0, 4, 5, 3, 2, 0, 4, 2, 3, 1, 4, 2,
2, 3, 0, 4, 5, 3, 2, 0, 1, 3, 2, 4, 0, 5, 4, 3,
1, 2, 0, 5, 4, 3, 2, 0, 1, 3, 4, 2, 1, 0, 4
};

color[] camoColors = {
color(87, 59, 12), // Dark Brown
color(119, 134, 68), // Olive Green
color(74, 94, 49), // Dark Green
color(170, 134, 93), // Light Brown/Tan
color(42, 42, 42) // Black
};

int currentNoteIndex = 0;
int generations = 12;
int index = 0;
String axiom = "FX";
String ruleX = "X+YF+";
String ruleY = "-FX-Y";
String currentString = axiom;
float length;
float angle = 90;
float currentAngle = 0;
float x, y;
boolean playing = false;
boolean started = false;
boolean delayComplete = false;
int startTime = 0;
float stepsPerFrame;
float scaleFactor = 1.5; // Adjust this for larger or smaller lines

void setup() {
size(1280, 720); // Canvas size
background(255);
strokeWeight(2);
frameRate(45); // Reduced frame rate for smoother animation
minim = new Minim(this);
out = minim.getLineOut(Minim.STEREO); // Stereo audio
osc1 = new Oscil(0, 0, Waves.TRIANGLE);
osc1.patch(out);
for (int i = 0; i < generations; i++) {
currentString = applyRules(currentString);
}

// Dynamically calculate step size
length = calculateLength() * scaleFactor; // Apply scaling factor
stepsPerFrame = currentString.length() / (120.0 * frameRate); // Distribute steps over 2 minutes
x = width / 2;
y = height / 2;
fill(0);
textSize(32);
textAlign(CENTER, CENTER);
text("Click to Start", width / 2, height / 2);
}

void draw() {
if (playing && !delayComplete) {
if (millis() - startTime >= 10000) {
delayComplete = true;
background(255);
}
}

if (playing && delayComplete) {
for (int i = 0; i < stepsPerFrame; i++) {
if (index < currentString.length()) {
char command = currentString.charAt(index);
if (command == 'F') {
stroke(camoColors[int(random(camoColors.length))]);
float newX = x + length * cos(radians(currentAngle));
float newY = y + length * sin(radians(currentAngle));
line(x, y, newX, newY);
x = newX;
y = newY;

playPluckedNote(bayatiScale[noteSequence[currentNoteIndex]]);
currentNoteIndex = (currentNoteIndex + 1) % noteSequence.length;
} else if (command == '+') {
currentAngle += angle;
}

else if (command == '-') {
currentAngle -= angle;
}
index++;
} else {
noLoop();
stop();
}
}
}

void mousePressed() {
if (!started) {
background(255);
started = true;
playing = true;
startTime = millis();
}
}

String applyRules(String input) {
StringBuilder nextString = new StringBuilder();
for (int i = 0; i < input.length(); i++) {
char c = input.charAt(i);
if (c == 'X') {
nextString.append(ruleX);
} else if (c == 'Y') {
nextString.append(ruleY);
} else {
nextString.append(c);
}
}
return nextString.toString();
}
float calculateLength() {
float margin = 20;
float maxStep = 0;
float xTemp = width / 2, yTemp = height / 2, angleTemp = 0;
for (char command : currentString.toCharArray()) {
if (command == 'F') {
xTemp += cos(radians(angleTemp));
yTemp += sin(radians(angleTemp));
maxStep = max(maxStep, dist(width / 2, height / 2, xTemp, yTemp));
} else if (command == '+') {
angleTemp += angle;
} else if (command == '-') {
angleTemp -= angle;
}
}
return (min(width, height) / 2 - margin) / maxStep;
}

void playPluckedNote(float targetFreq) {
osc1.setFrequency(targetFreq);
osc1.setAmplitude(0.6);
delay(50);
osc1.setAmplitude(0);
}

void stop() {
out.close();
minim.stop();
super.stop();
}