Audio Visualization with Nokia 3310 LCD and FFT
The purpose of this project is to make an audio visualizer to demonstrate the use of the Nokia 3310 LCD as a graphical display. By audio visualizer, I mean the visualization like Winamp, XMMS, or Windows Media player. This project utilizes a fixed point FFT (fast fourier transform) algorithm to convert the discrete audio samples in time into frequency. This allows us to graph bars for each frequency as the music is playing. In other words, different bars dance around for the bass, midrange, treble, and all the points in between.
For input, we use the sparkfun.com microphone module. This is fed to an ADC (analog to digital conversion) pin on an Atmel AVR atmega8 running at 8MHz. Like our other Nokia 3310 based projects, we talk to the LCD using SPI. In order to run the atmega8 in 8MHz, you must change the default value of the low byte on the fuse. Our atmega does not have a floating point unit. To be able to execute fast and without lots of extra instructions, we must use a fixed point FFT algorithm. Most FFTs use floating point for accuracy. For our purposes, this loss of accuracy is no big deal.
A popular fixed point FFT algorithm was written by Tim Robberts in 1989 (http://www.jjj.de/fft/fix_fft.tar.gz). Initially, I ported this code to the avr and avr libc to be used for this project. It definitely worked, but the performance was not great. Luckily, I stumbled on an AVR optimized fft library from http://elm-chan.org/works/akilcd/report_e.html and this code executes 4 times faster! Yes, that is 4 times faster. Go optimized assembly and go elm-chan.org
The process is shown in the diagram below. First, we take samples at 16kHz. We take 64 samples. With an FFT, the more samples that you take the more granularity that you have in determining what frequencies are present. For our case, even less would do just fine but the library we are using needs a minimum of 64 samples. Next, we do an FFT on the samples to convert it to frequency. Last, we update our display. Remarkably, even running the LCD over SPI, it still is able to refresh the entire screen in less than 4ms. This allows us to refresh the screen plenty often.
As a side note, the more samples we capture and process at a time, the more precise the granularity on our frequency results. In other words, we’ll have more accuracy. The sampling rate is what determines the range of frequencies that we know about. If one wants to see higher frequencies, one has to sample faster. For our case, 16KHz seemed more than adequate. It appears as if our microphone module does not have very good frequency response in the high end. In the end, we decided to “zoom in” on the lower frequencies by making their bars wider because it gave a better visual result with our microphone module.
avr-gcc project – avr-fft-3310.tar.gz (complete project code and firmware)
firmware – avr-fft.rom
* make sure you run the AVR at 8MHz by setting the lower fuse byte to 0xe4. I do this with uisp with “uisp -dprog=stk200 –wr_fuse_l=0xe4″ but the command will vary depending on what programming program and hardware that you use.