C# 中使用DirectSound录音
一,声卡录音的基本原理
为了实现一个录音的基本过程,至少需要以下对象的支持:
1.录音设备,对我们的PC设备就是声卡。这个录音设备可以进行的操作应该有开始和关闭。
2.缓冲区,也就是我们录制的声音放在哪里的问题。
二,DirectSound对录音的描述模型
1.DirectSound对录音的支持类
Capture,设备对象,可以看作是声卡的描述。
CaptureBuffer,缓冲区对象,存放录入的音频数据。
Notify,事件通知对象,由于录音是一个长时间的过程,因此使用一个缓冲队列(多个缓冲区)接受数据,每当一个缓冲区满的时候,系统使用这个对象通知应用程序取走这个缓冲区,并继续录音。
以上三个对象是进行录音操作的主要对象,由于在C++中队DirectSound的操作DirectX帮助文档中已经有很详细的说明,这里就不再赘述了。本文主要是针对Managed Code。除了以上三个主要的DirectSound类,还需要以下几个辅助类。
WaveFormat,描述了进行录制的声音波形的格式,例如采样率,单声道还是立体声,每个采样点的长度等等。
Thread,线程类,由于录音的过程是需要不断处理缓冲区满的事件,因此新建一个线程对此进行单独处理。
AutoResetEvent,通知的事件,当缓冲区满的时候,使用该事件作为通知事件。
三,代码解析(SoundRecord类)
1.需要引用的程序集
using System;
using System.Windows.Forms;
using System.Threading;
using System.IO;
//对DirectSound的支持
using Microsoft.DirectX;
using Microsoft.DirectX.DirectSound;
2.SoundRecord的成员数据
public const int cNotifyNum = 16; // 缓冲队列的数目
private int mNextCaptureOffset = 0; // 该次录音缓冲区的起始点
private int mSampleCount = 0; // 录制的样本数目
private int mNotifySize = 0; // 每次通知大小
private int mBufferSize = 0; // 缓冲队列大小
private string mFileName = string.Empty; // 文件名
private FileStream mWaveFile = null; // 文件流
private BinaryWriter mWriter = null; // 写文件
private Capture mCapDev = null; // 音频捕捉设备
private CaptureBuffer mRecBuffer = null; // 缓冲区对象
private Notify mNotify = null; // 消息通知对象
private WaveFormat mWavFormat; // 录音的格式
private Thread mNotifyThread = null; // 处理缓冲区消息的线程
private AutoResetEvent mNotificationEvent = null; // 通知事件
3.对外操作的函数
/// <summary>
/// 构造函数,设定录音设备,设定录音格式
/// </summary>
public SoundRecord1()
{
//初始化录音设备
InitCaptureDevice();
//设定录音格式
mWavFormat = CreateWaveFormat();
}
/// <summary>
/// 设定录音结束后保存的文件,包括路径
/// </summary>
/// <param name="filename"></param>
public void SetFileName(string filename)
{
mFileName = filename;
}
/// <summary>
/// 开始录音
/// </summary>
public void RecStart()
{
//创建录音文件
CreateSoundFile();
//创建一个录音缓冲区,并开始录音
CreateCaptureBuffer();
//建立通知消息,当缓冲区满的时候处理方法
InitNotifications();
mRecBuffer.Start(true);
}
/// <summary>
/// 停止录音
/// </summary>
public void RecStop()
{
// 关闭通知消息
if (null != mNotificationEvent)
mNotificationEvent.Set();