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. The model backing the <Database> context has changed since the database was created.

    Just found out the answer and thought of updating here. Just need to do the following. public class ...

  2. iOS WKWebView详解

    UIWebView就不用说了,这个过时了,现在iOS8以后建议都使用WKWebView. WKWebView 是现代 WebKit API 在 iOS 8 和 OS X Yosemite 应用中的核心 ...

  3. Xcode编译错误集锦

    1.在将ios项目进行Archive打包时,Xcode提示以下错误: [BEROR]CodeSign error: Certificate identity ‘iPhone Distribution: ...

  4. ci配置smarty手记

    需要用ci来写一个后台配置smarty,在网络上能够找到一些相关的文章.但是都是比较旧的内容,大部分是smary2.*的配置方法.按照这个配置后会出现一些错误.其实配置看smary官方会比较简单. 基 ...

  5. CodeWarrior环境下中断使用

    对于飞思卡尔CodeWarrior的中断使用,一般有3种方法: 1.把#pragma TRAP_PROC放在中断程序前面,并把中断向量表放到*.prm. 例如: #pragma TRAP_PROC v ...

  6. Java Web dev搭建经验总结

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

  7. Java实现动态代理的两种方式

    http://m.blog.csdn.net/article/details?id=49738887

  8. mysql查看和修改最大数量

    通常,mysql的最大连接数默认是100, 最大可以达到16384.1.查看最大连接数:show variables like '%max_connections%';2.修改最大连接数方法一:修改配 ...

  9. 一个基于POP3协议进行邮箱账号验证的类

    最近老陈要针对企业邮箱做一些开发,以对接企业OA神马的,但企业邮箱唯独没有开放账号密码验证功能,很恼火!不得已,翻出早些年的Asp代码改编成了C#类,实现了一个C#下的通过POP3协议进行邮箱账号验证 ...

  10. angularjs + seajs构建Web Form前端(三) -- 兼容easyui

    回顾 在上一章中使用了angular实现了ajax form和树形结构,经过以上两章对于angular的大致使用,对于angular也有了初步的认识,接下来的内容只会对angular的一些用法做简单的 ...