0

我正在尝试在 Audacity 中复制 Plot Spectrum,但我的输出与 Audacity 的输出不匹配。

我正在使用 NAudio 将 WAV 转换为 PCM 样本,然后对连续块进行 FFT 并将块的 FFT 平均在一起。最后,我使用 Scott Plot 来可视化 Plot Spectrum。下面是我的代码。请让我知道我在哪里犯了错误。

音频:

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();
        }
4

0 回答 0