1

I'm working on an audio visualisation that's basically supposed to be a circular spectrogram. I have a graph that shows the frequency already and an arc, that evolves based on the time passed. Now I would like to fill the arc with white points based on the amplitude of each frequency, much like here: https://vimeo.com/27135957. Apparently, I need to make a PGraphics that is filled with points, which change from white to black based on the amplitude. Then I need to texture the arc with this graphic. Does anyone know how to do this?

import ddf.minim.*;
import ddf.minim.analysis.*;
import ddf.minim.effects.*;
import ddf.minim.signals.*;
import ddf.minim.spi.*;
import ddf.minim.ugens.*;

Minim minim;
AudioPlayer song;
FFT fft;
PGraphics pg;
PShape arc;

float deg = 90;
float rad = radians(deg);

void setup()
{
  size(1000, 1000);

  minim = new Minim(this);
  song = minim.loadFile("Anthology.mp3");
  song.play();

  fft = new FFT(song.bufferSize(), song.sampleRate());

  pg = createGraphics(width, height);
}

void draw()
{
  background(0);
  fft.forward(song.mix);

  for (int i = 0; i < fft.specSize(); i++)
  {
    pushMatrix();
    stroke(255);
    line(i, height, i, height - fft.getBand(i)*0.5);
    popMatrix();
    println(fft.getBand(i));

    //Map Amplitude to 0 → 255, fill with points and color them
    float brightness = map(fft.getBand(i), -1, 1, 0, 255);
    pg.beginDraw();
    pg.endDraw();

    fill(255, 255, 255,);
    noStroke();
    float evolution = radians(map(song.position(), 0, song.length(), 90, 450));
    //texture(pg);
    arc(height/2, height/2, height-100, height-100, rad, evolution, PIE);
  }
}
inzn
  • 61
  • 8

1 Answers1

0

There are few concepts that appear unclear based on your code:

  1. If you plan to render the arc within the pg PGraphics instance access pg with . notation and call drawing functions in between beginDraw()/endDraw() calls. At the moment there is nothing rendered in pg and pg isn't rendered anywhere using image(). For more details see the createGraphics() reference, run the sample code/ tweak it/ break it/fix it/understand it
  2. Similarly PShape arc is created but is not used
  3. There is a commented attempt to use pg as a texture however the texture mapping is unclear

If using both PGraphics and PShape is confusing you can achieve a similar effect with PGraphics alone: simply render some larger gray dots instead of arcs. It won't be an identical effect but it will have a very similar look with less effort.

Here's a variant based on your code:

import ddf.minim.*;
import ddf.minim.analysis.*;
import ddf.minim.effects.*;
import ddf.minim.signals.*;
import ddf.minim.spi.*;
import ddf.minim.ugens.*;

Minim minim;
AudioPlayer song;
FFT fft;

PGraphics pg;

void setup()
{
  size(600, 600, P2D);

  minim = new Minim(this);
  song = minim.loadFile("jingle.mp3", 1024);
  song.loop();

  fft = new FFT(song.bufferSize(), song.sampleRate());
  // optional: use logarithmic averages: clover to how we perceive sound
  fft.logAverages( 30, 6 );
  // setup pg graphics layer disable fill, make points stroke thick
  pg = createGraphics(width, height);
  pg.beginDraw();
  pg.strokeWeight(3);
  pg.noFill();
  pg.endDraw();
}

void draw()
{
  background(0);
  image(pg, 0, 0);
  // perform FFT on stereo mix
  fft.forward(song.mix);
  // center coordinates
  float cx = width * 0.5;
  float cy = height * 0.5;
  // count FFT bins
  int fftSpecSize = fft.specSize();
  // calculate the visual size for representing an FFT bin
  float sizePerSpec = (height * 0.5 ) / fftSpecSize;

  stroke(255);
  noFill();

  // start @editing@ the pg layer (once
  pg.beginDraw();

  // start the FFT graph shape
  beginShape();

  // for each FFT bin
  for (int i = 0; i < fftSpecSize; i++)
  {
    // get the vands in reverse order (low frequencies last)
    float fftBand = fft.getBand(fftSpecSize - i - 1);
    // scale FFT bin value to pixel/render size
    float xOffset = fftBand * 10;
    // map FFT bins to 0-255 brightness levels (note 35 may differ 
    float brightness = map(fftBand, 0, 35, 0, 255);

    // draw the line graph vertex
    vertex(cx + xOffset, cy + sizePerSpec * i);
    // map song position (millis played) to 360 degrees in radians (2 * PI)
    // add HALF_PI (90 degrees) because  0 degrees points to the right and drawing should start pointing down (not right)
    //float angle = map(song.position(), 0, song.length(), 0, TWO_PI) + HALF_PI;
    // as a test map it to a lower value
    float angle = (frameCount * 0.0025) + HALF_PI;
    // map radius from FFT index
    float radius = map(i, 0, fftSpecSize - 1, 0, width * 0.5);
    // use mapped brightness as point stroke 
    pg.stroke(brightness);
    // use polar coordinates mapped from the centre
    pg.pushMatrix();
    pg.translate(cx,cy);
    pg.rotate(angle);
    pg.point(radius,0);
    pg.popMatrix();
    // alternatively use polar to cartesian coordinate conversion
    // x = cos(angle) * radius
    // y = sin((angle) * radius
    // cx, cy are added to offset from center
    //pg.point(cx + (cos(angle) * radius),
    //         cy + (sin(angle) * radius));
  }
  // finish FFT graph line
  endShape();
  // fnish pg layer
  pg.endDraw();
}

Note

  • you may want to change jingle.mp3 to your audio file name
  • for the sake of a test with a short track I used an arbitrary mapping of the angle (same as evolution in your code): there is a commented version that takes the track duration into account
  • the grayscale point position is rendered using coordinate transformations. Be sure to go through the 2D Transformations tutorial and bare in mind the order of transformations is important. Alternatively there is a versioon that does the same using the polar (angle/radius) to cartesian (x,y) coordinate system transformation formula instead.

FFT line plot verticall drawn leaving grayscale trails rotating clockwise as a radial spectrogram

P.S. I also wondered how to get nice visuals based on FFT data and with a few filtering tricks results can be nice. I recommend also checking out wakjah's answer here.

George Profenza
  • 50,687
  • 19
  • 144
  • 218