Seamless frequency circle (FFT)

Hi all,

For the past couple of days I’ve been getting into FFT and music visualization. Wanting to make a smooth, circular display of frequencies, I managed to do that, using Minim/FFT, a linear grouping of frequencies, and by using curveVertex to make the vertices around the circle. There is one problem, however, which is that the closing of the circle becomes a straight line instead of a curve, which looks quite off. Here’s what I have so far:

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

Minim minim;
AudioPlayer jingle;
FFT fftLin;

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

minim = new Minim(this);
jingle.loop();
fftLin = new FFT( jingle.bufferSize(), jingle.sampleRate() );
fftLin.linAverages( 32 );
}

void draw()
{
background(0);
noFill();
stroke(255);
strokeWeight(3);
translate(width / 2, height / 2);

fftLin.forward(jingle.mix);

beginShape();

for (int i = 0; i < fftLin.avgSize(); i++)
{
float angle = map(i, 0, fftLin.avgSize(), 0, 7);
float amp = fftLin.getAvg(i);
float r = map(amp, 0.2, 2, 150, 200);
float x = r * cos(angle);
float y = r * sin(angle);
curveVertex(x, y);
if (i < 26) {
} else {
}
}

endShape(CLOSE);
}

``````

I am aware that properly closing curveVertex shapes is a quite common issue and I’ve read every single thread I could find about it, trying to get a grasp of how to fix it - but so far, to no avail. The only proper, complete way I came across, was in this thread by @jeremydouglass : https://github.com/processing/processing/issues/5962

I managed to adapt that piece of code into my own project, and it actually closes the circle in a smooth way, but all the vertices only keep increasing in size intead of “resetting” as with my solution above, to the point where the whole circle exceeds the frame.

I would be very grateful for any help! Thanks.

1 Like

@jeremydouglass’ code from the thread linked above - and so far the only succesful attempt I’ve seen at making an organic shape with curveVertex that closes correctly:

``````/**
* Closed curveVertex
* 2019-12-17 Jeremy Douglass -- Processing 3.4
* https://github.com/processing/processing/issues/5962
*/
ArrayList<PVector> vecs = new ArrayList<PVector>();
int segs = 50;

void setup() {
size(400, 400);
randomSeed(1);
// populate closed curve points
for (int i=0; i<segs; i++) {
PVector v = new PVector(random(120, 180), 0);
v.rotate(i/(float)segs * TWO_PI);
}
}

void draw() {
background(192);
translate(width/2, height/2);
line(0, 0, width/2, 0); // indicator line for wrap-around

// draw shape
beginShape();
for (int i=0; i<vecs.size()+3; i++) {  // wrap around +3
PVector v = vecs.get(i%vecs.size()); // wrap around
curveVertex(v.x, v.y);
}
endShape(CLOSE);

// animate data
for (int i=0; i<vecs.size(); i++) {
PVector v = vecs.get(i);
v.setMag(v.mag()+random(-2, 2));
}
}
``````
1 Like

not sure if this is of any use but maybe you could try a different way to update the circle points? I did a similar thing on my app but mapped the x/y values manually and held them in an array of objects Id created (my points object), it looked a bit like this (i have removed a lot of the code to try to just show bits that might be relevant)…

Update code…

``````for (int i = 0; i < waveBuffer.length; i++) {

offset = PApplet.map(waveBuffer[i], -1, 1, -workingWidth / localHeight, workingWidth / localHeight);
angle = PApplet.map(i, 0, waveBuffer.length * 2, 0, PConstants.TWO_PI);

points.get(i).location.x = (float) (((workingWidth - workingWidth * 0.1) + offset) * PApplet.cos(angle));
points.get(i).location.y = (float) (((workingWidth - workingWidth * 0.1) + offset) * PApplet.sin(angle));
}
``````

draw code…

``````beginShape();
for (int i = 0; i < points.size() - 1; i++) {
vertex(points.get(i).location.x, points.get(i).location.y);
}
endShape(PConstants.CLOSE);
``````
1 Like

Thank you so much! While I couldn’t use your code directly, reading and understanding it made me figure out how to solve it - by updating the points with “vecs.get(i).x = r * cos(angle);”

IT WORKS!

3 Likes