现在的位置: 首页 > 综合 > 正文

C# DirectSound录音类

2011年04月15日 ⁄ 综合 ⁄ 共 6073字 ⁄ 字号 评论关闭

一.声卡录音的基本原理 

为了实现一个录音的基本过程,至少需要以下对象的支持: 

1.   录音设备,对我们的PC设备就是声卡。这个录音设备可以进行的操作应该有开始和关闭。 

2.   缓冲区,也就是录制的声音放在哪里的问题。

二.DirectSound对录音的描述模型 

1.   DirectSound对录音的支持类 

     Capture,设备对象,可以看作是声卡的描述。 

     CaptureBuffer,缓冲区对象,存放录入的音频数据。 

     Notify,事件通知对象,由于录音是一个长时间的过程,因此使用一个缓冲队列(多个缓冲区)接收数据,每当一个缓冲区满的时候,系统使用这个对象通知应用程序取走这个缓冲区,并继续录音。

以上三个对象是进行录音操作的主要对象,由于在C++中对DirectSound的操作DirectX帮助文档中已经有很详细的说明,这里就不再赘述了。本文是针对Managed Code。除了以上三个主要的DirectSound类,还需要以下几个辅助类。 

     WaveFormat,描述了进行录制的声音波形的格式,例如采样率,单声道还是立体声,每个采样点的长度等等。 

     Thread,线程类,由于录音的过程是需要不断处理缓冲区满的事件,因此新建一个线程对此进行单独处理。

     AutoResetEvent,通知的事件,当缓冲区满的时候,使用该事件作为通知事件。

 

 

 

 


  1using System;
  2using System.Collections.Generic;
  3using System.Text;
  4using System.IO;
  5using System.Windows.Forms;
  6using System.Threading;
  7using Microsoft.DirectX;
  8using Microsoft.DirectX.DirectSound;
  9namespace pcd.DirectSound
 10{
 11    /// <summary>
 12    /// 录音
 13    /// </summary>

 14    public class SoundRecord
 15    {
 16        //SoundRecord的成员数据
 17        public const int cNotifyNum = 16;       // 缓冲队列的数目
 18        private int mNextCaptureOffset = 0;      // 该次录音缓冲区的起始点
 19        private int mSampleCount = 0;            // 录制的样本数目
 20        private int mNotifySize = 0;             // 每次通知大小 
 21        private int mBufferSize = 0;             // 缓冲队列大小
 22        private string mFileName = string.Empty;     // 文件名 
 23        private FileStream mWaveFile = null;         // 文件流 
 24        private BinaryWriter mWriter = null;         // 写文件
 25        private Capture mCapDev = null;              // 音频捕捉设备 
 26        private CaptureBuffer mRecBuffer = null;     // 缓冲区对象 
 27        private Notify mNotify = null;               // 消息通知对象
 28        private WaveFormat mWavFormat;                       // 录音的格式 
 29        private Thread mNotifyThread = null;                 // 处理缓冲区消息的线程 
 30        private AutoResetEvent mNotificationEvent = null;    // 通知事件 
 31
 32        构造函数 构造函数
 33        /// <summary> 
 34        /// 构造函数,设定录音设备,设定录音格式. 
 35        /// </summary> 

 36        public SoundRecord()
 37        {
 38            // 初始化音频捕捉设备 
 39            InitCaptureDevice();
 40            // 设定录音格式 
 41            mWavFormat = CreateWaveFormat();
 42        }

 43        #endregion

 44
 45        公开方法 公开方法
 46        /// <summary> 
 47        /// 设定录音结束后保存的文件,包括路径 
 48        /// </summary> 
 49        /// <param name="filename">保存wav文件的路径名</param> 

 50        public void SetFileName(string filename)
 51        {
 52            mFileName = filename;
 53        }

 54        /// <summary> 
 55        /// 开始录音 
 56        /// </summary> 

 57        public void RecStart()
 58        {
 59
 60            // 创建录音文件 
 61            CreateSoundFile();
 62            // 创建一个录音缓冲区,并开始录音 
 63            CreateCaptureBuffer();
 64            // 建立通知消息,当缓冲区满的时候处理方法 
 65            InitNotifications();
 66            mRecBuffer.Start(true);
 67        }

 68
 69        /// <summary> 
 70        /// 停止录音 
 71        /// </summary>

 72        public void RecStop()
 73        {
 74            try
 75            {
 76                // 关闭通知消息
 77                if (null != mNotificationEvent)
 78                    mNotificationEvent.Set();
 79                // 停止录音
 80                mRecBuffer.Stop();
 81                // 写入缓冲区最后的数据 
 82                RecordCapturedData();
 83                // 回写长度信息 
 84                mWriter.Seek(4, SeekOrigin.Begin);
 85                mWriter.Write((int)(mSampleCount + 36));   // 写文件长度 
 86                mWriter.Seek(40, SeekOrigin.Begin);
 87                mWriter.Write(mSampleCount);                // 写数据长度 
 88                mWriter.Close();
 89                mWaveFile.Close();
 90                mWriter = null;
 91                mWaveFile = null;
 92            }

 93            catch
 94            { }
 95        }

 96        #endregion

 97
 98        内部调用函数 内部调用函数
 99        /// <summary> 
100        /// 初始化录音设备,此处使用主录音设备. 
101        /// </summary> 
102        /// <returns>调用成功返回true,否则返回false</returns>

103        private bool InitCaptureDevice()
104        {
105            // 获取默认音频捕捉设备
106            CaptureDevicesCollection devices = new CaptureDevicesCollection();  // 枚举音频捕捉设备 
107            Guid deviceGuid = Guid.Empty;                                       // 音频捕捉设备的ID
108            if (devices.Count > 0)
109                deviceGuid = devices[0].DriverGuid;
110            else
111            {
112                MessageBox.Show("系统中没有音频捕捉设备");
113                return false;
114            }

115            // 用指定的捕捉设备创建Capture对象 
116            try
117            {
118                mCapDev = new Capture(deviceGuid);
119            }

120            catch (DirectXException e)
121            {
122                MessageBox.Show(e.ToString());
123                return false;
124            }

125            return true;
126        }

127        /// <summary> 
128
129        /// 创建录音格式,此处使用16bit,16KHz,Mono的录音格式
130        /// </summary> 
131        /// <returns>WaveFormat结构体</returns> 

132        private WaveFormat CreateWaveFormat()
133        {
134            WaveFormat format = new WaveFormat();
135            format.FormatTag = WaveFormatTag.Pcm;   // PCM 
136            format.SamplesPerSecond = 16000;        // 16KHz 
137            format.BitsPerSample = 16;              // 16Bit 
138            format.Channels = 1;                    // Mono
139            format.BlockAlign = (short)(format.Channels * (format.BitsPerSample / 8));
140            format.AverageBytesPerSecond = format.BlockAlign * format.SamplesPerSecond;
141            return format;
142        }

143        /// <summary>
144        /// 创建录音使用的缓冲区 
145        /// </summary> 

146        private void CreateCaptureBuffer()
147        {
148            // 缓冲区的描述对象 
149            CaptureBufferDescription bufferdescription = new CaptureBufferDescription();
150            if (null != mNotify)
151            {
152                mNotify.Dispose();
153                mNotify = null;
154            }

155            if (null != mRecBuffer)
156            {
157                mRecBuffer.Dispose();
158                mRecBuffer = null;
159            }

160            // 设定通知的大小,默认为1s钟 
161

抱歉!评论已关闭.