ofxFft: FFTW + KISS FFT wrapper

hey thanks, I deleted the previous post because I figgured it doesnt really work well. i will try zour suggestion!

Hey, has anybody got this to work under snow leopard? When i try to include the libfftw3 library (that i intsalled through darwinports), its tells me that its of the wrong architecture… Any ideas?

as i posted it at the snow leopard thread:
snow leopard is compiling everything for 64bit by default, so you have to compile it for 32bit by changing the settings. i don’t know if that works with darwinports. it didn’t work with macports. so you’ll probably have to download fftw and do it yourself.

best
joerg

ofxFftw has now been replaced by ofxFft. Download it here.

ofxFft is completely restructured. You don’t call fft() and ifft() anymore, but instead:

  
  
void setSignal(float* signal);  
void setCartesian(float* real, float* imag = NULL);  
void setPolar(float* amplitude, float* phase = NULL);  
  
int getSignalSize();  
float* getSignal();  
void clampSignal();  
  
int getBinSize();  
float* getReal();  
float* getImaginary();  
float* getAmplitude();  
float* getPhase();  
  

The idea is that you should be able to set one of the three representations (one time domain, two frequency domain) and get the other two. The respective FFTs and IFFTs are evaluated lazily/when requested. To do an FFT, you might say setSignal(), then getAmplitude(). To do an IFFT you might say setPolar() with some modified amplitude values, and then call getSignal().

Two demos are packaged with the source. One shows how to do a low-pass filter EQ by modifying the amplitude. The other shows how to build up a spectrogram image.

An important change from the versions posted earlier in this thread is that the “basic”/non-fftw implementation has been changed to KISS-FFT. KISS-FFT is BSD licensed, which offers a lot of freedom. The old code posted by Pierre isn’t packaged as well, acted weird when doing the real IFFT, and, most importantly, was ambiguously licensed (it came from a numerical recipes book, which is famously-restrictive, and was later modified and called LGPL).

In Xcode I got an error about malloc.h, but a quick-google-search gave me an answer. You change

  
#include <malloc.h>  

in kiss_fft.h to

  
#include <malloc/malloc.h>  

I’m new to C++ so I’ve got no idea how it actually works, but it compiles fine now. Hope this helps anybody!

Another fix on that thread was this:

Actually, you shouldn’t need malloc.h at all, it’s obsolete; including stdlib.h should take care of what malloc.h used to handle. Basically, just remove it, or #if it out

  
>     #if !defined(__APPLE__)  
>     #include <malloc.h>  
>     #endif  
>     

I’ve tried it and it seems to work as well.

Thanks! I’ve committed an updated version and uploaded a new download that removes the line completely, as stdlib.h should define malloc.

So deleting the line should be enough? Or should I download the new version?

Deleting the line is enough. I just posted a new revision with only that change, because it’s clearly a significant problem if it’s keeping you from compiling it in xcode!

Sweet. By the way, is there any documentation for ofxFft? If not, do you have any tips for a beginner at C++? I’m already starting to battle my way through (I’ve begun by looking at your examples), but some simple pointers would be nice. Perhaps in the future I’ll write a tutorial for other silly people like me. Something along the lines of this one: http://www.anthonymattox.com/visualizin-…-processing

I don’t have a tutorial like the link you posted… but if you can put a good one together, I’d be glad to host it and include it with the download!

The most helpful thing I can say, besides what’s written in the examples, is this:

fft libraries normally hint at the fact that “fft” is a way of saying “time-domain to frequency-domain transformation”. ofxFft skips this hint, and just says it explicitly by allowing you to set different representations of a signal: time domain, or one of two frequency domain representations. Whether an fft is being done is almost inconsequential, the important thing is that you are getting frequency information from a time domain representation, or vice versa.

Thanks Kyle for the FFT object.

How would I amplify a certain range of frequencies ?
I guess something like a EQ with bass, middle and treble control?

thanks,
stephan.

Hi Stephan!

Try the ofxFftEq demo in the examples folder.

In the code, I define eqFunction as:

  
for(int i = 0; i < fft->getBinSize(); i++)  
  eqFunction[i] = (float) (fft->getBinSize() - i) / (float) fft->getBinSize();  
  

If you just dynamically change that function, you’re set. You could try having three gaussian functions centered at low, medium, and high. Then you pick their amplitude. Then for each point, you define the eqFunction as the weighted average of those values. This technique is called the “normalized radial basis function network”:

http://en.wikipedia.org/wiki/Radial-basis-function-network

thanks for replying so fast.

i understand most of what you are suggesting

pick amplitude and averaging

but i don’t know how to center a gaussian functions at low, medium and high.
could help a newby out ?

thx,
stephan

Definitely, here is the page on gaussians:

http://en.wikipedia.org/wiki/Gaussian-function

Here is the most important part:

The parameter a is the height of the curve’s peak, b is the position of the centre of the peak, and c controls the width of the “bell”.

In other words, take the equation there (a * exp(-pow(x-b, 2)/(2*c*c))) and change b to control whether the gaussian is centered at low, mid, or high.

edit: a computationally efficient gaussian is more like this:

  
  
float gaussian(float x, float amplitude, float center, float width) {  
 float base = (x - center) / width; // divide top by bottom  
 base *= base * -.5; // square top and bottom, multiply by -1/2  
 base = exp(base); // take pow(e, base)  
 return amplitude * base;  
}  
  

Hey, I’m finally beginning to understand this somewhat! One question: is there a way of dampening the FFT to get smoother transitions? Referring back to that Processing link I posted: http://www.anthonymattox.com/visualizin-…-processing

  
myfft.damp(.3);  
  

If you mean what I think you mean by “damping”, then you can maintain a separate buffer for your “damped” FFT. Then every time you get a new FFT output, you do something like this:

  
  
float* curFft = fft->getAmplitude();  
for(int i = 0; i < fft->getBinSize(); i++)  
 dampedFft[i] = (damping) * dampedFft[i] + (1 - damping) * curFft[i];  
  

If damping = 0, then the result of dampedFft[i] will just be curFft[i]. Anything great (up to 1) will be “temporally smoothed”.

Nice - that works perfectly. So you can just use:

  
float* curFft = fft->getAmplitude();  

instead of:

  
float* curFft;  
curFft = new float[fft->getBinSize()];  
memcpy(curFft, fft->getAmplitude(), sizeof(float) * fft->getBinSize());  

Very helpful - you’re a star! :slight_smile:

Should I use ofxFft if I just use fft for spectrum analysis to make something sound-reactive, or does it make sense only if you want to actually change the sound (like in the eq example)?

fft->getBinSize() returns 257. Does that mean i have 257 frequency bands? How would I divide it to say 16 bands?

ofxFft is good for spectrum analysis when you want to make something sound reactive. There is also a built in fft function in OF that is slightly easier (depending on your coding preferences).

To get fewer bands you have two options:

1 Initialize ofxFft with a smaller signal size by passing 32 as an argument to create().

  
  
fft->create(32);  
  

This will give you 17 for your bin size, which includes both the 0 Hz (DC) component and the Nyquist frequency. In most situations you can ignore the Nyquist frequency.

2 Use the default signal size of 512, but average multiple bands together.

You can either use linearly spaced averages, where you just average together every 16 bins, or use logarithmically spaced averages. Logarithmic averages are more true to the way we actually hear things. For that you might average bins 0-1, then bins 2-3, then bins 4-6, then 7-9, etc. Getting bigger until finally the last component contains a bunch of high frequencies. A good metric for doing this division is the Bark-scale.

thanks, I’ll try the barks scale.
Is there a way to use the sound that’s currently playing on the computer as input?