Coding Art Workshop

A short workshop on visuals, sound, and interaction as part of the ADAF festival 2022.

by Yu Zhang in May 2022.

About the workshop

In 2021, we published the book "Coding Art" to share experiences and useful steps around creative coding with a primarily non-technical audience: designers, artists, musicians and other creatives who deserve a very different approach to creative coding that what was available so far.

In this workshop, we follow a creative process from ideation to making and refining, and help participants make their first steps in Processing – a creative coding environment. Throughout this workshop, participants will experience hands-on how visual elements, dynamics, and audio-visual interaction are coming together. At the end, they can share their insights and feedbacks with each other. This workshop integrates “creative thinking” and “computational thinking” that leverage creatives’ prior design/art expertise, and bring the new ideas from their future practice.

Your host

An artist by training, Yu Zhang finished her PhD in 2017 on the theory and artistic practice of interactive technologies for public, large-scale installations. She approaches visual art with mixed reality installations and projections, sensor-based interactives, and computational arts. She roots her artistic intent in the symbolism of Asian traditions and transforms the artistic unpacking of drama and cultural signifiers into experiences of interactivity and connectivity that ultimately bridge artistic expression and audience experience. Yu's teaching experiences cover over ten years and a board space including traditional classrooms and design-led project-based learning activities.

Example 1: First steps with Processing

Get to know Processing by drawing different elements on a Processing canvas.


// make a canvas of 400 by 400 pixels 
size(400, 400);

// first number: x
// second number: y
// 3rd and 4th numbers are width and height

fill(255, 0, 255, 120);
stroke(255, 0, 255);
strokeWeight(10);
rect(121, 122, 123, 124);

fill(255, 255, 0, 120);
noStroke();
ellipse(120, 120, 120, 120);

// green
fill(0, 160, 0);
beginShape();
vertex(30, 20);
vertex(85, 20);
vertex(85, 75);
vertex(30, 75);
vertex(185, 75);
vertex(30, 175);
endShape(CLOSE);

// triangle, quads
translate(150, 250);
stroke(230, 100, 100);
strokeWeight(2);
curve(5, 26, 15, 26, 173, 124, 173, 261);
        

Example 2: Linear motion

How to create linear motion for basic elements in Processing.


void setup() {
  size(400,400);
  rectMode(CENTER);
}

void draw() {
  background(0);
  fill(255);
  strokeWeight(3);
  stroke(255,0,0);
  
  pushMatrix();
  translate(width/2,height/2);
  rect(0,0,20,20);
  popMatrix();
  
  pushMatrix();
  translate(0,height/4);
  rect(frameCount,0,20,20);
  popMatrix();
}
        

Example 3: Rotate elements

How to rotate two rectangles by different degrees in the center of the Processing canvas.


void setup() {
  size(400,400);
  rectMode(CENTER);
}

void draw() {
  background(255,230,230);
  translate(width/2,height/2);
  
  pushMatrix();
  fill(120);
  rotate(radians(frameCount*1.2));
  rect(0,0,20,20);
  popMatrix();
  
  pushMatrix();
  fill(120);
  rotate(-radians(frameCount*1.2));
  rect(20,20,20,20);
  popMatrix(); 
}
        

Example 4: Mouse interaction

Create interaction between mouse position and abstract elements: their position, number and colors.


void setup() {
  size(400, 400);
}

void draw() {
  //background(255);
  // dist function gives us the distance between 2 points
  // close distance --> 0, far away --> 200
  float distance = dist(width/2, height/2, mouseX, mouseY);
  fill(distance, 80, 255);
  ellipse(mouseX, mouseY, 30, 30);
}

void keyPressed() {
  if (key == 'h') {
    colorMode(HSB);
  } else {
    colorMode(RGB);
  }

  //saveFrame("beautiful_colors##.png");
}
        

Example 5: Use audio data

Gather audio data from the microphone input and draw two circles that change their size according to the ambient noise.


/**
 * Grab audio from the microphone input and draw a circle whose size
 * is determined by how loud the audio input is.
 */

import processing.sound.*;

AudioIn input;
Amplitude loudness;

void setup() {
  size(640, 360);
  
  // Create an Audio input and grab the 1st channel
  input = new AudioIn(this, 0);

  // Begin capturing the audio input
  input.start();
  // start() activates audio capture so that you can use it as
  // the input to live sound analysis, but it does NOT cause the
  // captured audio to be played back to you. if you also want the
  // microphone input to be played back to you, call
  //    input.play();
  // instead (be careful with your speaker volume, you might produce
  // painful audio feedback. best to first try it out wearing headphones!)

  // Create a new Amplitude analyzer
  loudness = new Amplitude(this);

  // Patch the input to the volume analyzer
  loudness.input(input);
}


void draw() {
  // Adjust the volume of the audio input based on mouse position
  //float inputLevel = map(mouseY, 0, height, 1.0, 0.0);
  //input.amp(inputLevel);

  // loudness.analyze() return a value between 0 and 1. To adjust
  // the scaling and mapping of an ellipse we scale from 0 to 0.5
  float volume = loudness.analyze();
  int size = int(map(volume, 0, 0.5, 1, 350));

  background(125, 255, 125);
  noStroke();
  fill(255, 0, 150);
  // fill(size,0,150);
  // We draw a circle whose size is coupled to the audio analysis
  ellipse(width/2, height/2, size, size);
  // fill(250,size,150);
  ellipse(width/2+frameCount*sin(size), height/2, size, size);
}
        

Example 6: Draw an image according to sound volume

Scale and draw an image according to the sound volume.


/**
 * Grab audio from the microphone input and draw a circle whose size
 * is determined by how loud the audio input is.
 */

import processing.sound.*;

AudioIn input;
Amplitude loudness;

PImage duck;
PImage originalDuck;

void setup() {
  size(1000, 900);
  duck = loadImage("duck.jpg");

  color white = color(255, 255, 255);

  //create new canvas has alpha channel support
  PImage newImage = createImage(duck.width, duck.height, ARGB);
  // go through every single pixel, for every single pixel,
  for (int n = 0; n < newImage.pixels.length; n++) {
    // you check if the color is white,
    if (duck.pixels[n] == white) {
      // if it is white, then you set into transparency (0),
      newImage.pixels[n] = 0;
    } else {
      // if not white, you copy the pixel from the duck image\
      newImage.pixels[n] = duck.pixels[n];
    }
  }
  imageMode(CENTER);

  originalDuck = duck;
  duck = newImage;

  // Create an Audio input and grab the 1st channel
  input = new AudioIn(this, 0);

  // Begin capturing the audio input
  input.start();
  // start() activates audio capture so that you can use it as
  // the input to live sound analysis, but it does NOT cause the
  // captured audio to be played back to you. if you also want the
  // microphone input to be played back to you, call
  //    input.play();
  // instead (be careful with your speaker volume, you might produce
  // painful audio feedback. best to first try it out wearing headphones!)

  // Create a new Amplitude analyzer
  loudness = new Amplitude(this);

  // Patch the input to the volume analyzer
  loudness.input(input);
}

void draw() {
  // Adjust the volume of the audio input based on mouse position
  //float inputLevel = map(mouseY, 0, height, 1.0, 0.0);
  //input.amp(inputLevel);

  // loudness.analyze() return a value between 0 and 1. To adjust
  // the scaling and mapping of an ellipse we scale from 0 to 0.5
  float volume = loudness.analyze();
  int size = int(map(volume, 0, 0.5, 1, 350));

  background(125, 255, 125);
  noStroke();
  fill(255, 0, 150);
  // We draw a duck whose size is coupled to the audio analysis
  image(duck, width/2, height/2, size*5, size*5);
}
        

Example 7: Drawing lots of images from sound

Use an image and duplicate it in random positions on the canvas. The sound volume controls the number of images drawn every frame.


/**
 * Grab audio from the microphone input and draw a circle whose size
 * is determined by how loud the audio input is.
 */

import processing.sound.*;

AudioIn input;
Amplitude loudness;

PImage duck;
PImage originalDuck;

void setup() {
  size(600, 600);
  background(0,0,0);
  duck = loadImage("duck.jpg");

  color white = color(255, 255, 255);

  //create new canvas has alpha channel support
  PImage newImage = createImage(duck.width, duck.height, ARGB);
  // go through every single pixel, for every single pixel,
  for (int n = 0; n < newImage.pixels.length; n++) {
    // you check if the color is white,
    if (duck.pixels[n] == white) {
      // if it is white, then you set into transparency (0),
      newImage.pixels[n] = 0;
    } else {
      // if not white, you copy the pixel from the duck image\
      newImage.pixels[n] = duck.pixels[n];
    }
  }
  imageMode(CENTER);

  originalDuck = duck;
  duck = newImage;

  // Create an Audio input and grab the 1st channel
  input = new AudioIn(this, 0);

  // Begin capturing the audio input
  input.start();
  // start() activates audio capture so that you can use it as
  // the input to live sound analysis, but it does NOT cause the
  // captured audio to be played back to you. if you also want the
  // microphone input to be played back to you, call
  //    input.play();
  // instead (be careful with your speaker volume, you might produce
  // painful audio feedback. best to first try it out wearing headphones!)

  // Create a new Amplitude analyzer
  loudness = new Amplitude(this);

  // Patch the input to the volume analyzer
  loudness.input(input);
}

void draw() {
  // only run blur every ten frames
  //if (frameCount % 10 == 0) {
   filter(BLUR, 1);
  //}

  // loudness.analyze() return a value between 0 and 1. To adjust
  // the scaling and mapping of an ellipse we scale from 0 to 0.5
  float volume = loudness.analyze();
  int number = int(map(volume, 0, 1, -2, 10));

  for (int i = 0; i < number; i++) {
    // We draw a duck at a random position in a constant size 30
    image(duck, random(0, width), random(0, height), 30, 30);
  }
}
        

Workshop feedback

It will be great to have your feedback about the workshop. Just type your thoughts below.