T.E.T. workshop in Taipei 27th Nov, 2010

This workshop is lead by Sadam Fujioka and Hiroshi Matoba.

Step 0: Download Processing

Before start, visit Processing Official Website and download the newest Processing.

Step 1: Let's coding!!

Let's coding!!


// Initial function
void setup(){
  // Functions written here will be called once.
}

// Loop function
void draw(){
  // functions written here will be called repeatedly.
}
When you coding on Processing, you use mainly 2 functions.


download the source code: TET001.zip

Step 2: Use the initial function.

OK, use the initial function.


void setup(){
  size(1024, 768, P2D); // set the window size 1024x768
  background(255, 0, 0); // set the color of background as red.
  frameRate(60); // set the framerate that decides how many times draw() function will be called per second.
  rectMode(CENTER); // set the basic point of rect as center.
  rect(150, 150, 100, 100); // draw 100x100 sized rect on (150, 150).
}

// Loop function
void draw(){
  // functions written here will be called repeatedly.
}
We have 4 functions inside the setup function, and now you can get 100x100 sized rect drawing on 1024x768 sized red window.


download the source code: TET002.zip

Step 3: Use the loop function.

Next, the loop function.


// Initial function
void setup(){
  size(1024, 768, P2D);
  background(255, 0, 0);
  frameRate(60);
  rectMode(CENTER); // set the basic point of rect as center.
  rect(150, 150, 100, 100); // draw 100x100 sized rect on (50, 50).
}

// Loop function
void draw(){
  noStroke(); // do not draw stroke of the object below this.
  fill(0, mouseX, mouseY); // fill the object below this.
  rect(mouseX, mouseY, 100, 100); // draw 100x100 sized rect on the mouse position.
}
We have 3 functions inside the loop function, and now you get many rects drawn on your mouse position.


download the source code: TET003.zip

Step 4: Use a variable.

If you want to use the same value for different functions, you'd better to use variable.


int var; // this is a variable. imagine this is a box named "var" and this box can accept only a "int" type value.

// Initial function
void setup(){
  size(1024, 768, P2D);
  background(255, 0, 0);
  var = 60; // this means put the value of 60 into var. (assignment) watch out this doesn't mean "equal".
  frameRate(var); // use variable. this means frameRate(60).
  rectMode(CENTER);
}

// Loop function
void draw(){
  noStroke();
  fill(0, mouseX, mouseY);
  
  background(0); // draw whole screen as black.
  rect(var, mouseY, 100, 100); // draw 100x100 sized rect on (60, mouseY).
  ellipse(mouseX, var, 100, 100); // draw 100x100 sized rect on (60, mouseY).
}
In this case, you use "var" variable for deciding frame rate and the position of figures, both values are 60.


download the source code: TET004.zip

Step 5: Understand "if statement".

Use "if statement" for conditional branch.


int var;

// Initial function
void setup(){
  size(1024, 768, P2D);
  background(255, 0, 0);
  var = 60;
  frameRate(var);
  rectMode(CENTER);
}

// Loop function
void draw(){
  background(0);
  
  if(mousePressed == true){ // if mouse is pressed ("==" means "equal")
    noStroke();
    fill(0, mouseX, mouseY);
  } else { // else (if mouse is not pressed)
    stroke(0, mouseX, mouseY);
    noFill();
  } // watch out that every bracket must be closed.
  
  rect(var, mouseY, 100, 100);
  ellipse(mouseX, var, 100, 100);
}
if statement is used as below.

if(condition1){
  -- statement1;
}else if(condition2){
  -- statement2;
}else{
  -- the other statement;
}
When the condition1 is true, then the program go into the bracket and excute the statement1.
And if the condition1 is false, then the program check the condition2.
If the condition2 is also false, then the program go into the last bracket and excute the other statement.



download the source code: TET005.zip

Step 6: Understand "for statement".

If you want to use the same value for different functions, you'd better to use variable.


int var;

// Initial function
void setup(){
  size(1024, 768, P2D);
  background(255, 0, 0);
  var = 60;
  frameRate(var);
  rectMode(CENTER);
}

// Loop function
void draw(){
  background(0);
  
  if(mousePressed){
    noStroke();
    fill(0, mouseX, mouseY);
  } else {
    stroke(0, mouseX, mouseY);
    noFill();
  }
  
  // repeat the process inside bracket for 5 times from i == 0 to i == 4.
  for(int i = 0; i < 5; i++){
    // draw rect at (60, mouseY), (150 + 60, mouseY), (300 + 60, mouseY)...
    rect(i * 150 + var, mouseY, 100, 100);
  }
  
  ellipse(mouseX, var, 100, 100);
}
for statement is used as below.

for (initialization; termination; increment) {
  -- statements;
}
In this case, initialization is (int i = 0), and it excutes statements while termination (i < 5) is true, and increment (i++) is done once in a repetition.
So, we got 5 rectangles (from 0 to 4). You can also use the variable "i" only inside this bracket.


download the source code: TET006.zip

Step 7: Use array.

If you want to use the same value for different functions, you'd better to use variable.


int[] var = {50, 200, 350, 500, 650}; // this is array. imagine shelf named "var" which has 5 drawers.

// Initial function
void setup(){
  size(1024, 768, P2D);
  background(255, 0, 0);
  frameRate(60);
  rectMode(CENTER);
}

// Loop function
void draw(){
  background(0);
  
  if(mousePressed){
    noStroke();
    fill(0, mouseX, mouseY);
  } else {
    stroke(0, mouseX, mouseY);
    noFill();
  }
  
  for(int i = 0; i < 5; i++){
    rect(var[i], mouseY, 100, 100); // draw rect on (50, mouseY), (200, mouseY), (350, mouseY)...
  }
  ellipse(mouseX, var[0], 100, 100); // draw ellipse on (mouseX, 50).
  ellipse(mouseX, var[3], 100, 100); // draw ellipse on (mouseX, 500).
}
If you use for statement, array would help your code to be simple.


download the source code: TET007.zip

Step 8: See the example of LoadSample.

Minim library is one of the solution for using sounds in Processing.
Processing has many example sourse codes.
You can find examples for Minim with checking File -> Examples -> Minim (Sound). Let's open the "LoadSample" example.


/**
 * Original LoadSample is coded by Damien Di Fede.
 */
import ddf.minim.*; // import the minim library.

Minim minim; // use the Minim typed variable which is named "minim".
AudioSample kick; // use the AudioSample typed variable which is named "kick".

void setup()
{
  size(512, 200, P2D);
  // always start Minim before you do anything with it
  minim = new Minim(this);
  // load BD.mp3 from the data folder, with a 2048 sample buffer
  kick = minim.loadSample("BD.mp3", 2048);
}

void draw()
{
  background(0);
  stroke(255);
  // use the mix buffer to draw the waveforms.
  // because these are MONO files, we could have used the left or right buffers and got the same data
  for (int i = 0; i < kick.bufferSize() - 1; i++)
  {
    line(i, 100 - kick.left.get(i)*50, i+1, 100 - kick.left.get(i+1)*50);
  }
}


void keyPressed()
{
  if ( key == 'k' ) kick.trigger(); // if you type 'k' and it triggers a sound of kick.
}

void stop()
{
  // always close Minim audio classes when you are done with them
  kick.close();
  minim.stop();
  
  super.stop();
}
Run this example and you can hear the sound of bass drum when you type 'k'.


If you want to ask ,"What is the number of 2048" ?
I have to tell you simply about how a sound file in your computer works.

Actually, a sound file consists of an array of numbers.

When playing a MONO sound file whose sampling rate is 44.1kHz, your computer read 44100 numbers every second.
So 2048 samples are about 0.1sec length.

If you understand this, you would also be able to understand what is going on the green part of the source code above.
It reads numbers of sample array from the begining to the end of buffer (s[0] to s[2047]), and give a line between them.



download the source code: TET008.zip

Step 9: Try to make a simple sequencer!

So, we can create the simple sequencer.


import ddf.minim.*;

Minim minim;
String samplefiles = "BD.mp3";
AudioSample kicks;
int counter = 0;

void setup(){
  size(1024, 768, P2D);
  minim = new Minim(this);
  kicks = minim.loadSample(samplefiles, 2048);
  
  frameRate(6); // set the framerate as 6.
}

void draw(){
  if(0 == counter){ // when counter == 0 (the 1st frame of every 16 frames)
    kicks.trigger(); // trigger the sound of bass drum.
    background(255, 0, 0); // draw Red
  }
  
  if(4 == counter){ // when counter == 0 (the 5th frame of every 16 frames)
    kicks.trigger();
    background(0, 255, 0); // draw Green
  }
  
  if(8 == counter){ // when counter == 0 (the 9th frame of every 16 frames)
    kicks.trigger();
    background(0, 0, 255); // draw Blue
  }
  
  // reset the counter every 16 frames.
  counter++;
  if(counter > 16){
    counter = 0;
  }
}

void stop()
{
  kicks.close();
  minim.stop();
  
  super.stop();
}
What we were doing above is,
  1. Set the framerate as 6 frames per second.
  2. Trigger sound at the first frame (counter == 0).
  3. Trigger sound at the 5th frame (counter == 4).
  4. Trigger sound at the 9th frame (counter == 8).
  5. Reset the counter every 16 frames.
"draw" function is called every frame with different value on "counter" variable.
And if the value of counter is the same as 0 or 4 or 8, then trigger the sound.



download the source code: TET009.zip