Suggestions on the shiny new FFT-Interface


#1

Hi Jules,

I just saw, that you've added an FFT class. Great! I have a few suggestions on the interface:

As you might know, Apples vDSP has FFT functions (vDSP_fft_zrip). It would be great, if JUCEs FFT class could use vDSP on OSX. But for that to work, it's neccessary to have a custom type for "container of complex". This is because vDSP is using DSPSplitComplex (in a rather strange layout).

It would also be great to have something like FloatVectorOperations that works on data in the frequency domain. This way the high-performance implementations of IPP, vDSP, FFTW, ... can be used without having to think about the data-layout that the library is using. Here's how the interface might look like (pseudo-code):

class FrequencyDomainOperations:
    void addWithMultiply(Spectrum& a, const Spectrum& b, const Spectrum& c)
    void getMagnitude(float* out, const Spectrum& s)
    void getPhase(float* out, const Spectrum& s)
    ...

It would also great, if there would be an compiler option (some time in the future) to use vDSP, IPP or FFTW as the default.

If you're interested in my wrapper implementations drop me a PM - I'm sure, we can figure something out.

-- Benjamin

PS.: Might I ask, why you aren't using std::complex? as far as I know, it's in the STL for ages. Some googling brought up some header files dating 1994 :)

 


#2

Thanks - yes, we'll optimise it at some point, but this initial release was just to get the ball rolling.

PS.: Might I ask, why you aren't using std::complex? as far as I know, it's in the STL for ages. Some googling brought up some header files dating 1994 :)

Yes, I probably could have used that (and could change it to use that with a typedef, of course). I just wasn't 100% confident that all STL versions would be packed structures of two floats (although I'm sure that's almost certainly the case). And even though I think most STLs will have included the complex class for a long time, I vaguely remember hearing that it's only officially there in C++11. (Could be wrong about that though)


#3

 

 

Yeah, big shout out for Jules on this one .... so glad to see this new class.

The scolling histogram is nice too .... great easy example for newcomers unsure what an FFT might be.

I would also recommend kissFFT - if only for it's simplicity.

 

Anyway, lots of potential uses/improvements that I'm sure will come along eventually.  Keep up the good work, senor!


#4

oooh FFT

I did some work using Apple's FFT a few years back.

http://stackoverflow.com/questions/3398753/using-the-apple-fft-and-accelerate-framework

That answer of mine links to another question: http://stackoverflow.com/questions/4633203/extracting-precise-frequencies-from-fft-bins-using-phase-change-between-frames

And in that answer I provide an algorithm for precise estimation of a peak in the spectrum by looking at the rotation speed of the bins on either side. I used this to build a pitch detection algorithm.

I could even provide code for that if Jules is interested in adding pitch detection to JUCE.

ŌÄ

PS Regarding std::complex in C++11, if I remember correctly the industry-standard is to support the current version and the previous version of a particular platform. Since C++14 is now ready, I think it would be fair to require >=  C++11.


#5

I could even provide code for that if Jules is interested in adding pitch detection to JUCE.

Sure, would be happy to take any contributions of that nature!


#6

I had a little dig around my old projects and found https://gist.github.com/p-i-/d835bb6e06e9e1a2f4c5

One thing I notice is that my implementation is windowing the signal prior to FFT, shouldn't yours also be doing this?

I can have a go at wiring it in if you like, or would you prefer to?

My actual pitch detector was in C, before my C++ days (i.e. the last few months) so it's about time I upgraded it. It will take a little while though...

ŌÄ

EDIT: found a couple more files:

https://gist.github.com/p-i-/56cb6caffcfd2989818b
That does the FFT, allowing the compiler to choose between using apples accelerate framework and a manual FFT implementation (provided). It produces phase information for each bin.

https://gist.github.com/p-i-/0d91631e84f474245d64
This uses the above data to accurately estimate each logical peak.
Say the actual peak is somewhere between 2 bins.
You can infer the exact location from the rotation of these 2 neighbouring bins.
A bit like a strobe lighting up a dripping tap so that the water drop appears stationary.
If the drip rate is slightly off, the drop appears to be slowly moving up or down.
You can use the apparent velocity to estimate the drift to an arbitrary accuracy.
Same deal...

I don't want to provide any more files this point because what to do with this exact peak data is an open question, and I'm not sure my original algorithm was a particularly good approach.

I think it's a very interesting problem. For my own use I was just interested in detecting the fundamental frequency of my own voice. I noticed that the first or second harmonic (not the zeroth, or fundamental) was by far the strongest, so I just looked for the biggest peak, and then try to figure out whether it made most sense as a fundamental, first or second harmonic.

Anyway, if anyone is interested, do feel welcome to join in the discussion here or on the IRC channel.

In the end I had to abandon this particular musical training game as I was getting serious voice strain. However, I did put a lot of thought into pitch detection algorithms and I'm happy to share what I remember of the journey.

I'll resist trying to implement it for the sake of it as I'm (barely) recovering from strain injuries.


#7

I had a go at modifying the pitch detection algorithm in the dRowAudio library a few months ago, as they were not designed for real-time use. 

I attempted to translate java code from https://github.com/JorenSix/TarsosDSP/blob/master/src/be/tarsos/dsp/pitch/McLeodPitchMethod.java into JUCE C++. I also wanted to modify it to use a Normalised Squared Difference Function, based on some advice I got on the DSP stack exchange forum.  

I had limited time, and did not manage to get it working. In the end I used the excellent Aubio library, which can compile across different platforms. It provides 5-6 different pitch detection algorithms based on different research papers, the default one being YIN-FFT, a fast Yin implementation using FFT. So far it works well for my needs. The only thing is, on top of the JUCE license, to use it in a commercial product I also need to pay a license fee for that... so releasing my app will be more expensive than I first thought. But I also value other peoples work especially with optimised algorithms that can run across different platforms. 


#8

One thing I notice is that my implementation is windowing the signal prior to FFT, shouldn't yours also be doing this?

Yes, windowing (and many other things!) would probably improve it. But the demo wasn't intended as a tutorial in good DSP algorithms, just a quick demo of the FFT class!


#9

Does JUCE now have a pitch detection feature built-in ?


#10

Ha, no - there are so many methods around it wouldn’t make sense to have this in a general purpose library…


#11

@adamski,
Thanks for your link and info on pitch detection. Did you manage to get a reliably accurate working version of live pitch detection.


#12

Yes I use the PitchMPM class in my app, and although not as fast as FFT based methods it is very reliable and accurate across different sources, at least in my tests.


#13

Sounds very promising.
Can the PitchMPM class be used without JUCE


#14

No it depends on JUCE classes, I think just Array - its here: https://github.com/adamski/PitchDetector/blob/master/modules/PitchMPM.h
If you want a JUCE-free version, I adapted it from this library: https://github.com/sevagh/pitch-detection

I realise this thread has been derailed somewhat…!