View the newer project here: 18-09-19_microphone_FFT_revisited
Realtime Graphing of Microphone Audio with FFT Display using C# (Visual Studio 2017)
-
Project Demo on YouTube: https://youtu.be/q9cRZuosrOs
-
Updated Video on YouTube: https://youtu.be/qUlCImYOC8c
-
See notes related to calculating FFT with C#
-
WHY THIS PROJECT EXISTS: This is intended to be a minimal case example how to capture audio data from the microphone and display it in real time. It is not a polished project. It is essentially a note-to-self project uploaded to provide code reference for the author in the future. I'm sharing it online so others may benefit from reviewing its code.
-
ScottPlot is a user control I am currently developing. It will be its own GitHub project when it is completed, but it's not ready yet. I'm adding a zip snapshot of the current development project frozen in time. If you are going to try to run this project as-is, you'll need to add ScottPlot as a reference.
WaveIn wi = new WaveIn();
wi.DeviceNumber = 0;
wi.WaveFormat = new NAudio.Wave.WaveFormat(44100, 1);
int frameSize = 1024; // how much buffer to read at once
var frames = new byte[frameSize]; // init the byte array
bwp.Read(frames, 0, frameSize); // read the buffer
int SAMPLE_RESOLUTION = 16; // this is for 16-bit integers in a byte array
int BYTES_PER_POINT = SAMPLE_RESOLUTION / 8;
Int32[] vals = new Int32[frames.Length/BYTES_PER_POINT];
for (int i=0; i<vals.Length; i++)
{
byte hByte = frames[i * 2 + 1];
byte lByte = frames[i * 2 + 0];
vals[i] = (int)(short)((hByte << 8) | lByte);
}
scottPlotUC1.Xs = Xs;
scottPlotUC1.Ys = Ys;
scottPlotUC1.UpdateGraph();
public double[] FFT(double[] data)
{
double[] fft = new double[data.Length]; // this is where we will store the output (fft)
Complex[] fftComplex = new Complex[data.Length]; // the FFT function requires complex format
for (int i = 0; i < data.Length; i++)
{
fftComplex[i] = new Complex(data[i], 0.0); // make it complex format (imaginary = 0)
}
Accord.Math.FourierTransform.FFT(fftComplex, Accord.Math.FourierTransform.Direction.Forward);
for (int i = 0; i < data.Length; i++)
{
fft[i] = fftComplex[i].Magnitude; // back to double
//fft[i] = Math.Log10(fft[i]); // convert to dB
}
return fft;
}
I got a large framerate increase when I modified the buffer size. Here is similar init code from another project which demonstrates the idea with comments:
int RATE=44100; // sample rate of the microphone
int BUFFER_SAMPLES=1024; // powers of two help for FFT
var waveIn = new WaveInEvent();
waveIn.DeviceNumber = 0; // change this to select different sound inputs
waveIn.WaveFormat = new NAudio.Wave.WaveFormat(RATE, 1); // 1 for mono
waveIn.DataAvailable += OnDataAvailable; // this function must exist
waveIn.BufferMilliseconds = (int)((double)BUFFER_SAMPLES / (double)RATE * 1000.0);
waveIn.StartRecording();
I reduced the size of this GitHub project by not including the packages folder. It contians the following folders:
- Accord.3.6.0
- Accord.Audio.3.6.0
- Accord.Math.3.6.0
- NAudio.1.8.0
All of these can be downloaded on your own system with nuget.