C# NAudio 音频库
- NAudio安装
- NAudio简述
- 简单示例1
- 录制麦克风
- 录制系统声卡
- WAV格式播放
- MP3格式播放
- AudioFileReader读取播放音频
- MediaFoundationReader 读取播放音频
NAudio安装
项目=>NuGet包管理器 搜索NAudio点击安装,自动安装依赖库。
安装成功后工具箱会新增NAudio.WinForms控件
NAudio简述
NAudio为.NET平台下的开源库,采用ML-PL协议,开源地址:https://github.com/naudio/NAudio支持多种音频操作,可实现多种API播放与录制、多种不同音频格式、音频格式转换(重采样、位深、声道等)、音频编码、多通道播放、音频效果处理等等。
快速入门
深入研究
常用类:
- WaveIn 表示波形输入, 继承了 IWaveIn, 例如麦克风输入, 或者计算机正在播放的音频流。
- WaveOut 表示波形输出, 继承了 IWavePlayer, 用来播放音频, 以 IWaveProvider 作为播放源播放音频, 通过拓展方法也支持以 ISampleProvider 作为播放源播放音频。
- WaveStream 表示波形流, 它继承了 IWaveProvider, 可以用来作为播放源。
- WaveFileReader 继承了 WaveStream, 用来读取波形文件。
- WaveFileWriter 继承了Stream, 用来写入文件, 常用于保存音频录制的数据。
- AudioFileReader 通用的音频文件读取器, 可以读取波形文件, 也可以读取其他类型的音频文件例如 Aiff, MP3
常用接口:
- IWaveProvider 波形提供者, 上面已经提到, 是音频播放的提供者, 通过拓展方法可以转换为 ISampleProvider。
- ISampleProvider 采样提供者, 上面已经提到, 通过拓展方法可以作为 WaveOut 的播放源。
简单示例1
自定义录音机类:Recorder.cs
using NAudio.Wave;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NAudioDemo
{
internal class Recorder
{
public WaveIn mWaveIn;
public WaveFileWriter mWaveFileWriter;
public int secondsRecorded;
/// <summary>
/// 开始录音
/// </summary>
/// <param name="filePath"></param>
public void RecorderStart(string filePath)
{
// 创建WaveIn对象
mWaveIn = new WaveIn();
// 添加DataAvailable事件处理回调
mWaveIn.DataAvailable += OnDataAvailable;
// 创建WaveFileWriter对象
mWaveFileWriter = new WaveFileWriter(filePath, mWaveIn.WaveFormat);
// 开始录音
mWaveIn.StartRecording();
}
/// <summary>
/// 停止录音
/// </summary>
public void RecorderStop()
{
mWaveIn?.StopRecording();
mWaveIn?.Dispose();
mWaveFileWriter?.Close();
mWaveFileWriter = null;
}
/// <summary>
/// 录音数据回调
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnDataAvailable(object sender, WaveInEventArgs e)
{
// 写入录音数据
mWaveFileWriter.Write(e.Buffer, 0, e.BytesRecorded);
// 计算已录制的秒数
secondsRecorded = (int)mWaveFileWriter.Length / mWaveFileWriter.WaveFormat.AverageBytesPerSecond;
}
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using NAudio.Wave;
using System.Drawing.Text;
using System.Media;
using NAudio.Dsp;
namespace NAudioDemo
{
public partial class Form1 : Form
{
// 创建录音机类实例
Recorder recorder = new Recorder();
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
button1.Enabled = false;
button2.Enabled = true;
recorder.RecorderStart(@"D:\1.wav");
}
private void button2_Click(object sender, EventArgs e)
{
button1.Enabled = true;
button2.Enabled = false;
recorder.RecorderStop();
}
private void button3_Click(object sender, EventArgs e)
{
SoundPlayer player = new SoundPlayer(@"D:\1.wav");
player.Play();
}
}
}
录制麦克风
-
借助 WaveIn 类, 我们可以轻易的捕获麦克风输入, 在每一次录制到数据时, 将数据写入到文件或其他流, 这就实现了保存录音
-
在保存波形文件时需要借助 WaveFileWriter, 当然, 如果你想保存为其他格式, 也可以使用其它的 Writer, 例如 CurWaveFileWriter 以及AiffFileWriter, 美中不足的是没有直接写入到 MP3 的 FileWriter
-
需要注意的是, 桌面程序可以直接使用 WaveIn, 其回调基于 Windows 消息, 所以无法在控制台应用中使用 WaveIn
-
如果要在控制台应用中实现录音, 只需要使用 WaveInEvent, 它的回调基于事件而不是 Windows 消息, 所以可以通用
-
示例代码:
WaveIn cap = new WaveIn(); // cap, capture
WaveFileWriter writer = new WaveFileWriter();
cap.DataAvailable += (s, args) => writer.Write(args.Buffer, 0, args.BytesRecorded); // 订阅事件
cap.StartRecording(); // 开始录制
cap.StopRecording(); // 停止录制
writer.Close(); // 关闭 FileWriter, 保存数据 -
另外, 除了使用 WaveIn, 你还可以使用 WasapiCapture, 它与 WaveIn 的使用方式是一致的, 可以用来录制麦克风
-
Wasapi 全称 Windows Audio Session Application Programming Interface (Windows音频会话应用编程接口)
-
具体 WaveIn, WaveInEvent, WasapiCapture 的性能, 笔者还没有测试过, 但估计不会有太大差异.
-
提示: WasapiCapture 和 WasapiLoopbackCapture 位于 NAudio.Wave 命名空间下
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using NAudio;
using NAudio.Wave;
namespace NAudioDemo2
{
public partial class Form2 : Form
{
private WaveIn waveIn = null;
private WaveFileWriter writer = null;
public Form2()
{
InitializeComponent();
button2.Enabled = false;
button3.Enabled = false;
}
/// <summary>
/// 设置保存文件名称
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button1_Click(object sender, EventArgs e)
{
saveFileDialog1.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
saveFileDialog1.Filter = "audio files (*.wav)|*.wav| all files (*.*)|*.*"; // 文件类型过滤
saveFileDialog1.DefaultExt = "*.wav"; // 默认文件扩展名
//saveFileDialog1.FileName = "1.wav"; // 默认文件名
if (saveFileDialog1.ShowDialog() == DialogResult.OK)
{
string fName = saveFileDialog1.FileName; // 获取文件名
textBox1.Text = fName;
button2.Enabled = true;
}
}
/// <summary>
/// 开始录音
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button2_Click(object sender, EventArgs e)
{
//waveIn = new WaveIn { WaveFormat = new WaveFormat(44100, 1) };
waveIn = new WaveIn();
waveIn.WaveFormat = new WaveFormat(44100, 1);
writer = new WaveFileWriter(textBox1.Text.Trim(), waveIn.WaveFormat);
waveIn.DataAvailable += (s, args) => writer.Write(args.Buffer, 0, args.BytesRecorded);
waveIn.StartRecording();
button2.Enabled = false;
button3.Enabled = true;
}
/// <summary>
/// 停止录音
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button3_Click(object sender, EventArgs e)
{
waveIn.StopRecording();
waveIn.Dispose();
waveIn = null;
writer.Flush();
writer.Close();
writer.Dispose();
button2.Enabled = true;
button3.Enabled = false;
}
}
}
录制系统声卡
录制声卡输出, 也就是录制计算机正在播放的声音, 借助 WasapiLoopbackCapture 即可简单实现, 使用方式与 WasapiCapture 无异
WasapiLoopbackCapture cap = new WasapiLoopbackCapture();
WaveFileWriter writer = new WaveFileWriter();
cap.DataAvailable += (s, args) => writer.Write(args.Buffer, 0, args.BytesRecorded);
cap.StartRecording();
using NAudio.Wave;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace NAudioDemo2
{
public partial class Form3 : Form
{
private WasapiLoopbackCapture loopCap = new WasapiLoopbackCapture();
private WaveFileWriter fileWriter;
public Form3()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
SaveFileDialog saveFileDialog = new SaveFileDialog();
saveFileDialog.Filter = "wave file *.wav|*.wav|all filse *.*|*.*";
saveFileDialog.DefaultExt = ".wav";
if (saveFileDialog.ShowDialog() == DialogResult.OK)
{
string fName = saveFileDialog.FileName;
textBox1.Text = fName;
}
}
/// <summary>
/// 录制声卡开始
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button2_Click(object sender, EventArgs e)
{
fileWriter = new WaveFileWriter(textBox1.Text.Trim(), loopCap.WaveFormat) ;
loopCap.DataAvailable += (s, args) => fileWriter.Write(args.Buffer, 0, args.BytesRecorded);
loopCap.StartRecording();
}
/// <summary>
/// 录制声卡停止
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button3_Click(object sender, EventArgs e)
{
loopCap.StopRecording();
fileWriter.Flush();
fileWriter.Close();
fileWriter.Dispose();
}
}
}
WAV格式播放
NAudio 中, 通过 WaveFileReader 来读取波形数据, 在实例化时, 你可以指定文件名或者是输入流, 这意味着你可以读取内存流中的音频数据.
WaveFileReader reader = new WaveFileReader(filepath);
WaveOut wout = new WaveOut();
wout.Init(reader); // 通过 IWaveProvider 为音频输出初始化
wout.Play(); // 至此, wout 将从指定的 reader 中提供的数据进行播放
using NAudio.Wave;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace NAudioDemo2
{
public partial class Form4 : Form
{
private WaveOut wout_wav;
WaveFileReader reader;
public Form4()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = "audio file *.wav|*.wav";
ofd.DefaultExt = "*.wav";
if (ofd.ShowDialog() == DialogResult.OK)
{
string fName = ofd.FileName;
textBox1.Text = fName;
}
}
private void button2_Click(object sender, EventArgs e)
{
reader = new WaveFileReader(textBox1.Text.Trim());
wout_wav = new WaveOut();
wout_wav.Init(reader);
wout_wav.Play();
}
private void button3_Click(object sender, EventArgs e)
{
wout_wav.Pause();
}
private void button4_Click(object sender, EventArgs e)
{
wout_wav.Resume();
}
private void button5_Click(object sender, EventArgs e)
{
wout_wav.Stop();
wout_wav.Dispose();
reader.Close();
}
}
}
MP3格式播放
播放 MP3 音乐其实与播放波形音乐没有太大区别, 只不过将 WaveFileReader 换成Mp3FileReader 罢了
Mp3FileReader reader = new Mp3FileReader(filepath);
WaveOut wout = new WaveOut();
wout.Init(reader);
wout.Play();
using NAudio.Wave;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace NAudioDemo2
{
public partial class Form5 : Form
{
Mp3FileReader reader;
WaveOut wout_mp3;
public Form5()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = "audio file *.mp3|*.mp3";
ofd.DefaultExt = "*.mp3";
if (ofd.ShowDialog() == DialogResult.OK)
{
string fName = ofd.FileName;
textBox1.Text = fName;
}
}
private void button2_Click(object sender, EventArgs e)
{
reader = new Mp3FileReader(textBox1.Text);
wout_mp3 = new WaveOut();
wout_mp3.Init(reader);
wout_mp3.Play();
}
private void button3_Click(object sender, EventArgs e)
{
wout_mp3.Pause();
}
private void button4_Click(object sender, EventArgs e)
{
wout_mp3.Resume();
}
private void button5_Click(object sender, EventArgs e)
{
wout_mp3.Stop();
wout_mp3.Dispose();
reader.Close();
reader.Dispose();
}
}
}
AudioFileReader读取播放音频
通过AudioFileReader读取音频文件可以播放.mp3, .wav, .flac等多种格式
AudioFileReader reader = new AudioFileReader (@“d:\1.mp3”);
WaveOut wout = new WaveOut ();
wout.Init(reader );
wout.Play();
wout.Pause();
wout.Resume();
wout.Stop();
using NAudio.Wave;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace NAudioDemo2
{
public partial class Form6 : Form
{
AudioFileReader reader;
WaveOut wout;
public Form6()
{
InitializeComponent();
}
private void Form6_Load(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = "audio file *.mp3|*.mp3|all files *.*|*.*";
if (ofd.ShowDialog() == DialogResult.OK)
{
string fName = ofd.FileName;
textBox1.Text = fName;
}
}
private void button2_Click(object sender, EventArgs e)
{
reader = new AudioFileReader(textBox1.Text.Trim());
wout = new WaveOut();
wout.Init(reader);
wout.Play();
}
private void button3_Click(object sender, EventArgs e)
{
wout.Pause();
}
private void button4_Click(object sender, EventArgs e)
{
wout.Resume();
}
private void button5_Click(object sender, EventArgs e)
{
wout.Stop();
wout.Dispose();
reader.Close();
reader.Dispose();
}
}
}
MediaFoundationReader 读取播放音频
通过MediaFoundationReader 读取音频文件可以播放.mp3, .wav, .flac等多种格式
MediaFoundationReader reader = new MediaFoundationReader (@“d:\1.mp3”);
WaveOut wout = new WaveOut ();
wout.Init(reader );
wout.Play();
wout.Pause();
wout.Resume();
wout.Stop();
using NAudio.Wave;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace NAudioDemo2
{
public partial class Form7 : Form
{
MediaFoundationReader reader;
WaveOut wout;
public Form7()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = "audio file *.mp3|*.mp3|all files *.*|*.*";
ofd.DefaultExt = "*.mp3";
if (ofd.ShowDialog() == DialogResult.OK)
{
string fName = ofd.FileName;
textBox1.Text = fName;
}
}
private void button2_Click(object sender, EventArgs e)
{
reader = new MediaFoundationReader(textBox1.Text.Trim());
wout = new WaveOut();
wout.Init(reader);
wout.Play();
}
private void button3_Click(object sender, EventArgs e)
{
wout.Pause();
}
private void button4_Click(object sender, EventArgs e)
{
wout.Resume();
}
private void button5_Click(object sender, EventArgs e)
{
wout.Stop();
wout.Dispose();
reader.Close();
reader.Dispose();
}
}
}