C#使用NAudio的实时波形数据图

时间:2013-06-29 08:27:18

标签: c# naudio waveform real-time-data

我是处理wav文件和C#的新手。我的目标是在wavfile的波形中实时绘制数据。我的意思是在录制声音(wav)文件时,我想同时绘制它的图形。我搜索了一些声音的libiraries和决定使用NAudio。(不知道它是我的最佳选择。我对任何有关选择音频图书馆的建议持开放态度)。但是我不知道使用声音进行实时数据绘图。有些人建议使用GDI但是我说我是新手,我认为有效地使用GDI会花费太多时间。如果我必须学习GDI,请分享任何可以帮助像我这样的初学者的文章。其实我看起来不知道我应该从哪里开始。需要引导:))我有一个问题。

NAudio的教程之一,他使用字节数组来绘制Chart中的波形。如果你知道wav文件的大小,那就没问题了。但是它的工作速度太慢,并且对于更大的wav文件给出了Out of Memory Exception。 10mb。下面的代码指的是我的意思。

    OpenFileDialog open = new OpenFileDialog();
    open.Filter = "Wave File (*.wav)|*.wav;";
    if (open.ShowDialog() != DialogResult.OK) return;
    chart1.Series.Add("wave");
    chart1.Series["wave"].ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.FastLine;
    chart1.Series["wave"].ChartArea = "ChartArea1";
    NAudio.Wave.WaveChannel32 wave = new NAudio.Wave.WaveChannel32(new NAudio.Wave.WaveFileReader(open.FileName));

    byte[] buffer = new byte[426565];
    int read;
    while (wave.Position < wave.Length)
    {
        read = wave.Read(buffer, 0, 426565);
        for (int i = 0; i < read / 4; i++)
        {
            chart1.Series["wave"].Points.Add(BitConverter.ToSingle(buffer, i * 4));
        }
    }

有没有办法更快地执行此操作?

2 个答案:

答案 0 :(得分:4)

如果您绘制每个样本,最终会得到一个无法管理的大波形,因为音频通常每秒包含数千个样本。绘制波形的常用方法是在一段时间内选择最大值,然后绘制一条垂直线来表示它。例如,如果您有一首三分钟的歌曲,并且想要一个宽约600像素的波形,则每个像素将代表大约三分之一秒。因此,您可以在三分之一秒内找到最大的样本值,并使用它来绘制波形。

此外,在您的示例代码中,您正在读取奇数个字节。但由于这是浮点音频,因此应始终读取四个字节的倍数。

答案 1 :(得分:1)

这对我有用

            WaveChannel32 wave = new WaveChannel32(new WaveFileReader(txtWave.Text));
            int sampleSize = 1024;
            var bufferSize = 16384 * sampleSize;
            var buffer = new byte[bufferSize];
            int read = 0;
            chart.Series.Add("wave");
            chart.Series["wave"].ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.FastLine;
            chart.Series["wave"].ChartArea = "ChartArea1";
            while (wave.Position < wave.Length)
            {
                read = wave.Read(buffer, 0, bufferSize);
                for (int i = 0; i < read / sampleSize; i++)
                {
                    var point = BitConverter.ToSingle(buffer, i * sampleSize);

                    chart.Series["wave"].Points.Add(point);
                }
            }