Sequential_Guitar_Tu..

advertisement
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
Download