C# NAudio录音和播放音频文件-实时绘制音频波形图(从音频流数据获取,而非设备获取)

  NAudio的录音和播放录音都有对应的类,我在使用Wav格式进行录音和播放录音时使用的类时WaveIn和WaveOut,这两个类是对功能的回调和一些事件触发。

  在WaveIn和WaveOut之外还有对音频流读写使用的WaveFileWriter和WaveFileReader类,具体细节可查看其源码进行分析。

  其中绘制音频波形图根据录制和播放需要不同途径实现。

  1.录音时实时显示波形图,在录音时实时获取需要使用WaveIn.DataAvailable回调事件,在这个回调事件中会传递出音频流数据,数据类型Byte[],这就是音频内容

  但这个Byte数组需要还原为真实的数据,它的真实数据类型需根据PCM写入时的数据格式定,主要有8bit、16bit、24bit、32bit,如写入时是16bit就需将其转换为16bit数据

  然后根据WaveIn.WaveFormat的channels去获取音频波形值,然后输出出来,具体示例如下:

 private void waveSource_DataAvailable(object sender, WaveInEventArgs e)
        {
            if (waveFile != null)
            {
                waveFile.Write(e.Buffer, 0, e.BytesRecorded);
                waveFile.Flush();

               
                float[] sts = new float[e.Buffer.Length / channels];
                int outIndex = 0;
                for (int n = 0; n < e.Buffer.Length; n += channels)
                {
                    sts[outIndex++] = BitConverter.ToInt16(e.Buffer, n) / 32768f;
                }

                for (int n = 0; n < sts.Length; n += channels)
                {
                    Add(sts[n]);
                }
            }
        }

  其中Add()方法就是添加波形值到UI控件上的方法,可根据自己需求实现。 

 

 2.播放录音文件时显示波形图

  播放录音时需初始化AudioFileReader类,并传入需要播放的文件路径,并将这个类传入WaveOut类中,最后用继承自ISampleProvider的类加载和初始化调用Play方法,然后会调用到WaveOut类Read方法时,会可以使用AudioFileReader.Read()方法进行获取参数,获取的是float数组,可直接用于绘制波形图

   private void AnalysisRecord_Click(object sender, RoutedEventArgs e)
        {
           
            var inputStream = new AudioFileReader(recordList[0]);
            ISampleProvider aggregator = new NAudioReader(inputStream);
            aggregator.MaximumCalculated += Aggregator_MaximumCalculated;
            aggregator.Start();
            waveOutDevice.Init(aggregator);
            waveOutDevice.Volume = 0;
            waveOutDevice.PlaybackStopped += WaveOutDevice_PlaybackStopped;
            waveOutDevice.Play();
        }

 

public int Read(float[] buffer, int offset, int count)///这个函数是ISampleProvider调用的函数 
{ var samplesRead = source.Read(buffer, offset, count); for (int n = 0; n < samplesRead; n += channels) { Add(buffer[n + offset]); } return samplesRead; }

  至于绘制波形的WPF细节就在Demo中看吧,主要要注意WaveIn和WaveOut、WaveFileReader和WaveFileWriter相关内容,具体可下源码和Demo看下

  具体可调试示例如下:示例 (也是粗浅学习,可交流,轻拍砖)