我目前正在使用NAudio和XNA对MusicPlayer进行编码,虽然使用类似于Monstercat视频的所有频率的强度来显示图表是一个不错的主意(例如:watch?v = VGh5DV0D3wk) 。 经过短暂的互联网搜索后,我发现了FFT,并使用NAudio方法将其实现到我的程序中。然后我尝试将结果可视化,但它几乎不像频率/振幅图。
我使用此视频的不同频率进行了一些测试:观看?v = 4Av788P9stk 我想在这里添加图片,但我没有足够的声誉。
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);
}
}
绘制方法:
// 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();
}