import ddf.minim.analysis.*;
import ddf.minim.*;
// Declare and construct three objects
Minim minim;
AudioPlayer test;
FFT fft;
// Declare an object to define the particles' movement
FlowField flowfield;
// Declare an array to store particles
ArrayList<Particle> particles;
boolean debug = false;
void setup() {
size(1280, 720);
background(0);
// Draws all geometry with smooth (anti-aliased) edges at level two
smooth(2);
// Initialize the object
minim = new Minim(this);
// Specify that we want the audio buffers of the AudioPlayer
// to be 1024 samples long because our FFT needs to have
// a power-of-two buffer size and this is a good size.
test = minim.loadFile("final.mp3", 1024);
// Create an FFT object that has a time-domain buffer
// the same size as test's sample buffer
// Note that this needs to be a power of two
// and that it means the size of the spectrum will be half as large.
fft = new FFT(test.bufferSize(), test.sampleRate());
// Loop the song
test.loop();
// Initialize and call the object
flowfield = new FlowField(10);
flowfield.update();
// Initialize the array and store the particles
particles = new ArrayList<Particle>();
for (int i = 0; i < 10000; i++) {
PVector start = new PVector(random(width), random(height));
particles.add(new Particle(start, random(2, 8)));
}
}
void draw() {
// Perform a forward FFT on the samples in test's mix buffer,
// which contains the mix of both the left and right channels of the file
fft.forward(test.mix);
// Call the update function of the movement
flowfield.update();
if (debug) flowfield.display();
// Draw and munipulate the movement of particles
for (Particle p : particles) {
p.follow(flowfield);
p.run();
}
}
// Declare a particle class
public class Particle {
// Set position, velocity and acceleration
PVector pos;
PVector vel;
PVector acc;
// Declare an variable to store the previous position
PVector previousPos;
// Declare an variable as maximum speed
float maxSpeed;
// Store the information of the particles
Particle(PVector start, float maxspeed) {
maxSpeed = maxspeed;
pos = start;
vel = new PVector(0, 0);
acc = new PVector(0, 0);
previousPos = pos.copy();
}
// Define the movment of the particles
void run() {
update();
edges();
show();
}
// The update movement of the particles
void update() {
pos.add(vel);
vel.limit(maxSpeed);
vel.add(acc);
acc.mult(0);
}
// Apply the force to the particles
void applyForce(PVector force) {
acc.add(force);
}
// Display the particles
void show() {
// Re-maps the variables according to the amplitude of the requested frequency band 7
float alpha = map(fft.getBand(7), 0, 100, 30, 255);
stroke(255, alpha);
strokeWeight(0.5);
line(pos.x, pos.y, previousPos.x, previousPos.y);
//point(pos.x, pos.y);
updatePreviousPos();
}
// Set the edges of the particles avoiding overflow
void edges() {
if (pos.x > width) {
pos.x = 0;
updatePreviousPos();
}
if (pos.x < 0) {
pos.x = width;
updatePreviousPos();
}
if (pos.y > height) {
pos.y = 0;
updatePreviousPos();
}
if (pos.y < 0) {
pos.y = height;
updatePreviousPos();
}
}
// Update previous position of the articles
void updatePreviousPos() {
this.previousPos.x = pos.x;
this.previousPos.y = pos.y;
}
// The position of each particle
void follow(FlowField flowfield) {
int x = floor(pos.x / flowfield.scl);
int y = floor(pos.y / flowfield.scl);
int index = x + y * flowfield.cols;
PVector force = flowfield.vectors[index];
applyForce(force);
}
}
// Declare a movement class
public class FlowField {
// Declare an array as position of movement
PVector[] vectors;
int cols, rows;
// Declare variables to control the increment of movement
float inc = 0.1;
float zoff = 0;
// Declare the unit of the grid
int scl;
// Process each unit and place them in the array
FlowField(int res) {
scl = res;
cols = floor(width / res) + 1;
rows = floor(height / res) + 1;
vectors = new PVector[cols * rows];
}
// Update the movement
void update() {
float xoff = 0;
for (int y = 0; y < rows; y++) {
float yoff = 0;
for (int x = 0; x < cols; x++) {
float angle = noise(xoff, yoff, zoff) * TWO_PI * 4;
PVector v = PVector.fromAngle(angle);
v.setMag(1);
int index = x + y * cols;
vectors[index] = v;
xoff += inc;
}
yoff += inc;
}
zoff += 0.004;
}
// Display the particles
void display() {
for (int y = 0; y < rows; y++) {
for (int x = 0; x < cols; x++) {
int index = x + y * cols;
PVector v = vectors[index];
float alpha = map(fft.getBand(7), 0, 100, 0, 255);
stroke(255, alpha);
strokeWeight(0.1);
pushMatrix();
translate(x * scl, y * scl);
rotate(v.heading());
line(0, 0, scl, 0);
popMatrix();
}
}
}
}