I am currently coding a MusicPlayer with NAudio and XNA and I though it'd be a nice idea to visualize a diagram with the intensity of all the frequencies similar to the Monstercat videos (example). After a short internet search I found FFT and used the NAudio methods to implement that into my program. Then I tried to visualize the result but it does not nearly look like a frequency / amplitude diagram.
I did some tests with different frequencies from this video:
100Hz:
5kHz:
public static void UpdateWaveBuffer()
{
buffer = new byte[bufferLength];
WaveBuffer = new float[bufferLength / 4];
if (Channel32 != null && Channel32Reader != null)
{
// I have two WaveChannel32 objects, one to play the song and another
// that reads the data from the current position in realtime
// It's not the most efficient method but Im gonna improve that later
Channel32Reader.Position = Channel32.Position;
int Read = Channel32Reader.Read(buffer, 0, bufferLength);
// Converting the byte buffer in readable data
for (int i = 0; i < bufferLength / 4; i++)
WaveBuffer[i] = BitConverter.ToSingle(buffer, i * 4);
}
}
public static void UpdateFFTbuffer()
{
Complex[] tempbuffer = new Complex[WaveBuffer.Length];
for (int i = 0; i < tempbuffer.Length; i++)
{
tempbuffer[i].X = (float)(WaveBuffer[i] * FastFourierTransform.BlackmannHarrisWindow(i, WaveBuffer.Length));
tempbuffer[i].Y = 0;
}
FastFourierTransform.FFT(true, (int)Math.Log(tempbuffer.Length, 2.0), tempbuffer);
FFToutput = new float[tempbuffer.Length / 2 - 1];
for (int i = 0; i < FFToutput.Length; i++)
FFToutput[i] = (float)Math.Sqrt(tempbuffer[i].X * tempbuffer[i].X) + (tempbuffer[i].Y * tempbuffer[i].Y);
}
And the draw method:
// FFT Line Graph
if (VisSetting == Visualizations.fftline && Assets.Channel32 != null)
{
spriteBatch.Begin();
//float Length = Assets.FFToutput.Length / 2f;
float Length = Assets.FFToutput.Length;
// Shadow
for (int i = 0; i < Length; i++)
{
double value = Math.Sqrt(Assets.FFToutput[i]) * 1000;
if (value > 100)
value = 100;
Assets.DrawLine(new Vector2((i - 1) * Values.WindowSize.X / Length + 5,
Values.WindowSize.Y / 2f + (int)value + 5),
new Vector2(i * Values.WindowSize.X / Length + 5,
Values.WindowSize.Y / 2f - (int)value + 5),
2,
Color.Black * 0.6f,
spriteBatch);
}
for (int i = 0; i < Length; i++)
{
double value = Math.Sqrt(Assets.FFToutput[i]) * 1000;
if (value > 100)
value = 100;
Assets.DrawLine(new Vector2((i - 1) * Values.WindowSize.X / Length,
Values.WindowSize.Y / 2f + (int)value),
new Vector2(i * Values.WindowSize.X / Length,
Values.WindowSize.Y / 2f - (int)value),
2,
Color.Lerp(primaryColor, secondaryColor, i / Length),
spriteBatch);
}
spriteBatch.End();
}