Not sure how to work with Minim's FFT feature

So, this is my code:

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

Minim minim;
AudioPlayer sound;
FFT spectrum;

void setup() {
  size(600, 600);
  noStroke();
  fill(255);
  minim = new Minim(this);
  sound = minim.loadFile("untitled.mp3", 1024);
  sound.loop();
  spectrum = new FFT(sound.bufferSize(), sound.sampleRate());
}

void draw() {
  background(0);
  spectrum.forward(sound.mix);
  for (int i = 0; i < spectrum.specSize(); i++) {
    float x = map(i, 0, spectrum.specSize(), 0, width);
    //float y = map(spectrum.getBand(i), 0, ???, 0, height);
    rect(x, height, width/spectrum.specSize(), -spectrum.getBand(i));
  }
}

I’ve even uploaded the sound file online in case you wanna hear it: https://ufile.io/3encm
(It’s just a simple sine wave, rapidly ascending by musical semitones)

So, I have a ton of questions:

  1. What is the max amplitude the spectrum.getBand() method can output? I need to know it in order to finish that second map() function (which I’ve commented out). In p5.sound, it was 255. Here, I’m not so sure. A few of the values went all the way past 300.

  2. What are the specific frequencies of the 1024 analyzed portions?

  3. When I bring the number of portions down (e.g. 64), it starts lagging. Why?

  4. Why is the actual number of portions half the size plus 1 than what I’ve specified using the loadFile() function?

  5. In p5, the p5.FFT() function can take a parameter which specifies smoothing/averaging. Since my visualization is incredibly erratic, I’d like to add that. Is there a function like that in Minim that would smooth out/average the data? I want to achieve that smooth music visualizer effect that you can find in so many music videos lately.

  6. The frequencies of the portions are distributed linearly. This causes the tones from the sound file to appear rising exponentially. Is there a function that would make the analysis exponential? Music, in essence, IS exponential. When we play a linear sequence (100 Hz, 200 Hz, 300 Hz…), the sequence will appear to rise slower and slower. I’d simply like the analyzed data to be distributed more naturally.

  7. In case Minim does not have such a function, I will have to resort to an analysis of specific, hand-picked frequencies. Is there a function to get the amplitude of a specific frequency? I know that in p5.sound, it’s p5.FFT.getEnergy().

  8. The console seems to be outputting some kind of a non-sketch-breaking error. What’s that all about?

2 Likes

pls check also

i think at first you need to know more about the actual numbers…
so try the code i show later

also i not know about exact differences
between Processing 3.4 Minim
and the P5.js version,

but your comment sounds like
the p5.js version is normalizing the amplitude???
as far as i know,
a FFT gets a series of numbers and spits out
the 2* average and the amplitude of
a sinus what fits in that numbersequences
( and all harmonics. 2,3,4,5… fitting sinus. )
again,
if you give 1024 samples the result is a array of 512 +1
so, why Fourier only counts the first 512 frequencies
he could calculate more, ha? kind of lazy?

the basic idea is, if you do one measurement there is no way to
know if there are frequencies in that signal.
but if you make 2 measurements you can try to fit that to a sinus.
( even it still can be anything else, no way to know )
that is the first problem of any digitizing, sampling of analog signals.
the more samples the more you know
also that says you need min 2 samples to fit a frequency,
that is called the
https://www.tutorialspoint.com/signals_and_systems/signals_sampling_theorem.htm
turn that around and you know why FFT only do 512 sinus in 1024 samples.

and for the correlation to the sound frequencies?
again the FFT does not know frequencies, only samples
the base frequency ( one sinus in the 1024 samples ) you have to
calculate what it really means
by find out how many msecs that 1024 samples mean
that base frequency ( amplitude in fft[1] ) would be 1 / ( sec of 1024 samples )

now to make from that fft information any of that
“today” spectrum show

  • green to red color on amplitude
  • show max of it for some second then fading down…

is sure a challenging coding,
but sounds more like you looking for ready examples or “better” libraries
i would think its out there already but i don’t know

also check google tutorial videos…
Processing Tutorial #5 on Vimeo

// update:
i play little bit and got the idea that we need a common ground
so we can compare data:
i started my raspberry pi, and used the default audio program i install there

audacity

and with this i generated a 440 Hz tone “a”
and export to mp3 file
that i used in the little bit modified

code
import ddf.minim.*;
import ddf.minim.analysis.*;

//String soundfile = "untitled.mp3";
String soundfile = "the_a.mp3";

float amp =1;
float max = -1000;

Minim minim;
AudioPlayer sound;
FFT spectrum;

void setup() {
  size(600, 600);
  noStroke();
  fill(255);
  minim = new Minim(this);
  sound = minim.loadFile(soundfile,1024);
  sound.loop();
  spectrum = new FFT(sound.bufferSize(), sound.sampleRate());
  println("bufferSize() "+sound.bufferSize());
  println("sampleRate() "+sound.sampleRate());
  println("fft.specSize()"+spectrum.specSize());
}

void draw() {
  background(0);
  spectrum.forward(sound.mix);
  if ( keyPressed ) max = -1000;
  for (int i = 0; i < spectrum.specSize(); i++) {
    float x = map(i, 0, spectrum.specSize(), 0, width);
    if ( keyPressed ) if ( spectrum.getBand(i) > max ) max = spectrum.getBand(i);
    //float y = map(spectrum.getBand(i), 0, ???, 0, height);
    rect(x, height-10, width/spectrum.specSize(), -spectrum.getBand(i)*amp);
    if ( keyPressed ) if ( i < 20) print(" i: "+i+" "+nf(spectrum.getBand(i),1,1));
}
if ( keyPressed ) println("\nmax "+nf(max,1,1));
if ( keyPressed ) println("\nnext");

}

and you can get the same audio file from:

http://kll.engineering-news.org/kllfusion01/downloads/the_a.mp3

now using this shows


and press any key

the max amplitude at i=10
ha? can that be related to

sampleRate() 44100.0
and the selected frequency 440Hz

and buffersize 1024

and with buffersize 512
i find the max at i=5

1 Like

Hi! Have you seen this example? https://github.com/ddf/Minim/blob/v2.2.2/examples/Analysis/SoundSpectrum/SoundSpectrum.pde It shows how to get both linear and logarithmic average values, and includes comments that may answer some of your questions.

When you say “portions” do you mean buffer size? Lowering the buffer size lowers the latency, but also increases the CPU usage. At some point your cpu may not be fast enough to handle it. I suspect it may be Java related, as using Jack I can use lower buffer sizes than with Minim without glitches.

2 Likes