#c# #wpf #audio #fft #scottplot
Вопрос:
Я пытаюсь воспроизвести спектр сюжета в Audacity, но мои результаты не совпадают с результатами Audacity.
Я использую NAudio для преобразования WAV в образцы PCM, а затем БПФ последовательных блоков и усреднения БПФ блоков вместе. Наконец, я использую график Скотта для визуализации спектра графика. Ниже приведен мой код. Пожалуйста, дайте мне знать, где я допустил ошибку.
НАудио:
double[] ReadWav(string filePath)
{
using (AudioFileReader afr = new AudioFileReader(filePath))
{
sampleRate = afr.WaveFormat.SampleRate;
var bitsPerSample = afr.WaveFormat.BitsPerSample;
var sampleCount = (int)(afr.Length * 8 / bitsPerSample);
int channelCount = afr.WaveFormat.Channels;
audio = new List<double>(sampleCount);
var buffer = new float[sampleRate * channelCount];
int samplesRead = 0;
while ((samplesRead = afr.Read(buffer, 0, buffer.Length)) > 0)
{
audio.AddRange(buffer.Take(samplesRead).Select(x => (double)x));
}
double[] fft = new double[bufferSize];
counter = 0;
while (counter bufferSize <= audio.Count())
{
double[] pcm = audio.Skip(counter).Take(bufferSize).ToArray();
fft = fft.Zip(WindowedFFT(pcm), (x, y) => x y).ToArray();
counter = bufferSize;
}
fft = fft.Select(x => 10 * Math.Log10(x * bufferSize / counter)).ToArray();
fftReal = new double[bufferSize / 2];
Array.Copy(fft, fftReal, fftReal.Length);
fftPointSpacingHz = (double)sampleRate / (2 * bufferSize);
return audio.ToArray();
}
}
БПФ:
public double[] WindowedFFT(double[] data)
{
double[] wdata = new double[data.Length];
double[] hann = MathNet.Numerics.Window.Hamming(data.Length);
for (int i = 0; i < data.Length; i )
{
wdata[i] = hann[i] * data[i];
}
double[] fft = new double[data.Length];
System.Numerics.Complex[] fftComplex = new System.Numerics.Complex[data.Length];
for (int i = 0; i < data.Length; i )
{
fftComplex[i] = new System.Numerics.Complex(wdata[i], 0.0);
}
Accord.Math.FourierTransform.FFT(fftComplex, Accord.Math.FourierTransform.Direction.Forward);
for (int i = 0; i < data.Length; i )
{
fft[i] = fftComplex[i].Magnitude;
}
return fft;
}
Сюжет Скотта:
void Btn_Load_Click(object sender, RoutedEventArgs e)
{
s_graph.Plot.Clear();
s_graph.Plot.AddSignal(music_data, sampleRate);
s_graph.Plot.Title("Time Domain");
s_graph.Plot.XLabel("Time (seconds)");
s_graph.Plot.YLabel("Amplitude");
s_graph.Plot.AxisAuto(0);
s_graph.Configuration.LockVerticalAxis = true;
s_graph.Configuration.LockHorizontalAxis = true;
s_graph.Refresh();
s_graph_fft.Plot.Clear();
s_graph_fft.Plot.AddSignal(fftReal, fftPointSpacingHz);
s_graph_fft.Plot.Title("Frequency Domain");
s_graph_fft.Plot.XLabel("Frequency (Hz)");
s_graph_fft.Plot.YLabel("Amplitude");
s_graph_fft.Plot.AxisAuto(0);
s_graph_fft.Configuration.LockVerticalAxis = true;
s_graph_fft.Configuration.LockHorizontalAxis = true;
s_graph_fft.Refresh();
}