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!
Download the patchers created in this tutorial.
Advanced Max: FFTs, Part 7
- Floating PointAug 09 2017 | 1:36 amthank you, Tim, now I understand the relation between frequency and phase as they interact with fft bins-- very clear and useful tutorial!
- Horácio Tomé-MarquesAug 19 2017 | 6:04 pmDear 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
- Timothy PlaceAug 21 2017 | 2:22 pmHi 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.cppThis 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
- Horácio Tomé-MarquesAug 22 2017 | 6:48 pmDear Timothy,Many thanks for the response and suggestions. I'll, so, investigate the other possibilities.Best, Horácio
- Holland HopsonAug 24 2017 | 10:56 pmThanks 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~?
- Timothy PlaceAug 25 2017 | 1:07 amGood 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 :-)
- Tj ShredderNov 07 2017 | 8:35 pmThanks 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 +~ ?
- Alex JacobsNov 14 2017 | 11:23 pmissues with gen~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?
- Timothy PlaceNov 15 2017 | 3:24 pmStefan -- 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.
- Timothy PlaceNov 15 2017 | 3:28 pmHi 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!
- umfufuApr 11 2018 | 5:17 pmThis 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
- Timothy PlaceMay 14 2018 | 9:16 pmGlad 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!
- dudadiusMar 19 2019 | 11:04 pmHey 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??
- Alo FaroMar 15 2022 | 6:55 pmHi 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 !