Chromatic Tuner

This was my final project for my second embedded systems course. Utilized Microblaze on a Xilinix Artyx 7 FPGA and the QPnano RTEF (Real time embedded framework). This project was quite the challenge, we needed to capture microphone samples and get the primary frequency utilizing the FFT, while simultaneously drawing to an external LCD display with low latency. To implement the menu, we utilized a HSM (hierarchical state machine) through QPnano, with a menu parent state that encompassed child states for each of the menu selections (Tuner mode, Octave selection, A4 Value selection, Frequency Histogram). Using a rotary encoder for the menu selection, we would detect the voltage sequence that corresponds to a left or right turn, which would fire an interrupt. In the rotary encoder ISR we would send a signal to the HSM that would indicate a left or right turn. These signals would navigate us through the child states in the menu. When the rotary encoder was pressed down, that would indicate that you were selecting one of the four menu options. Let’s start with the octave selection. When performing the FFT it’s important to note that the maximum frequency that you can detect without aliasing is the Nyquist frequency, or 1/2 the sampling frequency. It’s also important to note that the size of the FFT determines the bin size of the output. If the FFT has too few points then the output frequency bin sizes will be much too large, and you lose a lot of accuracy in the lower notes where a few Hz might be a half-step. The octave selector would allow you to input what octave you intend to play in, and would modify the FFT size and decimation rate to ensure that the tuner would be accurate for that frequency range. The next menu selection is the A4 Value. If you’re unfamiliar with music theory A4 is note A in the fourth octave, and is also the note frequency that all other notes are based upon. Some instruments are not tuned to A4 = 440, and some weirdos on the internet also think that certain A4 values heal your soul. To be inclusive of these instruments (and those weirdos) you can modify the A4 value. Changing the A4 value comes with a lot of consequences though, as it alters our note-finding algorithm. Our note detection works as follows, we take the A4 value, divide that frequency by 16 to obtain A0, and then fill an array with all of the other notes, multiplying our current frequency by 2^(-1/12) to go down a semitone, and 2^(1/12) to go up a semitone. Then we would create an array of all the notes plus 50 cents, or half way to the next note. (1 cent = 1% of a transition to the next semitone, however this is not a constant number as notes get more spaced out the higher up you go). This +50 cents array would be our note detection, every time we obtain a frequency from the FFT we would run through that array until we find the first value that is larger than our obtained frequency, and that index is our note. The reason we do the +50 cents array is because we never want to display a note as being over 50 cents sharp or flat, as that would mean we’re actually closer to the next semi-tone. So, when our A4 value is calibrated, we recalculate those arrays. This version of note detection is very useful, as there are no calculations to be done but comparisons when we’re actually running the tuner. The histogram state is quite simple, it records the input frequencies into a buffer and displays them onto the screen. The final state is the actual tuner. In the tuner state we would grab samples from the microphone, convert them to usable data using some sneaky inline assembly, and then pass them to the FFT. Once we have the frequency we would run our note detection algorithm, and display the note on the screen, as well as a bar that indicates how sharp/flat you are. Fortunately we managed to get our latency quite low, even for large point FFTs, so it runs quite smoothly. This project was quite fun, and definitely the most difficult embedded project I’ve ever undergone.

Leave a comment