



文档简介
c#实现录音.txt我这辈子只有两件事不会:这也不会,那也不会。人家有的是背景,而我有的是背影。 肉的理想,白菜的命。肉的理想,白菜的命。白马啊你死去哪了!是不是你把王子弄丢了不敢来见我了。 本文由chongweiluo贡献 doc文档可能在WAP端浏览体验不佳。建议您优先选择TXT,或下载源文件到本机查看。 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. 对外操作的函数 / / 构造函数,设定录音设备,设定录音格式. / public SoundRecord() / 初始化音频捕捉设备 InitCaptureDevice(); / 设定录音格式 mWavFormat = CreateWaveFormat(); / / 设定录音结束后保存的文件,包括路径 / / 保存 wav 文件的路径名 public void SetFileName(string filename) mFileName = filename; / / 开始录音 / public void RecStart() / 创建录音文件 CreateSoundFile(); / 创建一个录音缓冲区,并开始录音 CreateCaptureBuffer(); / 建立通知消息,当缓冲区满的时候处理方法 InitNotifications(); mRecBuffer.Start(true); / / 停止录音 / public void RecStop() / 关闭通知消息 if (null != mNotificationEvent) mNotificationEvent.Set(); / 停止录音 mRecBuffer.Stop(); / 写入缓冲区最后的数据 RecordCapturedData(); / 回写长度信息 mWriter.Seek(4, SeekOrigin.Begin); mWriter.Write(int)(mSampleCount + 36); mWriter.Seek(40, SeekOrigin.Begin); / 写文件长度 mWriter.Write(mSampleCount); / 写数据长度 mWriter.Close(); mWaveFile.Close(); mWriter = null; mWaveFile = null; 4.内部调用函数 / / 初始化录音设备,此处使用主录音设备. / / 调用成功返回 true,否则返回 false private bool InitCaptureDevice() / 获取默认音频捕捉设备 CaptureDevicesCollection devices = new CaptureDevicesCollection(); / 枚举音频捕 捉设备 Guid deviceGuid = Guid.Empty; 捉设备的 ID / 音频捕 if (devices.Count0) deviceGuid = devices0.DriverGuid; else MessageBox.Show(系统中没有音频捕捉设备); return false; / 用指定的捕捉设备创建 Capture 对象 try mCapDev = new Capture(deviceGuid); catch (DirectXException e) MessageBox.Show(e.ToString(); return false; return true; / / 创建录音格式,此处使用 16bit,16KHz,Mono 的录音格式 / / WaveFormat 结构体 private WaveFormat CreateWaveFormat() WaveFormat format = new WaveFormat(); format.FormatTag = WaveFormatTag.Pcm; format.SamplesPerSecond = 16000; format.BitsPerSample = 16; format.Channels = 1; / PCM / 16KHz / 16Bit / Mono format.BlockAlign = (short)(format.Channels * (format.BitsPerSample / 8); format.AverageBytesPerSecond = format.BlockAlign * format.SamplesPerSecond; return format; / / 创建录音使用的缓冲区 / private void CreateCaptureBuffer() / 缓冲区的描述对象 CaptureBufferDescription bufferdescription = new CaptureBufferDescription(); if (null != mNotify) mNotify.Dispose(); mNotify = null; if (null != mRecBuffer) mRecBuffer.Dispose(); mRecBuffer = null; / 设定通知的大小,默认为 1s 钟 mNotifySize = (1024 mWavFormat.AverageBytesPerSecond / 8) ? 1024 : (mWavFormat.AverageBytesPerSecond / 8); mNotifySize -= mNotifySize % mWavFormat.BlockAlign; / 设定缓冲区大小 mBufferSize = mNotifySize * cNotifyNum; / 创建缓冲区描述 bufferdescription.BufferBytes = mBufferSize; bufferdescription.Format = mWavFormat; / 录音格式 / 创建缓冲区 mRecBuffer = new CaptureBuffer(bufferdescription, mCapDev); mNextCaptureOffset = 0; / / 初始化通知事件,将原缓冲区分成 16 个缓冲队列,在每个缓冲队列的结束点设定通知点. / / 是否成功 private bool InitNotifications() if (null = mRecBuffer) MessageBox.Show(未创建录音缓冲区); return false; / 创建一个通知事件,当缓冲队列满了就激发该事件. mNotificationEvent = new AutoResetEvent(false); / 创建一个线程管理缓冲区事件 if (null = mNotifyThread) mNotifyThread = new Thread(new ThreadStart(WaitThread); mNotifyThread.Start(); / 设定通知的位置 BufferPositionNotify PositionNotify = new BufferPositionNotifycNotifyNum + 1; for (int i = 0; i cNotifyNum; i+) PositionNotifyi.Offset = (mNotifySize * i) + mNotifySize - 1; PositionNotifyi.EventNotifyHandle = mNotificationEvent.Handle; mNotify = new Notify(mRecBuffer); mNotify.SetNotificationPositions(PositionNotify, cNotifyNum); return true; / / 将录制的数据写入 wav 文件 / private void RecordCapturedData() byte CaptureData = null; int ReadPos; int CapturePos; int LockSize; mRecBuffer.GetCurrentPosition(out CapturePos, out ReadPos); LockSize = ReadPos - mNextCaptureOffset; if (LockSize 0) LockSize += mBufferSize; / 对齐缓冲区边界,实际上由于开始设定完整,这个操作是多余的. LockSize -= (LockSize % mNotifySize); if (0 = LockSize) return; / 读取缓冲区内的数据 CaptureData = (byte)mRecBuffer.Read(mNextCaptureOffset, typeof(byte), LockFlag.None, LockSize); / 写入 Wav 文件 mWriter.Write(CaptureData, 0, CaptureData.Length); / 更新已经录制的数据长度. mSampleCount += CaptureData.Length; / 移动录制数据的起始点,通知消息只负责指示产生消息的位置,并不记录上次录制的 位置 mNextCaptureOffset += CaptureData.Length; mNextCaptureOffset %= mBufferSize; / Circular buffer / / 接收缓冲区满消息的处理线程 / private void WaitThread() while(true) / 等待缓冲区的通知消息 mNotificationEvent.WaitOne(Timeout.Infinite, true); / 录制数据 RecordCapturedData(); / / 创建保存的波形文件,并写入必要的文件头. / private void CreateSoundFile() /* Here is where the file will be created. A wave file is a RIFF file, which has chunks of data that describe what the file contains. A wave RIFF file is put together like this: The 12 byte RIFF chunk is constructed like this: Bytes 0 - 3 : R I F F Bytes 4 - 7 : Length of file, minus the first 8 bytes of the RIFF description. (4 bytes for WAVE + 24 bytes for format chunk length + 8 bytes for data chunk description + actual sample data size.) Bytes 8 - 11: W A V E The 24 byte FORMAT chunk is constructed like this: Bytes 0 - 3 : f m t Bytes 4 - 7 : The format chunk length. This is always 16. Bytes 8 - 9 : File padding. Always 1. Bytes 10- 11: Number of channels. Either 1 for mono, or 2 for stereo. Bytes 12- 15: Sample rate. Bytes 16- 19: Number of bytes per second. Bytes 20- 21: Bytes per sample. 1 for 8 bit mono, 2 for 8 bit stereo or 16 bit mono, 4 for 16 bit stereo. Bytes 22- 23: Number of bits per sample. The DATA chunk is constructed like this: Bytes 0 - 3 : d a t a Bytes 4 - 7 : Length of data, in bytes. Bytes 8 -: Actual sample data. */ / Open up the wave file for writing. mWaveFile = new FileStream(mFileName, FileMode.Create); mWriter = new BinaryWriter(mWaveFile); / Set up file with RIFF chunk info. char ChunkRiff = R,I,F,F; char ChunkType = W,A,V,E; char ChunkFmt = f,m,t, ; char ChunkData = d,a,t,a; short shPad = 1; int nLength = 0; This will be filled in later. short shBytesPerSample = 0; / 一个样本点的字节数目 if (8 = mWavFormat.BitsPerSample & 1 = mWavFormat.Channels) shBytesPerSample = 1; else if (8 = mWavFormat.BitsPerSample & 2 = mWavFormat.Channels) | (16 = mWavFormat.BitsPerSample & 1 = mWavFormat.Channels) shBytesPerSample = 2; else if (16 = mWavFormat.BitsPerSample & 2 = mWavFormat.Channels) shBytesPerSample = 4; / RIFF 块 mWriter.Write(ChunkRiff); mWriter.Write(nLength); mWriter.Write(ChunkType); / WAVE 块 mWriter.Write(ChunkFmt); mWriter.Write(nFormatChunkLength); mWriter.Write(shPad); / Bytes per sample. / File padding / File length, minus first 8 bytes of RIFF description. int nFormatChunkLength = 0x10; / Format chunk length. mWriter.Write(mWavFormat.Channels); mW
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 滤波补偿技术方案
- 2025年建材购销合同书样本5篇
- 2025终止土地承包合同
- 2025珠宝销售服务合同
- 2025年二人合伙投资合同范本
- 2025年wps考试题及答案
- 南京彩钢防水漆施工方案
- 内蒙古智能酒店施工方案
- 回民区高端宾馆施工方案
- 吉林长春不锈钢施工方案
- 雪花啤酒终端销售协议书
- 生产风险管理
- 钛镁合金合同协议
- 2025年人保车险考试题及答案
- 《茉莉花》音乐课件
- 2025年云南省职教高考电工技术类《电工基础理论知识》考试复习题库(含答案)
- 工厂交叉作业安全管理协议书(2篇)
- 外墙真石漆工程安全文明施工保证措施及环境保护体系和保证措施
- 品管圈PDCA改善案例-产科联合多部门降低阴道分娩产后出血发生率
- 矿井火灾防治理论与技术课件
- 【MOOC】生命的教育-浙江大学 中国大学慕课MOOC答案
评论
0/150
提交评论