已阅读5页,还剩6页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
微型计算机接口大作业DirectX录音程序的实现学院: 软件学院专业: 网络安全姓名: 学号: 2011年6月11日星期六程序简介该程序使用DirectX提供的DirectSound来,控制音频驱动程序的各种接口,来录制和储存WAV音频文件。使用接口举例DirectSound中Capture捕获器对象来获取音频捕捉设备DirectSound中的CaptureBuffer捕获缓存储存由音频捕获设备捕获的数据。DirectSound中Notify消息通知对象对象来对缓冲区进行记录和界限 。DirectSound中的WaveFormat设定录音的格式。WAV文件的二进制形式WAV文件头格式:虚拟地址数据长度类型描述00H4charRIFF标志04H4longint文件长度08H4charWAVE标志0CH4charfmt标志10H4过渡字节(不定)14H2int格式类别(10H为PCM形式的声音数据)16H2int通道数,单声道为1,双声道为218H2int采样率(每秒样本数),表示每个通道的播放速度,1CH4longint波形音频数据传送速率,其值为通道数每秒数据位数每样本的数据位数8。播放软件利用此值可以估计缓冲区的大小。20H2int数据块的调整数(按字节算的),其值为通道数每样本的数据位值8。播放软件需要一次处理多个该值大小的字节数据,以便将其值用于缓冲区的调整。22H2每样本的数据位数,表示每个声道中各个样本的数据位数。如果有多个声道,对每个声道而言,样本大小都一样。24H4char数据标记符data28H4longint语音数据的长度缓冲区指针缓冲区是存放音频数据的地方,并且它还提供了我们两个指针:读指针和捕捉指针。它们的位置按照相对于缓冲区起始位置的偏移量计算。读指针位于当前已经被完全捕捉到缓冲区的数据末尾。捕捉指针位于当前将要从硬件中复制的数据块的末尾。如果你想从缓冲区中读取数据,则只能从已经完全写入缓冲区的数据中读取,也就是说我们只能从偏移量小于读指针的地方读取。缓冲区通知时间相同的音频文件,WAVE文件会比其它格式的音频文件大得多,这是因为WAVE文件没有对数据进行压缩。如果录音的时候,不限制缓冲区大小,那么你录制很短的时间可能就会占用很多内存,说不定不过多久,你的2G内存就不够用了。因此我们必须对缓冲区的大小进行限制,而且当缓冲区满了之后,还可以重新从缓冲区起始处开始,用新的数据覆盖旧的数据。为保证不丢失旧的数据,那就得在旧的数据被覆盖之前,将它转移到其它地方。微软提供了“通知”的方法。在缓冲区中的某些位置处设置通知,当读指针到达通知位置的时候,就会触发相应的事件执行转移操作。捕获流程程序代码上述主要在RecordSound类中using System;using System.Collections.Generic;using System.Text;using System.Windows.Forms; using System.Threading; using System.IO;/ 对DirectSound的支持using Microsoft.DirectX; using Microsoft.DirectX.DirectSound;namespace _001 class 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; / 通知事件t / / 构造函数,设定录音设备,设定录音格式. / public SoundRecord() / 初始化音频捕捉设备 InitCaptureDevice(); / 设定录音格式 mWavFormat = CreateWaveFormat(); / / 设定录音结束后保存的文件,包括路径 / / 保存wav文件的路径名 public void SetFileName(string filename) mFileName = filename; / / 开始录音 / public void RecStart() / 创建录音文件t 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; / / 初始化录音设备,此处使用主录音设备 / / 调用成功返回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; / PCM format.SamplesPerSecond = 16000; / 16KHz format.BitsPerSample = 16; / 16Bit format.Channels = 1; / 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; / 设定通知的大小,默认为s 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() / 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; / File padding int nFormatChunkLength = 0x10; / Format chunk length. int nLength = 0; / File length, minus first 8 bytes of RIFF description. This will be filled in later. short shBytesPerSample = 0; / Bytes per sample. / 一个样本点的字节数目 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
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026年保密宣传月保密知识考试真题
- 2026年高考北京卷文综政治题库(含答案)
- 2026年保密教育线上培训考试题含答案(完整版)
- 吉林省双辽市八年级地理下册 8.1自然特征与农业教学设计 (新版)新人教版
- 本单元复习与测试教学设计初中综合实践活动八年级第一学期沪科版(贵州专用)
- 第18课 海陆兼备的多山省份教学设计-2025-2026学年小学地方、校本课程浙教版人·自然·社会
- 2026年装饰售后合同(1篇)
- 开学教学设计中职基础课-基础模块 下册-高教版(2023)-(语文)-50
- 初中语文人教部编版九年级下册渔家傲秋思教案设计
- 机器人辅助支气管镜诊疗技术专家共识重点2026
- 癌症患者生活质量量表EORTC-QLQ-C30
- (正式版)JB∕T 14732-2024 中碳和中碳合金钢滚珠丝杠热处理技术要求
- 核心素养视域下小学低学段古诗词教学策略研究
- 江苏省徐州市树人初级中学2023-2024学年八年级下学期5月月考生物试题
- MATLAB仿真实例(通信原理)
- 共享菜园未来趋势研究报告
- 玻璃纤维窗纱生产工艺流程
- 《功能材料介绍》课件
- 少先队辅导员主题宣讲
- 15ZJ001 建筑构造用料做法
- 国家级重点学科申报书
评论
0/150
提交评论