Aug 12, 2016 at 6:20 PM
Edited Aug 12, 2016 at 6:21 PM

I'm trying to make an application to show pitch of microphone input in a pitch contour in realtime using NAudio. To check the FFT results I inputted an A4 note on a clarinet which has the known f0 of 440Hz. But I got 430.6641Hz and got 904.3945Hz once
in a blue moon.
Button_Click Event
var inputStream = new AudioFileReader("a4.wav");
fileStream = inputStream;
var aggregator = new SampleAggregator(inputStream);
aggregator.NotificationCount = inputStream.WaveFormat.SampleRate / 100;
aggregator.PerformFFT = true;
aggregator.FftCalculated+=OnFftCalculated;
playback = new WaveOut();
playback.Init(aggregator);
int read = 0;
float[] buffer = new float[1024];
do
{
read = aggregator.Read(buffer, 0, buffer.Length);
} while (read > 0);
playback.Play();
OnFFTCalculated Event
float[] magnitudes = new float[e.Result.Length / 2];
for (int i = 0; i < e.Result.Length / 2; i++)
magnitudes[i] = ((float)Math.Sqrt((e.Result[i].X * e.Result[i].X) + (e.Result[i].Y * e.Result[i].Y)));
float max_mag = float.MinValue;
float max_index = 1;
for (int i = 0; i < e.Result.Length / 2; i++)
if (magnitudes[i] > max_mag)
{
max_mag = magnitudes[i];
max_index = i;
}
var frequency = max_index * samplingFrequency / 1024; // CurrentSamplerate gets set dynamically incase some tracks have a different samplerate.
Dispatcher.Invoke(new Action(() =>
{
Debug.WriteLine(frequency.ToString() + "Hz");
}));
NAudio's Sample Aggregator Class
public bool PerformFFT { get; set; }
public SampleAggregator(int fftLength)
{
if (!IsPowerOfTwo(fftLength))
{
throw new ArgumentException("FFT Length must be a power of two");
}
this.m = (int)Math.Log(fftLength, 2.0);
this.fftLength = fftLength;
this.fftBuffer = new Complex[fftLength];
this.fftArgs = new FftEventArgs(fftBuffer);
}
bool IsPowerOfTwo(int x)
{
return (x & (x  1)) == 0;
}
public void Add(float value)
{
if (PerformFFT && FftCalculated != null)
{
// Remember the window function! There are many others as well.
fftBuffer[fftPos].X = (float)(value * FastFourierTransform.HammingWindow(fftPos, fftLength));
fftBuffer[fftPos].Y = 0; // This is always zero with audio.
fftPos++;
if (fftPos >= fftLength)
{
fftPos = 0;
FastFourierTransform.FFT(true, m, fftBuffer);
FftCalculated(this, fftArgs);
}
}
}
}
public class FftEventArgs : EventArgs
{
[DebuggerStepThrough]
public FftEventArgs(Complex[] result)
{
this.Result = result;
}
public Complex[] Result { get; private set; }
}
}
What can be the issue? How can I improve the accuracy of the results?
