1、首先要使用Microsoft.DirectX.DirectSound和Microsoft.DirectX这两个dll进行录音,需要先安装microsoft directx 9.0cz这个组件,

百度云盘下载地址:http://pan.baidu.com/s/1bpgbdP9,里面包含安装程序和两个dll

2、编写录音程序功能

1)编写录音支持的辅助类SoundRecord

源码:

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.IO;
using Microsoft.DirectX;
using Microsoft.DirectX.DirectSound;

namespace SoundRecord
{
    public class SoundRecord
    {
        // 对DirectSound的支持
        int cNotifyNum = 16;       // 缓冲队列的数目
        int mNextCaptureOffset = 0;      // 该次录音缓冲区的起始点
        int mSampleCount = 0;            // 录制的样本数目
        int mNotifySize = 0;             // 每次通知大小
        int mBufferSize = 0;             // 缓冲队列大小
        string mFileName = string.Empty;     // 文件名
        FileStream mWaveFile = null;         // 文件流
        BinaryWriter mWriter = null;         // 写文件
        Capture mCapDev = null;              // 音频捕捉设备
        CaptureBuffer mRecBuffer = null;     // 缓冲区对象
        Notify mNotify = null;               // 消息通知对象
        WaveFormat mWavFormat;                       // 录音的格式
        Thread mNotifyThread = null;                 // 处理缓冲区消息的线程
        AutoResetEvent mNotificationEvent = null;    // 通知事件

/// <summary>
        /// 构造函数,设定录音设备,设定录音格式.
        /// </summary>
        public SoundRecord()
        {
            // 初始化音频捕捉设备
            InitCaptureDevice();
            // 设定录音格式
            mWavFormat = CreateWaveFormat();
        }

/// <summary>
        /// 设定录音结束后保存的文件,包括路径
        /// </summary>
        /// <param name="filename">保存wav文件的路径名</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();
            // 停止录音
            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;
        }

/// <summary>
        /// 初始化录音设备,此处使用主录音设备.
        /// </summary>
        /// <returns>调用成功返回true,否则返回false</returns>
        bool InitCaptureDevice()
        {
            // 获取默认音频捕捉设备
            CaptureDevicesCollection devices = new CaptureDevicesCollection(); // 枚举音频捕捉设备
            Guid deviceGuid = Guid.Empty;                                       // 音频捕捉设备的ID
            if (devices.Count>0)
                deviceGuid = devices[0].DriverGuid;

else
            {
                MessageBox.Show("系统中没有音频捕捉设备");
                return false;
            }

// 用指定的捕捉设备创建Capture对象
            try
            {
                mCapDev = new Capture(deviceGuid);
            }
            catch(DirectXException e)
            {
                MessageBox.Show(e.ToString());
                return false;
            }
            return true;
        }

/// <summary>
        /// 创建录音格式,此处使用16bit,16KHz,Mono的录音格式
        /// </summary>
        /// <returns>WaveFormat结构体</returns>
        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;
        }

/// <summary>
        /// 创建录音使用的缓冲区
        /// </summary>
        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;
        }

/// <summary>
        /// 初始化通知事件,将原缓冲区分成16个缓冲队列,在每个缓冲队列的结束点设定通知点.
        /// </summary>
        /// <returns>是否成功</returns>
        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 BufferPositionNotify[cNotifyNum + 1];
            for (int i = 0; i < cNotifyNum; i++)
            {
                PositionNotify[i].Offset = (mNotifySize * i) + mNotifySize - 1;
                PositionNotify[i].EventNotifyHandle = mNotificationEvent.Handle;               
            }

mNotify = new Notify(mRecBuffer);
            mNotify.SetNotificationPositions(PositionNotify, cNotifyNum);
            return true;
        }

/// <summary>
        /// 将录制的数据写入wav文件
        /// </summary>
        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
        }

/// <summary>
        /// 接收缓冲区满消息的处理线程
        /// </summary>
        private void WaitThread()
        {
            while(true)
            {
                // 等待缓冲区的通知消息
                mNotificationEvent.WaitOne(Timeout.Infinite, true);
                // 录制数据
                RecordCapturedData();
           }
        }

/// <summary>
        /// 创建保存的波形文件,并写入必要的文件头.
        /// </summary>
        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.Write(ChunkType);

// WAVE块
            mWriter.Write(ChunkFmt);
            mWriter.Write(nFormatChunkLength);
            mWriter.Write(shPad);
            mWriter.Write(mWavFormat.Channels);
            mWriter.Write(mWavFormat.SamplesPerSecond);
            mWriter.Write(mWavFormat.AverageBytesPerSecond);
            mWriter.Write(shBytesPerSample);
            mWriter.Write(mWavFormat.BitsPerSample);

// 数据块
            mWriter.Write(ChunkData);
            mWriter.Write((int)0);   // The sample length will be written in later.
        }
    }
}

2)调用方法的winform界面源码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

using System.Threading;
using System.IO;
using Microsoft.DirectX;
using Microsoft.DirectX.DirectSound;

namespace SoundRecord
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

private SoundRecord recorder = new SoundRecord();

private void btnStart_Click(object sender, EventArgs e)
        {
            string wavfile = null;
            wavfile = "test.wav";
            recorder.SetFileName(wavfile);
            recorder.RecStart();
        }

private void btnStop_Click(object sender, EventArgs e)
        {
            recorder.RecStop();
            recorder = null;
        }   
    }
}

3)winform界面图

4)生成后的录音文件,在项目bin目录下

5)用播放器播放录音文件

附录:

录音的demo源码下载地址:http://pan.baidu.com/s/1hslW5Je

运用Microsoft.DirectX.DirectSound和Microsoft.DirectX实现简单的录音功能的更多相关文章

  1. Microsoft.DirectX.DirectSound.dll和Microsoft.DirectX.dll引用,导致项目无法调试问题

    最近在做录音功能,用到了Microsoft.DirectX.DirectSound.dll和Microsoft.DirectX.dll两个dll,但是引入后,无法调试项目 具体解决方法: 修改app. ...

  2. Microsoft.DirectX.DirectSound学习(一)

    背景:为什么用到这个类库呢?公司要一个要播放音频文件(.wav)的功能,本来想着很ez的事,网上提供的jq插件.本地也有很多播放器,怎么用都行.可当我实现的时候发现大部分网上插件在火狐上不支持.wav ...

  3. C#调用Microsoft.DirectX.DirectSound问题记录及解决

    问题1:初始化结构体WaveFormat或其他变量时卡死 修改App.config,修改方法如下: 原App.config <?xml version="1.0" encod ...

  4. C#调用Microsoft.DirectX.DirectSound.dll时出错

    1.修改工程的编译选项.我的开发运行环境是Windows 10 x64系统.需要修改一下工程的编译选项,把AnyCPU改成x86的. 未能加载文件或程序集“Microsoft.DirectX.Dire ...

  5. DirectX.DirectSound声音播放资料

    参考:https://msdn.microsoft.com/en-us/library/windows/desktop/bb318665(v=vs.85).aspx Microsoft DirectS ...

  6. 需要正确安装 Microsoft.Windows.ShellExperienceHost 和 "Microsoft.Windows.Cortana" 应用程序。

    windows 10 开始菜单修复工具 Win10开始菜单修复工具出现的原因,自从升级到Windows  10,一直BUG不断,而其中有一个BUG非常的让你印象深刻,就是开始菜单无响应,你用着用着电脑 ...

  7. VS编程中找不到Microsoft.Office.Core、Microsoft.Office.Interop.Word和VBIDE

    在使用vs2005. vs2008. vs2010 制作包含 word等office的应用程序时,有时找不到对Microsoft.Office.Core. Microsoft.Office.Inter ...

  8. 未找到导入的项目“C:\Program Files\MSBuild\Microsoft\Silverlight\v5.0\Microsoft.Silverlight.CSharp.targets”。

    问题描述: 原先创建的Silverlight程序,后来系统重装了,再打开Silverlight程序时提示:C:\Users\yzg\Desktop\ocr\TJSilverlight\TJSilver ...

  9. An error occurred during the installation of assembly 'Microsoft.VC90.ATL or 'Microsoft.VC80.ATL'

    An error occurred during the installation of assembly 'Microsoft.VC90.ATL or 'Microsoft.VC80.ATL' 下载 ...

随机推荐

  1. 学习OpenGL简单易懂网站

    帅炸天的教程:欢迎来到OpenGL的世界

  2. Java开发者值得关注的7款新工具

    云计算.大数据地快速发展催生了不少热门的应用及工具.作为老牌语言Java,其生态圈也出来了一些有关云服务.监控.文档分享方面的工具.本文总结了7款较新的Java工具,大家不妨看下. 1. JClari ...

  3. jdbc无法连接数据解析

    1.网络原因 2.账户权限问题 账户是否赋予以下的权限: grant connect, resource to ADM_BI; grant read, write on directory BACKU ...

  4. Java Web dev搭建经验总结

    摘要: 原创出处:www.bysocket.com 泥瓦匠BYSocket 希望转载,保留摘要,谢谢! 回馈分析法使我看到,我对专业技术人员,不管是工程师.会计师还是市场研究人员,都容易从直觉上去理解 ...

  5. How to Debug Enterprise Portal Code in Dynamics AX 2009

    转载 To set up debugging for pages1. Log into the server that is running the AOS.2. Open the Microsoft ...

  6. 如何使用MVC编写Winform程序代码

    efwplus开源框架官网:www.efwplus.cn 前提:业务分析设计已完成,界面设计完成   1.代码结构划分 1)界面层:FrmSugeryApplyList.ISugeryApplyLis ...

  7. hbase 使用

    hbase shell命令的使用 再使用hbase 命令之前先检查一下hbase是否运行正常 hadoop@Master:/usr/hbase/bin$ jps HMaster NameNode Se ...

  8. js判断手机浏览器并跳转到手机网站

    function uaredirect(murl){ try { if(document.getElementById("bdmark") != null){ return; } ...

  9. 看那记不住命令的猿,如何使用GitHub

    什么是GitHub呢? GitHub是什么?好吧, 请看百科:http://baike.baidu.com/view/3366456.htm 准备:msysgit.tortoisegit 首先,我们得 ...

  10. react native之组织组件

    这些组件包括<TabView>,<NavigatorView>和<ListView>,他们实现了手机端最常用的交互和导航.你会发现这些组件在实际的项目中会非常有用. ...