在网络聊天系统中。採集麦克风的声音并将其播放出来。是最基础的模块之中的一个。本文我们就介绍怎样高速地实现这个基础模块。

一. 基础知识

  有几个与声音採集和播放相关的专业术语必需要先了解一下,否则。后面的介绍将无法展开。语音採集指的是从麦克风採集音频数据。即声音样本转换成数字信号。

其涉及到几个重要的參数:採样率、採样位数、声道数。

  简单的来说:

採样率:即採样频率,就是在1秒内进行採集动作的次数。

採样位数:又叫採样深度。就是每次採集动作得到的数据长度,即使用多少个bit来记录一个样本。

声道数:通常是单声道或双声道(立体声)。普通的麦克风採集差点儿都是单声道的。

  这样。1秒钟採集得到的声音数据的大小为(单位byte):(採样频率×採样位数×声道数×时间)/8。

  音频帧:通常一个音频帧的时长为10ms,即每10ms的数据构成一个音频帧。假设:採样率16k、採样位数16bit、声道数1,那么一个10ms的音频帧的大小为:(16000*16*1*0.01)/8 = 320 字节。计算式中的0.01为秒。即10ms

二. 怎样採集、播放?

  假设直接基于底层的DirectX来进行麦克风的採集与播放。那将是十分繁琐的。

好在我们有现成的组件来完毕这个工作。MCapture 用于採集硬件设备(如麦克风、摄像头、声卡、屏幕等)。MPlayer用于播放採集到的数据。

1.採集麦克风

  MCapture提供了IMicrophoneCapturer。用于採集麦克风输入的声音。其每隔20ms触发一次AudioCaptured事件,通过事件的參数byte[]暴露这20ms採集得到的数据。

  IMicrophoneCapturer 相关採集參数的值是这种:

採样频率:16000,採样位数:16bit。声道数:1。

所以,依照上面的公式进行计算,我们能够得到AudioCaptured事件的參数byte[]的长度为640。

2. 播放声音数据

  MPlayer提供了IAudioPlayer,用于播放声音数据。在创建IAudioPlayer实例时,要正确的设置採样频率、採样位数、声道数这些參数的值。假设它们与即将要播放的声音数据的特征不一致,播放将出现错误。

  我们在拿到MCapture採集的声音数据后,将其提交给IAudioPlayer的Play方法进行播放就可以。

三.Demo实现

  在有了前面的介绍作为基础后,接下来实现麦克风的採集和播放就相当简单了。在接下来的demo中。不仅演示了播放从麦克风採集到的声音,并且多加了一个功能。就是直接播放wav声音文件,这些实现都是相当简单的。  

    public partial class Form1 : Form
{
private IAudioPlayer audioPlayer;
private IMicrophoneCapturer microphoneCapturer; public Form1()
{
InitializeComponent();
} private void button_mic_Click(object sender, EventArgs e)
{
try
{
this.microphoneCapturer = CapturerFactory.CreateMicrophoneCapturer(int.Parse(this.textBox_mic.Text));
this.microphoneCapturer.AudioCaptured += new ESBasic.CbGeneric<byte[]>(microphoneCapturer_AudioCaptured);
this.audioPlayer = PlayerFactory.CreateAudioPlayer(int.Parse(this.textBox_speaker.Text), 16000, 1, 16, 2);
this.microphoneCapturer.Start(); this.label_msg.Text = "正在採集麦克风,并播放 . . .";
this.label_msg.Visible = true;
this.button_wav.Enabled = false;
this.button_mic.Enabled = false;
this.button_stop.Enabled = true;
}
catch (Exception ee)
{
MessageBox.Show(ee.Message);
}
} void microphoneCapturer_AudioCaptured(byte[] audioData)
{
if (this.audioPlayer != null)
{
this.audioPlayer.Play(audioData);
}
}
private void button_wav_Click(object sender, EventArgs e)
{
try
{
string path = ESBasic.Helpers.FileHelper.GetFileToOpen2("请选择要播放的wav文件", AppDomain.CurrentDomain.BaseDirectory, ".wav");
if (path == null)
{
return;
} AudioInformation info = PlayerFactory.ParseWaveFile(path);
if (info.FormatTag != (int)WaveFormats.Pcm)
{
MessageBox.Show("只支持PCM编码方式的语音数据!");
return;
} int secs = info.GetTimeInMsecs() / 1000; //声音数据的播放时长
this.audioPlayer = PlayerFactory.CreateAudioPlayer(int.Parse(this.textBox_speaker.Text), info.SampleRate, info.ChannelCount, info.BitsNumber, secs + 1); this.audioPlayer.Play(info.AudioData); this.label_msg.Text = "正在播放wav文件 . . .";
this.label_msg.Visible = true;
this.button_wav.Enabled = false;
this.button_mic.Enabled = false;
this.button_stop.Enabled = true;
}
catch (Exception ee)
{
MessageBox.Show(ee.Message);
}
} private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (this.microphoneCapturer != null)
{
this.microphoneCapturer.Stop();
this.microphoneCapturer.Dispose();
this.microphoneCapturer = null;
} if (this.audioPlayer != null)
{
this.audioPlayer.Dispose();
this.audioPlayer = null;
}
} private void button_stop_Click(object sender, EventArgs e)
{
if (this.audioPlayer == null)
{
return;
} if (this.microphoneCapturer != null)
{
this.microphoneCapturer.Stop();
this.microphoneCapturer.Dispose();
this.microphoneCapturer = null;
} this.audioPlayer.Clear();
this.audioPlayer.Dispose();
this.audioPlayer = null; this.label_msg.Visible = false;
this.button_wav.Enabled = true;
this.button_mic.Enabled = true;
this.button_stop.Enabled = false;
}
}

  看看demo执行的效果图:

  

    麦克风採集与播放Demo源代码下载

C#实现麦克风採集与播放的更多相关文章

  1. C++ 採集音频流(PCM裸流)实现录音功能

    与上一篇的"C++ 播放音频流(PCM裸流)" 点击打开链接 相相应,本篇是关于用C++实现录音功能的.相同是直接建一个win32控制台程序然后将代码拷过去改个文件名称就能够用,也 ...

  2. XP下採用DirectShow採集摄像头

    转载请标明是引用于 http://blog.csdn.net/chenyujing1234 欢迎大家提出意见,一起讨论! 须要演示样例源代码的请独自联系我. 前提: 摄像头能正常工作.摄像头有创建di ...

  3. 手机Android音视频採集与直播推送,实现单兵、移动监控类应用

    最新手机採集推送直播监控以及EasyDarwin开源流媒体平台的版本号及代码: EasyDarwin 开源流媒体云平台:https://github.com/easydarwin EasyClient ...

  4. 用DirectShow实现视频採集-流程构建

    DirectShow作为DirectX的一个子集,它为用户提供了强大.方便的多媒体开接口,而且它拥有直接操作硬件的能力,这使得它的效率远胜于用GDI等图形方式编写的多媒体程序.前面一篇文章已经对Dir ...

  5. 开源 java CMS - FreeCMS2.3 Web页面信息採集

    原文地址:http://javaz.cn/site/javaz/site_study/info/2015/23312.html 项目地址:http://www.freeteam.cn/ Web页面信息 ...

  6. python爬虫之採集——360联想词W2版本号

    http://blog.csdn.net/recsysml/article/details/30541197,我的这个博文介绍了对应的简单的方法做一个联想词的爬虫,并且还承诺了下面优化: 下一版本号的 ...

  7. 【源代码】基于Android和蓝牙的单片机温度採集系统

    如需转载请标明出处:http://blog.csdn.net/itas109 QQ技术交流群:129518033 STC89C52单片机通过HC-06蓝牙模块与Android手机通信实例- 基于And ...

  8. 【MFC两种视频图像採集方法】DirectShow与Opencv

    效果图: DirectShow採集核心代码: 创建线程调用该函数,採集图像通过x264解码封装rtmp协议包.推送至FMSserver,可实现视频直播 UINT __stdcall StartVide ...

  9. PHP採集CSDN博客边栏的阅读排行

    项目中要用到採集的数据,所以就先拿CSDN博客来试了试.这里使用Simple HTML DOM(官网)这个库,它可以方便的遍历HTML文档. <?php include_once('simple ...

随机推荐

  1. Linux进程间通信—套接字

    六.套接字(socket) socket也是一种进程间的通信机制,不过它与其他通信方式主要的区别是:它可以实现不同主机间的进程通信.一个套接口可以看做是进程间通信的端点(endpoint),每个套接口 ...

  2. 7.volatile关键字

    volatile:一个线程修改了某一个共享变量的值,其他线程也是否能够立即知道这个修改的 1.主要是让该“变量”在多个线程中可见,在java中每一个线程都有一块自己的工作区,其中就存放着所有线程“共享 ...

  3. @MySQL中length字符长度函数使用方法

    MySQL里面的length函数是一个用来获取字符串长度的内置函数,一个汉字是算三个字符,中文的标点符号也是算三个字符,一个数字或字母算一个字符.具体用法示例如下: 1.查看某字符串的长度 SELEC ...

  4. Oracle 乱码或则中文无法正确查询问题

    解决Oracle本身的字符集问题 oracle数据库的字符集更改 A.oracle server 端 字符集查询 select userenv('language') from dual 其中NLS_ ...

  5. http://www.cnblogs.com/nick-huang/p/4848843.html

    http://www.cnblogs.com/nick-huang/p/4848843.html

  6. scala "←" "<-"

    程序里看到"←"符号 (for { routee ← valueHolder.routee } yield routee).toVector 找遍scala的操作符表都没找到,回头 ...

  7. 搭建SpringBoot服务器,在公司内网中使用

    搭建SpringBoot服务器,在公司内网中使用. 学习了:https://blog.csdn.net/z3881006/article/details/78902231 就是一个程序,托管于gith ...

  8. python爬虫模拟登陆

    python爬虫模拟登陆 学习了:https://www.cnblogs.com/chenxiaohan/p/7654667.html  用的这个 学习了:https://www.cnblogs.co ...

  9. sysstat 工具

    转:http://www.ctohome.com/FuWuQi/1b/688.html sysstat 工具简介 sysstat 是 Linux 系统中的常用工具包.它的主要用途是观察服务负载,比如C ...

  10. Antlr与Regex

    Antlr与Regex都是文本分析工具. Antlr内部分为词法(Lexer)和语法(Parser),在Antlr中,变量第一个字符大写表示词法,变量第一个字符小写表示语法.词法表示哪些是有效的词,语 ...