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看下
具体可调试示例如下:示例 (也是粗浅学习,可交流,轻拍砖)
写的比较乱,可跳转到下一篇,写的相对具体点