Fast Fourier transform examples
I finally got a fast Fourier transform working on an Arduino Due! This is not exactly a final product but just a documentation of progress. I am working my way toward beat detection, but am still getting a better feel for FFT processing and observing different types of music and beats. Below is some information about how I got up to speed, and at the end are videos of where I am now.
Listening to Superlove by Avicii and visualizing it with the free iSpectrum app" class="mt-image-none" height="1820
A week ago I posted some sound reading charts as I was getting my feet wet, but struggled to find documentation to understand how the Atmel ATSAM3X8E Cortex-M3 MCU chip that powers the Due works, especially regarding the analog to digital conversion nuts and bolts. I don’t have a ton of experience with electrical engineering, registers, pull-up resistors and all sorts of relevant terminology. I was starting to wonder if I needed to learn more fundamentals, and then it would all make sense, or if I just needed to find more examples or documentation.
First I spent the better part of a day looking at all the FFT and FHT Arduino libraries I could find, but in my (somewhat cursory) testing, none worked on the Due, due to it being a different architecture than the other Arduinos, and who knows what other factors. Here are some of them:
- Adafruit’s FFT tutorial apparently uses a chip with a 32-bit ARM Cortex-M4 processor and the CMSIS DSP math library. I overlooked this in my first pass, so that might have been useful, since I ended u p using the CMSIS DSP library after finding it used in the wild.
- The Arduino forum post DUE’s more advanced FFT capabilities discusses modifications needed to get access to the CMSIS DSP library functions in the Arduino IDE.
- Arduino FFT Library on Open Music Labs. I used this in testing on the FLORA, but it would not compile on the Due. Still, their site has some good explanation of the FFT and what the data inputs and outputs are like.
- The Arduino forum post FFT Library for Arduino Due, SAM3X mentioned an FFT library for the Due, but the URL is dead. There’s some potentially insightful discussion though.
- Adafruit’s Piccolo tutorial includes an FFT library called ELM-ChaN ffft, which also didn’t work on the Due.
- DueTimer library — did not use but might have useful code comments
- Fast Hartley Transformation Library for AVR microcontrollers: good explanation, and claims to be suitable for the Due.
My salvation came in finding a Github repo by Arduino forum user stimmer, where he had a working example of the CMSIS DSP library on the Arduino Due, and also the post Arduino DSP on the blog m0xpd’s ‘Shack Nasties’.
Whilst there is a great FFT application library for Arduino UNO etc, here (I’ve used it and can vouch for its quality), it isn’t suitable for the DUE. It is too limited in scope and - more importantly - doesn’t take advantage of the extra resources on the DUE’s ARM processor. Fortunately, ARM themselves produce a library which includes DSP functions - the CMSIS-DSP library, which you can find documented at the websites of the major software providers for ARM development such as Keil.
Unfortunately, the Arduino software isn’t set up to use the CMSIS-DSP library - so you need to do a little digging to set it up. Fortunately, that task is well-described in this discussion on the Arduino forum.
With the information in the links above, you’ll be able to play with audio on the Arduino DUE - which is a really exciting platform.
After a lot of reading the documentation I could find, mostly pretty low level register codes and not very friendly technical documents, I managed to get a sketch derived from Stimmer’s documented enough and working with my setup. I added a bunch of comments in fht_setup.h
to help me make sense of all the settings from Stimmer’s sketch.
I originally was using the same microphone as on my other projects, Adafruit’s Electret Microphone Amplifier (MAX4466 with Adjustable Gain), but I tried swapping that out for Adafruit’s Electret Microphone Amplifier (MAX9814 with Auto Gain Control), and the results were better. I thought I tried this in the past and it didn’t work well, which I attributed to the normalization code the sketch already included. If the Arduino is volume leveling, the microphone shouldn’t have to also. But maybe it doesn’t hurt, after all. I’ll need to do more comparisons.
I listened to a bunch of songs while visualizing the frequencies with the free iSpectrum app for OSX, so I could get an idea what my FFT should produce.
I used an FFT transform of 512 samples processed 100 times a second and then summed the resulting 256 frequency bands into six groups such that the range of the groups should roughly encompass an equal amount of sound to the human ear, since lower frequencies sound louder at the same amplitude. The ranges are 0–200Hz, 200–400Hz, 400–800Hz, 800–1600Hz, 1600–3200Hz and 3200–6400Hz and are represented by the six bars on the matrix, each 5 pixels wide. I played with skipping some FFT cycles when updating the lights so it would flicker less, but I did not document which video is which. Most of them are probably being updated around 30 times a second, which might cause issues with 30fps video, maybe.
The LEDs are all NeoPixels from Adafruit. The strip lights along the ceiling are not using FFT and are powered by a FLORA Arduino board. The LED matrix is using FFT and powered by an Arduino Due. More information and links to the programs are at https://votecharlie.com/blog/2016/03/fft-examples.html and elsewhere on my blog.
The below videos include some of the LED strip along my ceiling. That is currently powered by this code. The LED grid is powered by this code.
This is just a test to confirm the FFT is working. I am not sure why the lower frequencies seem to affect the first three buckets, but the higher ones are more discrete. It may be exacerbated by the normalization applied to each bin over several seconds of readings, or the auto gain of the microphone I am using, or FFT effects where frequencies sometimes show up at double or triple in addition to actual.
This one has beats in several frequencies, but a strong <200Hz baseline. The music is “Blutsbrüder” by Kollektiv Turmstrasse.
This one may have too many instruments in the lowest frequency bin, as there does not appear to be a consistent beat till 20 seconds in, after which point it is obvious. The music is “Flaschenpost” by Kollektiv Turmstrasse.
This is the same as the previous one, but juxtaposed against the strip lights that are computed stricly on amplitude and not using an FFT transform to isolate frequencies. I am trying to observe the strengths and weaknesses of both approached. The music is “Flaschenpost” by Kollektiv Turmstrasse.
Version 1 of 2 of “Grillen im Garten” by Kollektiv Turmstrasse, which has many strange sounds and instruments of many frequencies in addition to a beat that comes and goes. It will be interesting to see if I can make a good way to detect this beat.
Version 2 of 2 of “Grillen im Garten” by Kollektiv Turmstrasse, which has many strange sounds and instruments of many frequencies in addition to a beat that comes and goes. It will be interesting to see if I can make a good way to detect this beat.
This is “Nightwalking Your Memory” by Vector Lovers, which has a triple beat every other beat.
“Pheasant” by Einmusik, which has a pretty consistent beat, though it switches at times from the drum to something else that seems to be close enough in frequency it should not screw up a beat detection based on frequency.
This crazy song has all sorts of frequencies and inconsistent beats. It is “Sex” by Slugabed.