2

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:
100hz

5kHz:
5000hz

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();
}
unknown6656
  • 2,765
  • 2
  • 36
  • 52
  • You seem to be taking the square root twice for some reason (once in the FFT code and then again in the draw method) ? Also one usually plots log magnitude, rather than linear, since human hearing is logarithmic (think dB). So you can drop the square root altogether and combine it with a log, e.g. `FFToutput[i] = 10.0 * Math.Log10(tempbuffer[i].X * tempbuffer[i].X) + (tempbuffer[i].Y * tempbuffer[i].Y);` – Paul R Apr 12 '17 at 18:51
  • @PaulR I was playing around with the output already. ^^ Using your logarithmic function resulted in FFToutput having mostly similar values. No sound was really recognizable... –  Apr 12 '17 at 20:43

0 Answers0