PFA:006 – Loops Continued, Sound Visualisation

Inspiration

Artists

More About the for Loop

In the previous class, we used the for loop to iterate through arrays, but you don’t always need to have an array to draw (or do) something multiple times with a for loop.

Example

This example uses local variables inside the for loop to draw multiple shapes. The index i is used to give each shape a unique location. See the code. Run the code in Processing so you can use the Tweak mode to see how changing the values influences the outcome.

  • for – Check the reference for the for loop, if you don’t remember how it works.
  • map() – Also see the map function. We use it a lot today to scale different values.

Sound Visualizer

This example uses the Sound library. So please install it using the library manager. We are going to use the following classes of the library:

  • AudioIn – Allows us to use the audio input (microphone) of the computer
  • Amplitude – Gives the amplitude of the audio input
  • FFT –  Fast Fourier Transform (FFT) analyzer for the sound input.

1st Step: Enable Audio Input and Do Simple Amplitude Analysis

The code below shows you how you can modify the example above to control the size of the ellipses using amplitude analysis from the Sound library. The sound library is not available in OpenProcessing so you need to run the code in Processing.

import processing.sound.*;

AudioIn input;
Amplitude loudness;
int num = 16;


void setup() {
  size(600, 600);
  input = new AudioIn(this, 0);
  input.start();
  loudness = new Amplitude(this);
  loudness.input(input);
}

void draw() {
  background(135, 80, 135);
  // analyze the amplitude of the audio input
  float volume = loudness.analyze();
  textAlign(LEFT);
  textSize(32);
  text("volume: " + volume, 20, 100);

  for (int i=0; i<num; i++) {
    float s = map(volume, 0.0, 1.0, 10, 50);
    float x = map(i, 0, num-1, 50, 550);
    float y = 300;

    // ellipses
    fill(0);
    ellipse(x, y, s, s);

    // text
    textAlign(CENTER);
    textSize(16);
    text(i, x, y-s);
  }
}

2nd Step: FFT

Then we can add the FFT analysis, and connect each band of the FFT to the corresponding ellipse size.

import processing.sound.*;

AudioIn input;
Amplitude loudness;
FFT fft;
int num = 16;
float[] spectrum = new float[num];

void setup() {
  size(600, 600);
  input = new AudioIn(this, 0);
  input.start();
  loudness = new Amplitude(this);
  loudness.input(input);
  fft = new FFT(this,num);
  fft.input(input);
}

void draw() {
  background(135, 80, 135);
  // analyze the amplitude of the audio input
  float volume = loudness.analyze();
  // FFT
  fft.analyze(spectrum);
  textAlign(LEFT);
  textSize(32);
  text("volume: " + volume, 20, 100);

  for (int i=0; i<num; i++) {
    float s = map(spectrum[i], 0.0, 0.4, 10, 100);
    float x = map(i, 0, num-1, 50, 550);
    float y = 300;

    // ellipses
    fill(0);
    ellipse(x, y, s, s);

    // text
    textAlign(CENTER);
    textSize(16);
    text(i, x, y-s);
  }
}

3rd Step: Add Smoothing

We didn’t do this in class, but it is something that you might want to do to make the visualization a bit more pleasing to the eye. The raw values from the FFT change really quickly, which is not always what you want for the graphics.

import processing.sound.*;

AudioIn input;
Amplitude loudness;
FFT fft;
int num = 16;
float[] spectrum = new float[num];

// the sum[] array is used to store the smoothed values 
float[] smooth = new float[num];
// how smooth you want it? smaller number-->smoother animation
float smoothingFactor = 0.2; 

void setup() {
  size(600, 600);
  input = new AudioIn(this, 0);
  input.start();
  loudness = new Amplitude(this);
  loudness.input(input);
  fft = new FFT(this,num);
  fft.input(input);
}

void draw() {
  background(135, 80, 135);
  // analyze the amplitude of the audio input
  float volume = loudness.analyze();
  // FFT
  fft.analyze(spectrum);
  textAlign(LEFT);
  textSize(32);
  text("volume: " + volume, 20, 100);

  for (int i = 0; i < num; i++) {
    // smooth the values
    smooth[i] += (spectrum[i] - smooth[i]) * smoothingFactor;
    
    float s = map(smooth[i], 0.0, 0.4, 10, 100);
    float x = map(i, 0, num-1, 50, 550);
    float y = 300;

    // ellipses
    fill(0);
    ellipse(x, y, s, s);

    // text
    textAlign(CENTER);
    textSize(16);
    text(i, x, y-s);
  }
}

Assignment: Project Proposal for Your Final Project