Sequential Guitar Tuner By Daniel Sonnenmark Fall 2012 ECE 3551 Purpose The purpose of this project is to create a program which can be used to tune a guitar. This is done by creating a sequential guitar tuner using the OMAPL137 Development Board. A user would upload the program to their own OMAPL137 Development Board and be able to tune their guitar with it. Specifically, the program measures the sound of the user’s guitar. It then compares the frequency of the guitar sound to the ideal frequency stored in memory. It then indicates whether the guitar’s frequency is too high (sharp), too low (flat), or in tune. The guitar tuner continues to detect the guitar’s frequency until it is in tune. Once it is in tune, the program progresses to the next string. This process continues until all strings are in tune. The program then terminates. This process is illustrated in the diagram shown below. For the student, this project presents a challenge. While most projects use filtering, this project is unique in that it uses functions of the CCS software not previously used within the lab. This includes using the Fast Fourier Transform as well as data processing not previously used. This project is challenging though achievable for a student. Method Although the process described earlier seems fairly simple, implementing it is not as elementary as one would think. There were many difficult procedures that had to be researched, designed, and implemented in CCS. The most challenging portion of the design was detecting the pitch of the guitar. There were actually many steps needed to accomplish this along with many hours of research. Through vigorous research and testing an ideal solution was found. The first portion that had to be researched was the pitch detection method. There are actually many ways to evaluate the frequency and pitch of a sound. All methods either occur in the time domain (amplitude vs. time) or frequency domain (amplitude vs. frequency). When a signal is received by the development board, it is already in the time domain. Using the time domain eliminates any need to compute the complex Fourier Transform, making the code somewhat simpler. There are a few ways to evaluate the signal in this domain to obtain its pitch. One method is the zero-crossing method. This method detects every instance of a zero in a signal; that is, where the amplitude transitions from positive to negative or vice versa. By counting every zero-crossing, the period of signal can be found, and hence the fundamental frequency can be determined. A flaw in this design is that it may not work well for a signal that has many harmonics, such as the sound emit from a guitar. This is because the zero-crossings of the harmonics may be confused for the zeros of the target fundamental frequency, resulting in skewed results. Using this method combined with auto-correlation and other algorithms can in fact create a very accurate pitch detection method. Utilizing various methods is what is used in most commercial digital guitar tuners. Auto-correlation will be explained in detail later. Another method is using the FFT method. The FFT computes the Discrete Fourier Transform(DFT) of a signal much quicker than using normal DFT calculations. The DFT allows signals to be displayed as functions of frequency, where the fundamental frequency (desired frequency) can be found. The most common FFT is the Cooley-Tukey method. The disadvantage of using just an FFT to derive the fundamental frequency is that the harmonics associated with the signal may interfere with the desired frequency. Any of these methods in both the time and frequency domains can be utilized in an autocorrelation type algorithm to produce a more accurate result. Autocorrelation compares a function with itself, and is widely used to determine the fundamental frequency when noise or harmonics are present. It works by comparing the function at two different times while looking for a distinct pattern. Common types of auto-correlation methods include Cepstrum, Harmonic Product Spectrum (HPS), Maximum Likelihood, Average Mean Difference Function (AMDF), and various algorithms that build on autocorrelation. Although using one of these auto-correlation methods would be ideal, the basic FFT and zero-crossing methods are much simpler to implement and are the best options to use for a novice CCS user. Guitar signals are not just simple sine waves. In fact they often have arbitrary peaks and strange waveforms that make the signal difficult to analyze. The signal also contains many harmonics, which are waves of different amplitude, frequency and phase which can create confusion for any pitch detection software. Using just the Zero-Crossing method will only work for a periodic signal with absolutely no harmonics. Any harmonics at all will interfere with the measurement of zero crossings and thus create inaccurate results. Thus the FFT was chosen as the method that the program would use to determine the pitch of the guitar. The FFT converts the input signal from the time domain to the frequency domain. Since the system is digital, a DFT is created from this computation. The DFT is created in the form of an array of amplitudes. By indexing the element with the maximum amplitude, the fundamental frequency is found. This process will be discussed in detail in the Code Explanation section. An image of a typical DFT output can be seen below. Figure 1- Typical FFT Transformation After the guitar note’s fundamental frequency is established the next step is to determine whether this frequency is the correct frequency for that note. If you are not familiar with guitars, a standard guitar has six strings. Each string has a corresponding note when played in the open position, which means that the frets are not used. Each guitar string is labeled by this note. Each guitar string, its note, and that notes fundamental frequency is shown in a table below. Guitar String Note Fundamental Freq. 1st string e 329.6 Hz nd 2 string B 246.9 Hz 3rd string G 196 Hz th 4 string D 146.8 Hz th 5 string A 110 Hz 6th string E 82.4Hz Table A- Guitar Strings and Corresponding Frequencies Since it is unlikely for the FFT to be able to be accurate enough to determine the frequency with four significant figures, it was deemed that the best way to determine the tune of the string would be to determine if its fundamental frequency falls within a specified range deemed acceptable. Through research it was deemed that a difference in 1Hz may be not make an audible difference. Thus each note has a range of length two Hz that it must fall within to be considered in tune. An instrument’s note is flat if its frequency falls below that of the intended note and sharp if it is above the target frequency. The program is able to determine if the fundamental frequency is either flat, sharp, or in tune by using comparison methods. Once the state of the note is determined the following happens. If the note is flat or sharp, the process repeats itself until the note is deemed in tune. If the string is in tune, the next string is evaluated. This continues until all strings are evaluated. The program then terminates itself. The program uses LEDs to indicate the status of the guitar’s note. The OMAPL137’s usable LEDs are labeled as DS1, DS2, DS3, and DS4. For each state (flat, sharp, in tune) a different sequence of LEDs are used to indicate the state of the note. The next section describes the code in detail and how it is implemented. Code Explanation The code itself is not made from scratch. In fact, there is a lab not done in class but available on the Angel website that contains the FFT algorithm. This lab is labeled Lab10, and its purpose is to allow the user to see a visual graph of the FFT of an input signal. Thus for development purposes it was easier to modify Lab 10 to suit the needs of this project. Most of the code is the same as in other labs, priming the inputs/outputs etc, and therefore will not be discussed. The first portion that is described is the use of the FFT. Shown below are the definitions and declarations used in the FFT process. Figure 2- FFT Definitions The FFT is available from the “dsplib” site as a file that can be referenced through code. This file is labeled “DSPF_sp_fftSPxSP” and was referenced through the CCS linker. The two states of the program are “Passthrough”, which passes input to output, and “Complex_FFT,” which computes the DFT of the input signal. “N” is the number of samples that the FFT computes. This is used in many calculations to determine the fundamental frequency. “pCFFT_In” and the others are the different states of the FFT calculation that will be explained in further detail later. Next shown is the bit-reversal array used in the decomposition portion of the FFT. This is used where the FFT reverses the binary data of the time-domain signal. Figure 3- Bit-reversal Definition The twiddle factors are an array of coefficients that are multiplied by the input data within the FFT computation. In the Cooley-Turkey algorithm, these coefficients are used to combine the DFTs that were initially broken up by the FFT algorithm. Instead of listing these as an array, the twiddle factors are created by a specific portion of the code. An image of this section is shown below. Figure 4- Twiddle Factor Generation The section shown below is the main processing section. The first portion, labeled “decide on radix” is what determines how the FFT will operate. This implies that the FFT is using a split-radix method, which divides the samples into either radix-2 or radix-4 portions to speed up the computation time. Each value encloses a number of samples. Given a number of input samples, previously defined by “N”, this section will coerce this value to one of these in order to compute the FFT. Sample numbers such as 512 are powers of only and thus require a radix of 2. Sample numbers such as 1024, which is used in this program, are powers of four and thus can use radix-4. The next portion prepares the input for use in the FFT. It does this by splitting the input up into real and imaginary numbers. As shown there are two different input values, one containing only real values and the other containing the imaginary ones as well. The computational portion simply enacts the FFT file that was described previously. This file computes the FFT so it does not have to be written in the program. The FFT is a very complex process that would be very difficult to emulate using hard code. The last portion computes the DFT magnitudes from the FFT output. The values contained in the “pCFFT_Mag” array are amplitudes, in order from 0Hz to half of the sampling frequency (22,050 Hz). These values are used in the code created by the student to determine the fundamental frequency. Figure 5- FFT Portion of Code The next portion highlights the code created to determine the fundamental frequency. The first part that should be pointed out is the while loop. Each case represents a string. A while loop is used to determine whether the program should continue testing the same string (out of tune) or move on to the next one. More about this will be shown later. Also note that the portion shown below initially turns off all LEDs. Figure 6- E-string Case The next portion determines the fundamental frequency of the guitar signal. From the FFT we have an array of magnitudes. The element of that array with the maximum amplitude is the fundamental frequency. From finding the location of this element within the array, the fundamental frequency can be calculated. A For loop is set up which uses the first 50 samples of the DFT array. Each element’s magnitude is compared to the “Max_Amp”, which is initially set to a very low value. When an element’s magnitude is greater than “Max_Amp”, it then becomes “Max_Amp.” This process is continued until an element cannot be surpassed, meaning that it has the maximum amplitude of all of the elements. The index of this element is multiplied by the maximum frequency divided by the number of samples. For this program, this means that every element differs by 21.5 Hz. For example, if the index of the array was 5, then the fundamental frequency would be 107.5 Hz. Figure 7- Finding Fundamental Frequency The last portion of code determines whether the note is in tune or not. Boundaries of the acceptable range of frequencies are set for each note. These are labeled Highthresh and Lowthresh. A series of if-else statements determine which category the note falls under. If it is flat or sharp, that state is indicated through the use of LEDs, and “check” is set to 1. As long as check is equal to 1 the loop will keep repeating, thus forcing the process to continuously repeat. If the note is in tune then check is set to 0, thus ending the loop and allowing the code to progress to the next case. Figure 8- Determining State of Guitar Note Troubleshooting Unfortunately, the program would not execute in the required manner. Although the program would compile, the LEDs would not indicate anything. Using a breakpoint on the FFT output, no output was found either. This problem was never resolved; however steps were taken to fix it. When these steps failed to fix the problem, an alternate program was created using a Win32 application and in Labview. These steps are documented below. The first step was to determine if there was an input waveform. This was confirmed by using a breakpoint and graphing pOut. The result was a perfect sine wave, as generated from a YouTube video. Next was to determine if the FFT was working properly. A graph was generated of the FFT magnitude by placing a breakpoint after the FFT operations. The resulting graph looks nothing like an FFT should, leading to a lack of appropriate data to be processed. The resulting graph looks like this: Figure 9- FFT Magnitude Output Although graph settings were tinkered with, the code would simply not work. It seemed that the data processing portion was not receiving the data either, leading to not outputs. The LED functionality was attempted to be tested, though this also failed. The LED test program was imported and attempted to run. Unfortunately, an error kept popping up indicating that the “evmomapl137bsl.lib” file could not be found. Using the linker, this file was directed to the file. This did not change anything, as the error continued to show. This seems like an internal error of the CCS program. This contradiction is shown in the image below. Figure 10- Missing File Error Contradiction From the lack of ability to test the functionality of different portions of the code, it was hard to troubleshoot the program. Through hours of failed attempts, it was understood that time was running out and there had to be something to show for the presentation. Thus as a back-up two programs were created which showcase the theoretical abilities of the code already discussed. These two programs will continue to be the topic of discussion as real results were obtained from these. Alternate Solutions The first objective was to demonstrate that the code that was written was indeed correctly written and would work as intended. The code was copied into Microsoft Visual Studio 2010 to be made into a Win32 application. The only portion of the code that was copied was the portion that was written by the user. Thus the FFT and I/O configurations were left out. The Win32 application assumes that the FFT Magnitude array was already created and thus uses an array of values to represent that. From then everything else is exactly the same. Instead of using LEDs to indicate the state of the guitar’s tuning, strings are outputted on the Win32 window. The complete code for this is shown below. /* **SEQUENTIAL GUITAR TUNER** */ #include "stdafx.h" #include <iostream> #include <iomanip> #include <Windows.h> using namespace std; int _tmain() { int check = 1; while (check == 1) { int pCFFT_Mag[] = {0,2.7,3.5,4.8,6.8, 4.2, 3, 1, 2}; const int N = 512; int Max_Amp = -1; int Fund_Index; int Fund_Freq; int i; for(i=1; i < 8; i++) { if (pCFFT_Mag[i] > Max_Amp) { Max_Amp = pCFFT_Mag[i]; Fund_Index = i; Fund_Freq = (22050/N)*i; } } int Highthresh_E; int Lowthresh_E; Highthresh_E = 550; Lowthresh_E = 650; if (Fund_Freq >= Highthresh_E) { check = 1; cout << "LED 1: ON " << "NOT IN TUNE"; cout << endl; cout << endl; } else if (Fund_Freq <= Lowthresh_E) { cout << "LED 3: ON " << "NOT IN TUNE"; cout << endl; cout << endl; check = 1; } else { cout << cout << cout << check = "LEDs 1,2,3: ON endl; endl; 0; " << "IN TUNE"; } cout << "Fundamental Frequency = " << Fund_Freq; cout << endl; cout << endl; Sleep(1000); system("pause"); } check = 1; /*If check is = 0, the program exits the while loop. Another while loop is placed right after this, the only difference being the frequency thresholds.*/ return 0; } Figure 11- Win32 Code The results of this turned out to be flawless. From the array of magnitudes the resulting fundamental frequency was found. This was proven by outputting the value of the “Fund_Freq”. From this the program either executes again or terminates. The program also correctly determined the state of tune of the guitar string. This code only tunes one string of a guitar. To tune other strings cases just like the one shown would have to be added in sequence, a simple task. The output of the application is shown below. Figure 12- Win32 Application The next alternate solution was designed to simulate the entire Sequential Guitar Tuner program. This was done by creating a Virtual Instrument using Labview. The VI uses a similar implementation as the CCS program. It uses the same basic format to tune the guitar: determine fundamental frequency, compare to ideal frequency, indicate whether flat, sharp, or in tune, repeat or proceed to next string when previous string is in tune. This VI features a very organized layout. The block diagram utilizes the machine state architecture to avoid clutter and make the VI much more presentable and simple to understand. SubVIs determine the fundamental frequency and graph the FFT spectrum. The front panel is laid out in an attractive manner, with an easy to use GUI. The block diagram and front panel of this VI are shown below. Figure 13- Block Diagram of Sequential Guitar Tuner VI Figure 14- Front Panel of Sequential Guitar Tuner VI The guitar tuning VI is actually much better than the proposed CCS program in a few ways. One advantage is that the VI can utilize multiple input methods, giving it much more flexibility. The CCS program can only use a sound input from a guitar or computer, whereas the VI can import a sound file, use the microphone input, or even simulate signals using the provided controls. Another advantage of the VI is that it is much more accurate than the CCS program. The CCS program is inherently flawed in that there is no ability to window the provided FFT program. This means that with the maximum number of samples set at 1024, the FFT has a tolerance of +/- 21.5 Hz. This is inaccurate to the point of being useless. On the other hand, the VI uses windowing to create a very accurate DFT. The last advantage is that the VI has an easy to use interface that can directly communicate to the user. The CCS program would communicate using LEDs, which is fine, but if any other information was to be obtained the user would have to halt the program, add breakpoints, and then graph the desired section, hardly a quick procedure. With the VI all of this information is showed immediately. The VI turned out to work flawlessly. Even with added noise or harmonics, the VI computes the fundamental frequency without a hitch. It was very easy to tune a guitar within a short amount of time. Examples of the output of this VI are shown below. Figure 15- VI Evaluating a Pure Sound Wave Figure 16- VI Evaluating the D String of a Guitar Conclusion First it needs to be said that although much work was put in, the project was technically not successful. The object of the project was to create a guitar tuner using the CCS software and upload it to the DSP development board. This was simply not accomplished. Even if the CCS software did work properly, the program would suffer from the inherent flaw of being very inaccurate. Since there is no way to window the FFT, the program would only be able to detect a fundamental frequency to the nearest 21.5 Hz. However, the failure of the CCS program was supported by two alternate programs which simulate the operation of the CCS program. An application was made that proved that the student created CCS code was indeed correct and functional. A VI was made that acts as a sequential guitar tuner. Most importantly, much knowledge was gained from doing this project. A clear understanding of pitch detection and how it works is now understood. References 1. 2. 3. 4. 5. 6. FFT- http://www.cmlab.csie.ntu.edu.tw/cml/dsp/training/coding/transform/fft.html FFT- http://www.dspguide.com/ch12/2.htm Labview- http://forums.ni.com/t5/LabVIEW/bd-p/170 Pitch Detection- http://sound.eti.pg.gda.pl/student/eim/synteza/leszczyna/index_ang.htm Pitch Detection- https://ccrma.stanford.edu/~pdelac/154/m154paper.htm Microcomp Resource- http://my.fit.edu/~vkepuska/web/courses.php#ece3551-files