Basic Electroacoustics II: Music-Making Systems

Music G6602Y
TueThu 3:10-5:00pm
Spring 2008
Professor: Douglas Repetto [douglas at music columbia edu]
TA: Victor Adan [vga2102 at columbia edu]
Our Motto: "Why and how."
syllabus | lectures




February 5

Text Score Homework Presentations

Wherein we perform our text score masterworks.

Generative Art

Reading: "What is generative art?" by Philip Galanter

Now that we've figured out what an algorithm is, we're going to spend the rest of the term looking at ways that artists have used algorithms/systems/processes in their work.

We'll use Philip Galanter's paper as a starting point. "Generative Art" is a currently popular catch-all name for art made via some sort of system. It's a convenient phrase that we'll use to replace the awkward batch of slashes (algorithm/system/process) we've been using. Galanter's definition is:

Generative art refers to any art practice where the artist uses a system, such as a set of natural language rules, a computer program, a machine, or other procedural invention, which is set into motion with some degree of autonomy contributing to or resulting in a completed work of art.
Another definition by Adrian Ward:

Generative art is a term given to work which stems from concentrating on the processes involved in producing an artwork, usually (although not strictly) automated by the use of a machine or computer, or by using mathematic or pragmatic instructions to define the rules by which such artworks are executed.

Those are pretty broad definitions! It's important to note that we're not talking about aesthetics, style, genre, or any other content-based quality of the work here. It's not hard to find generative work in virtually any style or genre, from pure pop (where "formulaic" is an oft-heard criticism!) to EXTREMENOISETERROR!!! The point we're interested in here is that in one way or another all of artists we'll be talking about have choosen to use the output of some system as an integral part of their work.

Some listening & looking:

tmema/blonk/la barbara: messa di voce -- speech sounds drive live visualizations

Douglas Repetto: Happiness Too, Is Inevitable. -- environmental sensors drive live sound and image

Amy Alexander & Peter Traub: Netsong -- singing the results of web searches

Jason Freeman: iTSM -- creates a "signature" soundfile based on your listening habits

Jason Van Anden: BubbleBeats -- sample-based online graphical/algorithmic composition environment

Camille Utterback & Romy Achituv: Text Rain -- simulated physics from an imaginary world

Daniel Rozin: mirrors!

Brad Garton: My Music Book -- a book with a generative soundtrack

Adam Parrish: frotzophone -- sonification & visualization of the path through a game of Zork.

Rules of Thumb


some generative art resources:

http://www.generative.net and the eu-gene mailing list have become an online focal point of Generative Art discussion.

runme.org is a software art repository. Although all software art isn't generative, much of it is, and runme.org has a definite generative slant.

Philip Galanter has a nice collection of generative art links and a bibliography.

And of course the Processing Exhibition website is full of generative works.


More processing basics

* for-loop tricks and tips

* for loops can go backwards, start at any point, bail out in the middle, increment by an arbitrary factor, and so on.
for (int numRedBalloons = 99; numRedBalloons > 0; numRedBalloons--)
    println(numRedBalloons + " red balloons go by");
println("das ist alles.");

boolean contactMade = false;
for (int spiritContactAttemptNum = 0; spiritContactAttemptNum < 100; spiritContactAttemptNum++)
{
    float spiritNum = random(1.0);
 
    print("attempt number " + spiritContactAttemptNum + ": " + spiritNum + " ");
 
    if (spiritNum == 0.5)
    {
        println();
        println("we did it after " + spiritContactAttemptNum + " tries!");
        contactMade = true;
        //the break statement will pop us out of the for loop!
        break;
    }

}
println();
if (contactMade)
    println("see, I told you it was possible.");
else
    println("you didn't believe hard enough.");


float pi = 3.14159;
float limit = pi * pi;

for (float i = 3.14159; i < limit; i += random(1.0))
{
    println("i: " + i);

}
* for loops can contain other for loops (or anything else, for that matter)
println("weird graphic score:");
println();
for (int i = 0; i < 5; i++)
{
  print("$");
  for (int j = 0; j < 5; j++)
  {
    print(":");
    for (int k = 0; k < 5; k++)
    {
      print("^");
      for (int m = 0; m < 5; m++)
      {
        float play = random(1.0);
        if (play > 0.5)
          print("X");
        else
          print(" ");      
      }
    } 
  }
  println();
}
* while loops
* while loops make more sense than for loops in certain situations

// a strange horse race

//note the use of variables width, height, length -- this makes it 
//easy to change the number of riders, width/height of screen, etc.

size(1000,500);
PFont fonty = loadFont("AmericanTypewriter-48.vlw");
textFont(fonty, 24);

int[] xPositions = {0,0,0,0};
int numRiders = xPositions.length;
int leadingX = 0;
int heightOffset = int(height/numRiders);
println("heightOffset: " + heightOffset);

//draw finish line
line(width - 100, 0, width - 100, height);
  
//check to see if anyone has crossed the finish line yet...
while (xPositions[leadingX] < width - 100)
{
  for (int rider = 0; rider < numRiders; rider++)
  {
    //move each rider ahead by a bit
    xPositions[rider] += int(random(5.0));
    
    //see if we have a new leader
    if (xPositions[rider] >= xPositions[leadingX])
      leadingX = rider;
    
    //draw our position
    int yStart = heightOffset * rider;
    line(xPositions[rider], yStart, xPositions[rider], yStart + heightOffset);
  }
}

fill(0);
//add 5 pixels to move us away from last line drawn
int textX = xPositions[leadingX] + 5;
//put us in the middle of the winning rider
int textY = (heightOffset * leadingX) + (heightOffset/2);
print("leadingX: " + leadingX + " textX: " + textX + " textY: " + textY);
//draw winner text
text( "winner!", textX, textY);

* Processing's event loop structure
More sophisticated programs will use Processing's event loop structure. Using the event loop allows you to create programs that unfold over time.
* setup() -- first thing called in the program. Use to set up global variables, initialize screen size, colors, frame rate, etc.

* draw() -- the event loop. Gets called over and over and over and over and over. It's like an infinite while() loop.

* use noloop()/loop()/redraw()/etc to control your app with simple clicks
http://www.processing.org/learning/basics/index.html

* use frameRate() to set the looping speed inside of draw() in frames per second
It's best to set frameRate() inside of setup().

The horse race again, but in "real time"!

// a strange horse race, this time LIVE!!!

//note the use of variables width, height, length -- this makes it 
//easy to change the number of riders, width/height of screen, etc.

int[] xPositions = {0,0,0,0};
int numRiders = xPositions.length;
int leadingX = 0;
//we'll give this a useful value inside of setup()
int heightOffset = 0;

//NOTE: has to be void setup(), not just setup()!!!
void setup()
{
  size(1000,500);
  PFont fonty = loadFont("AmericanTypewriter-48.vlw");
  textFont(fonty, 24);
  frameRate(25);
  heightOffset = int(height/numRiders);
  println("heightOffset: " + heightOffset); 
  
  //draw finish line
  line(width - 100, 0, width - 100, height);
}

//NOTE: has to be void draw() not just draw()!!!
void draw()
{
  //check to see if anyone has crossed the finish line yet...
  if (xPositions[leadingX] >= width - 100)
  {
    fill(0);
    //add 5 pixels to move us away from last line drawn
    int textX = xPositions[leadingX] + 5;
    //put us in the middle of the winning rider
    int textY = (heightOffset * leadingX) + (heightOffset/2);
    //draw winner text
    text( "winner!", textX, textY);
    exit();
  }
  else
  {
    for (int rider = 0; rider < numRiders; rider++)
    {
      //move each rider ahead by a bit
      xPositions[rider] += int(random(5.0));

      //see if we have a new leader
      if (xPositions[rider] >= xPositions[leadingX])
        leadingX = rider;

      //draw our position
      int yStart = heightOffset * rider;
      line(xPositions[rider], yStart, xPositions[rider], yStart + heightOffset);
    }
  }
}


Your assignments:

For this Thursday: Make 30 second generative graphical piece (no sound) that's musically interesting...

For next Tuesday: Search out some generative art online. Tell us about what you've found -- what's compelling, what's silly, what they've claimed to do, what doesn't work right, what's inspiring. 10 minute presentation.