Im trying to get the pitch of microphone input in real time. I have a capture base class which includes the sample rate, channels etc., and the sample aggregator class has taken from Mark's WPF demo
Capture Base
Capture Base
public class CaptureBase : IDisposable
{
static int fftLength = 1024;
const int samplingFrequency = 44100;
const int channels = 1;
const int noOfBuffers = 5;
const int bufferMilisecs = 10;
const int latency = 50;
WaveIn sourceStream;
DirectSoundOut soundOut;
SampleAggregator sampleAggregator;
bool disposed = false;
bool isCapturing = false;
public void StartCapture(Guid selectedDevice)
{
isCapturing = true;
sampleAggregator = new SampleAggregator(fftLength);
sampleAggregator.FftCalculated += new EventHandler<FftEventArgs>(FftCalculated);
sampleAggregator.PerformFFT = true;
sourceStream = new WaveIn();
sourceStream.NumberOfBuffers = noOfBuffers;
sourceStream.BufferMilliseconds = bufferMilisecs;
sourceStream.WaveFormat = new WaveFormat(samplingFrequency, channels);
sourceStream.DataAvailable += new EventHandler<WaveInEventArgs>(sourceStream_DataAvailable);
sourceStream.StartRecording();
}
private void FftCalculated(object sender, FftEventArgs e)
{
for (var i = 0; i < e.Result.Length; i++)
{
Debug.WriteLine("FFT output.");
Debug.WriteLine(e.Result[i].X);
Debug.WriteLine(e.Result[i].Y);
//Analysis.HPS hps = new Analysis.HPS();
//hps.HarmonicProductSpectrum(e.Result);
}
}
public SampleAggregator SampleAggregator
{
get
{
return sampleAggregator;
}
}
private void sourceStream_DataAvailable(object sender, WaveInEventArgs e)
{
byte[] buffer = e.Buffer;
int bytesRecorded = e.BytesRecorded;
for (int i = 0; i < e.BytesRecorded; i += 2)
{
short sample = (short)((buffer[i + 1] << 8) | buffer[i + 0]);
float sample32 = (sample / 32758f);
sampleAggregator.Add(sample32);
}
}
public void Stop()
{
if (isCapturing)
{
isCapturing = false;
}
}
public void Dispose(bool disposing)
{
if (disposed) return;
disposed = true;
GC.SuppressFinalize(this);
if (isCapturing) Stop();
}
void IDisposable.Dispose()
{
Dispose(true);
}
}
}
Sample Aggregator public class SampleAggregator
{
private readonly Complex[] fftBuffer;
private readonly FftEventArgs fftArgs;
private int fftPos;
private readonly int fftLength;
private int m;
public event EventHandler<FftEventArgs> FftCalculated;
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; }
}
}
}
Please can someone explain what i have done wrong.