0

I'm trying to use processing to take an audio input and create a audio spectrum that is broken into multiple rows and fits uniformly to the width of the sketch. I want the ellipse to be spread out in a grid like fashion and also represent different parts of the spectrum.

import ddf.minim.analysis.*;
import ddf.minim.*;

Minim minim;
FFT fft;
AudioInput mic;

void setup()
{
  size(512, 512, P3D); 
  minim = new Minim(this);  
  mic = minim.getLineIn();
  fft = new FFT(mic.bufferSize(), mic.sampleRate());
}

void draw()
{
  background(0);
  stroke(255);
  fft.forward(mic.mix);
  for(int i = 0; i < fft.specSize(); i++)
  {
    float size = fft.getBand(i);
    float x = map(i, 0, fft.specSize(), 0, height);
    float y = i;
    ellipse(x, y, size, size );

  }
}

1 Answers1

0

The fft data is a 1D signal and you want to visualise the data as a 2D grid.

If you know how many rows and columns you want your grid to have you can use arithmetic to calculate the x and y grid location base on the index.

Let's say you have 100 elements and you want to display them in a 10x10 grid:

use the 1D array counter and modulo (%) the number of columns to calculate the 2D x index and divide (/) by the number of columns to calculate the 2D y index:

for(int i = 0 ; i < 100; i++){
   println(i,i % 10, i / 10);
}

here's a longer commented example:

// fft data placeholder
float[] values = new float[100];
// fill with 100 random values
for(int i = 0 ; i < values.length; i++){
  values[i] = random(0.0,1.0);
}
// how many rows/cols
int rows = 10;
int cols = 10;
// how large will a grid element be (including spacing)
float widthPerSquare = (width / cols);

// grid elements offset from top left
float offsetX = widthPerSquare * 0.5;
float offsetY = widthPerSquare * 0.5;

noStroke();
smooth();

println("i,gridX,gridY,value");
// traverse data
for(int i = 0; i < 100; i++){
  // calculate x,y indices
  int gridX = i % rows;
  int gridY = i / rows;

  println(i+","+gridX+","+gridY+","+values[i]);
  // calculate on screen x,y position based on grid element size 
  float x = offsetX + (gridX * widthPerSquare);
  float y = offsetY + (gridY * widthPerSquare);

  // set the size to only be 75% of the grid element (to leave some spacing)
  float size = values[i] * widthPerSquare * 0.75;

  //fill(values[i] * 255);
  ellipse(x,y,size,size);
}

In your case, let's say fft.specSize() is around 512 and you want to draw a square grid, you could do something like this:

import ddf.minim.analysis.*;
import ddf.minim.*;

Minim minim;
FFT fft;
AudioInput mic;

int rows;
int cols;

float xSpacing;
float ySpacing;

void setup()
{
  size(512, 512, P3D);
  noStroke();

  minim = new Minim(this);  
  mic = minim.getLineIn();
  fft = new FFT(mic.bufferSize(), mic.sampleRate());

  // define your own grid size or use an estimation based on square root of your FFT data
  rows = cols = (int)sqrt(fft.specSize());
  println(rows,rows * rows);
  xSpacing = width / cols;
  ySpacing = height / rows;
}

void draw()
{
  background(0);

  fft.forward(mic.mix);

  for(int i = 0; i < fft.specSize(); i++)
  {
    float size = fft.getBand(i) * 90;

    float x = (i % rows) * xSpacing;
    float y = (i / rows) * ySpacing;

    ellipse(x, y, size, size );

  }
}

Notice that the example isn't applying the offset and the grid is 22 x 22 (484 != 512), but hopefully it will give you some ideas.

The other thing to bare in mind is the contents of that FFT array. You might want to scale that logarithmically to account for how we perceive sound. Check out Processing > Examples > Contributed Libraries > Minim > Analysis > SoundSpectrum and have a look at logAverages(). Playing minBandwidth and bandsPerOctave might help you get a nicer visualisation.

If you want to go a bit deeper into visualisation checkout this wakjah' excellent answer here and if you have time, go through Dan Ellis' amazing Music Signal Computing course

George Profenza
  • 50,687
  • 19
  • 144
  • 218
  • Thank you so much for this thorough answer. I appreciate it so much and you have helped a ton. I'll be trying this out this week. – West Rodri Dec 03 '18 at 06:10