Creating Circular Spectrogram

can anyone help point me in a direction on how this can be done

Example: https://vimeo.com/27135957

Thanks in advance

Here’s how I’d do it.

First, get the music playing. This will probably mean opening up a Minim library example, copying the code from it, and them making sure it plays the music file I want it to play. As a bonus perk, the example will probably draw the line of loudness at various frequencies that we’ll need - it’s the line at the bottom.

Then we’ll need an off-screen PGraphics object that will be all black to start with, and will fill with brighter points from left to right over time. Basically, one column of pixels for every, say, second of music? The brightness of a pixel in the column will depend of the loudness of the frequency that row represents.

Then just use the image of that PGraphics as a texture on many polygons that make an ever-increasing arc.

Should take a few hours. But that’s me.

What have you tried? Do you have any code yet? Can we see it? What works? What doesn’t?

Here is the sketch thus far… you will need to ad an audio file of your own titles “test.mp3” to test it.

import ddf.minim.analysis.*;
import ddf.minim.*;
 
Minim minim;
AudioPlayer song;
FFT fft;
int colmax = 500;
int rowmax = 256;
int[][] sgram = new int[rowmax][colmax];
int col;
int leftedge;


void setup()
{
  size(512, 256, P3D);
  textMode(SCREEN);
 
  minim = new Minim(this);
   song = minim.loadFile("test.mp3");
  song.play();
 
  fft = new FFT(song.bufferSize(), song.sampleRate());
  fft.window(FFT.HAMMING);
}
 
void draw()
{
  background(0);
  stroke(255);
  // perform a forward FFT on the samples in the input buffer
  fft.forward(song.mix);

  for(int i = 0; i < rowmax /* fft.specSize() */; i++)
  {
    // fill in the new column of spectral values
    sgram[i][col] = (int)Math.round(Math.max(0,2*20*Math.log10(1000*fft.getBand(i))));
  }

  col = col + 1; 
 
  if (col == colmax) { col = 0; }
  
 
  for (int i = 0; i < colmax-leftedge; i++) {
    for (int j = 0; j < rowmax; j++) {
      stroke(sgram[j][i+leftedge]);
      point(i,height-j);
    }
  }
  // Draw the rest of the image as the beginning of the array (up to leftedge)
  for (int i = 0; i < leftedge; i++) {
    for (int j = 0; j < rowmax; j++) {
      stroke(sgram[j][i]);
      point(i+colmax-leftedge,height-j);
    }
  }
 
  leftedge = leftedge + 1; 

  if (leftedge == colmax) { leftedge = 0; }
}
 
 
void stop()
{
  
  song.close();
  minim.stop();
 
  super.stop();
}
2 Likes

Hey, here’s my code so far. Having trouble with the “fill with brighter points from left to right over time”-part and then of course the texturing. Would appreciate help very much!

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++)
  {
    stroke(255);
    line(i, height, i, height - fft.getBand(i)*0.5);

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

    fill(255, 255, 0);
    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);
  }
}

Did you ever manage to recreate it?

Did this ever get anywhere? I am looking to do the same but struggling to find examples to work with.

Hello,

I shared my insights in this topic:

:)

1 Like