Advanced Max: FFTs, Part 7
For the final installment of our Advanced Max series on the Fast Fourier Transform, we're going to take the tools we’ve created in this series and our newly-gained understanding of the Fast Fourier Transform to build an FFT-based pitch tracker in the course of this 45-minute video. Be sure to check out the other installments in the series for the tools we'll be using as we build!
All the tutorials in this series: Part 1, f="https://cycling74.com/tutorials/advanced-max-ffts-part-2">Part 2, Part 3, Part 4, Part 5, Part 6, Part 7.
by Timothy Place on August 8, 2017
thank you, Tim, now I understand the relation between frequency and phase as they interact with fft bins-- very clear and useful tutorial!
Dear Timothy,
for the first time I am (well, I think I am...) understanding better the "magic" world of FFT in Max. Also invaluable is your lesson on editing externals in xCode. I am wondering if the source of the "basic" FFT external is available to "hack it". I would love to try to do an external that does fast transforms on real time data (e.g., sensor) other than signal (i.e., audio) without the caveats and turnarounds of using methods like sig~ / snapshot~ to convert between floats (e.g.,) and signal.
Thanks so much for your first class classrooms!
Best,
Horácio
Hi Horácio,
I'm glad to hear that these have been helpful! The standard fft~/ifft~ extern code is not currently available. One option you might consider is using the jit.fft object. I do this in Part 3 of the video series.
If you really want to go the C/C++ route, there is an FFT object in Jamoma whose source code could help:
https://github.com/jamoma/JamomaCore/blob/master/DSP/extensions/FFTLib/source/TTFFT.cpp
This object wraps two different implementations of the FFT from two different 3rd-parties: Mayer and Ooura. I'm not looking at the source right now but from what I recall, Max is using the Mayer library for the FFT implementation (or something like it).
Cheers!
Tim
Dear Timothy,
Many thanks for the response and suggestions. I'll, so, investigate the other possibilities.
Best,
Horácio
Thanks for the tutorials, Tim. Excellent work!
I'm curious about your use of the pass~ object. Without a corresponding mute~ object, pass~ looks like it's simply summing the signals here. Why not use +~? Is this a question of style? I usually reach for poly~ when I need to mute/unmute signals. Am I missing something by not using pass~?
Good observation. I use pass~ instead of +~ because it is slightly more efficient. Very slightly.
It probably doesn't make much difference these days but when I started using MSP 20 years ago it did and the old habits have stuck with me :-)
Thanks a lot for these quick insights especially for xcode and gen~ programming. Very inspiring...
How much is just adding signals by connecting them directly (what I usually do) different to pass~or +~ ?
i'm 29:00 mins into this tutorial and my gen~ object isn't sending any values to the number~ object - can anyone work out what i've done wrong?
Stefan -- There is typically no significant difference. The place where there is a big difference is when you connect to an outlet object.
As an example: say you have 24 bands of a vocoder summing at the outlet. They don't actually sum at the outlet -- they sum at the inlets of the "real" objects on the other side of the outlet. So if your vocoder output is connected to 4 different things then instead of 23 addition operations you have 92 (23 x 4) addition operations being computed.
Hi Alex -- I just tried your patcher. At first it looked like nothing was happening... then I remembered to turn on the toggle connected to the qmetro object and it works great!
This is so amazingly helpful!
I've modified the patch to pick out 15 frequencies, which works great, but it often picks out frequencies that are duplicates, or very nearly, to the previous frequency. Any thoughts as to the best way to modify the gen (I'm assuming that's the best place alter) so that it only picks frequencies after x-amount of resolution higher? I've attached below an example of the frequency spacing.
THANKS!
print: 330.385441
print: 776.170851
print: 776.170860
print: 1302.934814
print: 1302.934832
print: 1302.922044
print: 1302.922044
print: 1302.922076
print: 1302.922039
print: 1302.922039
print: 1302.903831
print: 1302.903831
print: 1302.903831
print: 1304.016427
print: 1304.157141
Glad this has been helpful!
There are definitely some more elaborate things that could be done to make sense of the peaks and attempt to filter them or deduce things about them. I would be inclined to try using the JS object to experiment and only migrate things back to the audio-level if it proves necessary.
There are lots of papers out there about "feature extraction" and "fundamental estimation" which may prove useful. Good luck!
Hey guys! This is the perfect tool for a need I have. Specifically, I'm trying to adapt fft-tracker3. I'm bussing a live audio signal to that patcher and it's NOT making it through. As a matter of fact, even audio signals created within the patcher aren't working within that patch. All of the other example patches in that lesson work.
Any advice on getting this to come to life??
Hi Timothy !
First of all, thanks a lot, this serie is awesome !
I got results pretty similar to [sigmund~] with the pitch detection part in "fft-part7b.maxpat" but, in comparison, there are some jumps because of micro variations between notes. I try to figure out how to stabilize that without success... Do you have an idea to solve this ? Thanks again !