13,798,781 members
alternative version

#### Stats

406.2K views
225 bookmarked
Posted 2 Jan 2009
Licenced MIT

# FFT Guitar Tuner

, 10 Aug 2010
Using a Fast Fourier Transform to calculate the fundamental frequency of the captured audio sound

## Introduction

This article shows how to use a Fast Fourier Transform (FFT) algorithm to calculate the fundamental frequency of a captured audio sound. Also, we will see how to apply the algorithm to analyze live sound to build a simple guitar tuner: the code provides a solution to the problem of calculation of the fundamental frequency of the played pitch.

## Background

The computer can capture live sound/music using a microphone that is connected to the sound card. Modern sound cards can capture digital signals. A digital signal is a set of quantized sound values that were taken in uniformly spaced times. The digital signal does not provide any information about frequencies that are present in the sound. To determine that, the data need to be analyzed.

The Short-Time Fourier Transform (STFT) makes representation of the phase and magnitude of the signal. The result of the STFT can be used to produce the spectrogram of the signal: the magnitude squared over time and frequencies. We will use a Fast Fourier Transform (FFT) to generate the spectrogram of the signal of short periods of time. After the spectrogram is calculated, the fundamental frequency can be determined by finding the index of the maximum value of the magnitude squared. The improved algorithm finds several such places, candidate frequency bins, with the magnitude squared in the top of the maximum values, and further analyzes them to verify the candidate fundamental frequencies by using the signal data.

When a note is played on a musical instrument, the sound waves are generated by strings, air, or the speaker - an instrument generates a musical note. One of the characteristics of a musical note is a pitch (fundamental frequency). Traditionally musical alphabet frequencies are divided by octaves, and then by semitones. An octave has 12 named pitches: C (prime), C#, D, D#, E, F, F#, G, G#, A, A#, and B. Octaves also have names: great, small, one-lined, two-lined, etc. The "standard pitch" (A one-lined or A4) has a fundamental frequency of its sound waves equals to 440 Hz. The frequencies of two neighboring notes are different by 21/12, and frequencies of the notes with the same name in two neighboring octaves are different by 2.

Table: Notes and Their Fundamental Frequencies
Note NameTraditional Octave Names (Scientific), Hz
Great (2)Small (3)One-lined (4)Two-lined (5)
C65.4064130.8128261.6256523.2511
C#69.2957138.5913277.1826554.3653
D73.4162146.8324293.6648587.3295
D#77.7817155.5635311.1270622.2540
E82.4069164.8138329.6276659.2551
F87.3071174.6141349.2282698.4565
F#92.4986184.9972369.9944739.9888
G97.9989195.9977391.9954783.9909
G#103.8262207.6523415.3047830.6094
A110.0000220.0000440.0000880.0000
A#116.5409233.0819466.1638932.3275
B123.4708246.9417493.8833987.7666

The typical (six string) guitar normally plays pitches of great through two-lined octaves. The pitches of the open strings (E2, A2, D3, G3, B3, and E4) are selected in the table in bold.

## Using the Code

The solution contains three projects: the main windows application (FftGuitarTuner), the sound analysis library (SoundAnalysis), and the sound capture library (SoundCapture). The heart of the solution and the SoundAnalysis project is the FFT algorithm (see the `Calculate` method of the `SoundAnalysis.FftAlgorithm` class):

```// bit reversal
ComplexNumber[] data = new ComplexNumber[length];
for (int i = 0; i < x.Length; i++)
{
int j = ReverseBits(i, bitsInLength);
data[j] = new ComplexNumber(x[i]);
}

// Cooley-Tukey
for (int i = 0; i < bitsInLength; i++)
{
int m = 1 << i;
int n = m * 2;
double alpha = -(2 * Math.PI / n);

for (int k = 0; k < m; k++)
{
// e^(-2*pi/N*k)
ComplexNumber oddPartMultiplier =
new ComplexNumber(0, alpha * k).PoweredE();

for (int j = k; j < length; j += n)
{
ComplexNumber evenPart = data[j];
ComplexNumber oddPart = oddPartMultiplier * data[j + m];
data[j] = evenPart + oddPart;
data[j + m] = evenPart - oddPart;
}
}
}

// calculate spectrogram
double[] spectrogram = new double[length];
for (int i = 0; i < spectrogram.Length; i++)
{
spectrogram[i] = data[i].AbsPower2();
}```

The data for the algorithm is provided from the sound card capture buffer. The abstract `SoundCapture.SoundCaptureBase` utility class is an adapter for DirectSound's `Capture` and `CaptureBuffer` classes, that helps to encapsulate buffering and setting up the audio format parameters. The application requires Microsoft DirectX 9 runtime components for the live sound capture from the microphone.

Figure: Main Application Form

After the application is started, select the sound device and play a note. The application will capture the live sound and will calculate the current fundamental frequency of the signal. The information can be used to tune the guitar.

## Points of Interest

To calculate the Fast Fourier Transform, the Cooley-Tukey algorithm was used. It gives good performance for the required task. To challenge the algorithm, the application analyses about 22,000 sample blocks in real time: the sound is captured at a 44,100 Hz rate and a 16 bits sample size, and the analysis is performed twice a second.

The sound analysis library can be used for tone, background noise, sound, or speech detection. Series of the spectrogram of the continued sound can be displayed as a 2D (or 3D) image to present it visually.

## History

• 1st January, 2009: Initial version
• 2nd January, 2009: Added algorithm code snippet
• 3rd August, 2010: Corrected article typos; new frequency detection algorithm

## Share

 Software Developer United States
No Biography provided

## You may also be interested in...

 First PrevNext
 Setup Member 1295200216-Jan-17 1:13 Member 12952002 16-Jan-17 1:13
 Re: Setup ProcopioPi29-Oct-18 22:16 ProcopioPi 29-Oct-18 22:16
 Point FFT Member 1167218922-May-15 22:12 Member 11672189 22-May-15 22:12
 FFT Guitar Tuner not work in win7 64bit & visual studio 2010 lpln85211-Aug-14 22:00 lpln852 11-Aug-14 22:00
 Re: FFT Guitar Tuner not work in win7 64bit & visual studio 2010 Member 106723433-Jun-15 10:28 Member 10672343 3-Jun-15 10:28
 Project within a project Member 1053139926-Apr-14 7:07 Member 10531399 26-Apr-14 7:07
 My vote of 1 Fabrizio Stellato12-Jan-14 4:28 Fabrizio Stellato 12-Jan-14 4:28
 How hard it would be to redo this project for java ? YuriyKravets25-Nov-13 7:00 YuriyKravets 25-Nov-13 7:00
 Got it working on XP x64 under .NET 4.0 bmac20-Jul-13 6:54 bmac 20-Jul-13 6:54
 Here's how I got it to run on XP x64: A couple of notes first: . Big shout-out to notmasteryet for this truly excellent project. . I don't use Visual Studio, so all compiling is done by calling msbuild on the three csprojs from the command-line. . No changes were made to the SoundAnalysis or SoundCapture projects or to the solution file. . I used the 64bit version of msbuild but I'd be surprised if the 32bit version didn't work, too. . This very purposefully generates a 32bit exe because Managed DirectX does not appear to have a 64bit version; if you open both the 32bit and 64bit DirectX Control Panel utilities (under "Programs/DirectX SDK June 2010/DirectX Utilities" and "[same]/DirectX Utilities (64-bit)"), the 5th and final tab is "Managed" which only has entries in the 32bit version. . The 32bit issue is separate from the fact that the DirectSound DLL is dependent upon v1.1 of .NET, which requires the BindAsLegacyV2Runtime rigmorole in Program.cs and the addition of the specially-crafted app.config file -- actually I've left it an exercise for the reader to determine if both are actually needed. . For now, all I've got is XP x64. 1) Add this after the last `using` in Program.cs ```using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices;``` 2) Add this before `static class Program` in Program.cs ```    // This dominating code worked the first time (let's not quibble on the formatting today :-) and is courtesy:     // http://reedcopsey.com/2011/09/15/setting-uselegacyv2runtimeactivationpolicy-at-runtime/     public static class RuntimePolicyHelper     {         public static bool LegacyV2RuntimeEnabledSuccessfully { get; private set; }              static RuntimePolicyHelper()         {             ICLRRuntimeInfo clrRuntimeInfo =                 (ICLRRuntimeInfo)RuntimeEnvironment.GetRuntimeInterfaceAsObject(                     Guid.Empty,                     typeof(ICLRRuntimeInfo).GUID);             try             {                 clrRuntimeInfo.BindAsLegacyV2Runtime();                 LegacyV2RuntimeEnabledSuccessfully = true;             }             catch (COMException)             {                 // This occurs with an HRESULT meaning                 // "A different runtime was already bound to the legacy CLR version 2 activation policy."                 LegacyV2RuntimeEnabledSuccessfully = false;             }         }              [ComImport]         [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]         [Guid("BD39D1D2-BA2F-486A-89B0-B4B0CB466891")]         private interface ICLRRuntimeInfo         {             void xGetVersionString();             void xGetRuntimeDirectory();             void xIsLoaded();             void xIsLoadable();             void xLoadErrorString();             void xLoadLibrary();             void xGetProcAddress();             void xGetInterface();             void xSetDefaultStartupFlags();             void xGetDefaultStartupFlags();             [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]             void BindAsLegacyV2Runtime();         }     }``` 3) Create FftGuitarTuner\app.config (in the same folder as FftGuitarTuner.csproj), making sure to create it as UTF8 to match the XML declaration encoding ``` ``` 4) Add the following to FftGuitarTuner.csproj before the ` ``` 5) Edit FftGuitarTuner.csproj as such: a) On line #2, change the ToolsVersion value from "3.5" to "4.0" b) On line #13, change "v3.5" to "v4.0" c) Delete the three lines {36,39,42} that contain "3.5" 6) Call msbuild from a cmd prompt as follows to force the exe to be treated strictly as a 32-bit exe, after, of course, you cd into the folder where FftGuitarTuner.csproj is `"C:\WINDOWS\Microsoft.NET\Framework64\v4.0.30319\MSBuild.exe" /property:PlatformTarget=x86 FftGuitarTuner.csproj` Robert's Robot Double "Lasting peace and happiness for *ALL* human beings."modified 20-Jul-13 12:15pm.
 Re: Got it working on XP x64 under .NET 4.0 Achmad Rahman M10-Apr-17 8:30 Achmad Rahman M 10-Apr-17 8:30
 My vote of 5 Abdullatif M. Abu Al Rub2-Mar-13 1:31 Abdullatif M. Abu Al Rub 2-Mar-13 1:31
 My vote of 5 vard9912-Jan-13 14:06 vard99 12-Jan-13 14:06
 Building as 4.0 theney11-Dec-12 8:04 theney 11-Dec-12 8:04
 Re: Building as 4.0 Member 869236731-Jan-13 9:52 Member 8692367 31-Jan-13 9:52
 Re: Building as 4.0 bmac20-Jul-13 6:58 bmac 20-Jul-13 6:58
 Problem with Fft Algorithm Member 963903729-Nov-12 2:14 Member 9639037 29-Nov-12 2:14
 ? Windows 7 rspercy6528-Nov-12 5:19 rspercy65 28-Nov-12 5:19
 Re: ? Windows 7 lalitsrana3-Jan-13 21:46 lalitsrana 3-Jan-13 21:46
 Re: ? Windows 7 Member 869236731-Jan-13 9:41 Member 8692367 31-Jan-13 9:41
 Re: ? Windows 7 bmac20-Jul-13 6:58 bmac 20-Jul-13 6:58
 Request Help on using this code to measure bicycle spoke tesnion Member 934224119-Aug-12 16:37 Member 9342241 19-Aug-12 16:37
 Not working as expected ZeAleks24-May-12 10:39 ZeAleks 24-May-12 10:39
 My vote of 1 vartika sharma25-Apr-12 3:23 vartika sharma 25-Apr-12 3:23
 HELP please: How to modify this to work for 2 channels (stereo) Member 813676915-Feb-12 5:02 Member 8136769 15-Feb-12 5:02
 Last Visit: 13-Dec-18 20:29     Last Update: 13-Dec-18 20:29 Refresh 123456 Next »