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, Part 2, Part 3, Part 4, Part 5, Part 6, Part 7.

    Advanced Max: FFTs, Part 7


    • Aug 09 2017 | 1:36 am
      thank you, Tim, now I understand the relation between frequency and phase as they interact with fft bins-- very clear and useful tutorial!
    • Aug 19 2017 | 6:04 pm
      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
    • Aug 21 2017 | 2:22 pm
      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
    • Aug 22 2017 | 6:48 pm
      Dear Timothy,
      Many thanks for the response and suggestions. I'll, so, investigate the other possibilities.
      Best, Horácio
    • Aug 24 2017 | 10:56 pm
      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~?
    • Aug 25 2017 | 1:07 am
      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 :-)
    • Nov 07 2017 | 8:35 pm
      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 +~ ?
    • Nov 14 2017 | 11:23 pm
      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?
    • Nov 15 2017 | 3:24 pm
      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.
    • Nov 15 2017 | 3:28 pm
      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!
    • Apr 11 2018 | 5:17 pm
      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
    • May 14 2018 | 9:16 pm
      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!