#### Howdy, Stranger!

We are about to switch to a new forum software. Until then we have removed the registration on this forum.

# How to get an octave based frequency spectrum from the FFT in Minim

edited December 2016

I want to create audio visuals like the bars visual that is commonly used in music videos. Minim has an FFT that gets the amplitude of each frequency band, but each band is evenly spaced. So the result is that the bars are mostly showing only the high frequencies, and the mid and low frequencies are bunched up on the left. I tried this, but I'm not good with logarithms and have no clue what the correct math to calculate this should be, and it didn't really work:

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

Minim minim;
AudioPlayer song;
FFT fft;

// the number of lines/bands to draw
int bands = 512;

float a = (log(20000 - 20) / log(bands));

void setup()
{
size(512, 200);

minim = new Minim(this);

song.loop();

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

void draw()
{
background(0);
stroke(255);

fft.forward(song.mix);

for(int i = 0; i < bands; i++)
{
// calculate the frequency for the current band on a logamorithmic scale
float freq = pow(i, a) + 20;

// get the amplitude at that frequency
float amplitude = fft.getFreq(freq);

// convert the amplitude to a DB value.
// this means values will range roughly from 0 for the loudest
// bands to some negative value.
float bandDB = 20 * log(2 * amplitude / fft.timeSize());
// so then we want to map our DB value to the height of the window
// given some reasonable range
float bandHeight = map( bandDB, 0, -150, 0, height );

// draw the band as a line
line(i, height, i, bandHeight);
}
}
``````

I don't even know if it can be done using the FFT in Minim because there might not be enough bands calculated for the lower frequencies. If not, what can I use to accomplish this?

Tagged:

• There's a logaverages in minim, does that do what you want?

http://code.compartmental.net/minim/fft_method_logaverages.html

• Aha! This post answered my question:

https://forum.processing.org/two/discussion/comment/17292/#Comment_17292

My new code is:

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

Minim minim;
AudioPlayer song;
FFT fft;

// the number of bands per octave
int bandsPerOctave = 4;

// the spacing between bars
int barSpacing = 3;

void setup()
{
size(512, 200);

minim = new Minim(this);

song.loop();

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

// calculate averages based on a miminum octave width of 22 Hz
// split each octave into a number of bands
fft.logAverages(22, bandsPerOctave);

rectMode(CORNERS);
}

void draw()
{
background(0);
stroke(255);

// perform a forward FFT on the samples in song's mix buffer
fft.forward(song.mix);

// avgWidth() returns the number of frequency bands each average represents
// we'll use it as the width of our rectangles
int w = int(width/fft.avgSize());

for(int i = 0; i < fft.avgSize(); i++)
{
// get the amplitude of the frequency band
float amplitude = fft.getAvg(i);

// convert the amplitude to a DB value.
// this means values will range roughly from 0 for the loudest
// bands to some negative value.
float bandDB = 20 * log(2 * amplitude / fft.timeSize());
// so then we want to map our DB value to the height of the window
// given some reasonable range
float bandHeight = map(bandDB, 0, -150, 0, height);

// draw a rectangle for the band
rect(i*w, height, i*w + w - barSpacing, bandHeight);
}
}
``````
• I also want to mention that converting the amplitude to decibels gives a much better result for anyone else who wants to do this effect.