麦克风采集与播放 (源码)

简介:   在网络聊天系统中,采集麦克风的声音并将其播放出来,是最基础的模块之一。本文我们就介绍如何快速地实现这个基础模块。 一. 基础知识   有几个与声音采集和播放相关的专业术语必须要先了解一下,否则,后面的介绍将无法展开。

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

一. 基础知识

  有几个与声音采集和播放相关的专业术语必须要先了解一下,否则,后面的介绍将无法展开。语音采集指的是从麦克风采集音频数据,即声音样本转换成数字信号。其涉及到几个重要的参数:采样率、采样位数、声道数。

  简单的来说:

       采样率:即采样频率,就是在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源码下载

 

目录
相关文章
|
Android开发
【错误记录】Android 可执行权限报错 ( Cannot run program “/data/user/0/cn.e/ffmpeg“: error=13,Permission denied )
【错误记录】Android 可执行权限报错 ( Cannot run program “/data/user/0/cn.e/ffmpeg“: error=13,Permission denied )
2513 0
【错误记录】Android 可执行权限报错 ( Cannot run program “/data/user/0/cn.e/ffmpeg“: error=13,Permission denied )
|
Ubuntu Linux 编译器
openssl 的编译(linux、Ubuntu) 和 交叉编译(arm、Hi3531A)的问题分析、解决
openssl 的编译(linux、Ubuntu) 和 交叉编译(arm、Hi3531A)的问题分析、解决
3432 0
|
6月前
|
人工智能 自然语言处理 算法
备案、登记、算法备案之间到底怎么区分
本文系统解析生成式AI三大合规要求:算法备案(针对推荐/排序等常规算法)、深度合成登记(聚焦AI换脸、语音生成等内容真实性)、大模型备案(最严层级,覆盖AI对话、写作、绘图等生成式服务),厘清其适用场景与监管逻辑,助力企业精准合规。
635 1
|
6月前
|
JavaScript Java 数据库
一个基于Spring Boot + Vue的诊所管理系统全栈开发指南
本项目介绍诊所管理系统(门诊系统)的全栈开发方案:采用Spring Boot + Vue.js技术栈,结合MySQL/Redis数据库、RESTful API与HL7/FHIR等医疗标准接口,支持预约挂号、电子病历、处方管理、药房库存、医保对接及多维统计。强调SaaS部署、微服务架构与数据安全合规。
499 0
|
11月前
|
机器学习/深度学习 算法 API
商品价格动态调整接口技术详解
本文详解电商商品价格动态调整接口设计,涵盖RESTful API规范、成本加成与需求弹性算法、Python代码实现及优化策略,结合真实场景,助力构建高效、可扩展的智能定价系统。
|
12月前
|
机器学习/深度学习 监控 算法
基于YOLOv8的人体多姿态行为识别系统(站立、摔倒、坐姿、深蹲与跑步)|完整源码数据集+PyQt5界面+完整训练流程+开箱即用!
本项目基于YOLOv8深度学习模型,实现了一个多姿态行为识别系统,能够精准地识别站立、摔倒、坐姿、深蹲和跑步等行为。项目的核心内容包括完整的YOLOv8训练代码、标注数据集、预训练权重文件、部署教程和PyQt5界面,提供了一套从数据收集到最终部署的完整解决方案。
基于YOLOv8的人体多姿态行为识别系统(站立、摔倒、坐姿、深蹲与跑步)|完整源码数据集+PyQt5界面+完整训练流程+开箱即用!
|
11月前
|
缓存 运维 文字识别
《大模型驱动的智能文档解析系统:从领域适配到落地优化的全链路开发实践》
本文聚焦大模型在高端装备制造企业智能文档解析系统的落地实践,针对领域术语理解断层、长文档上下文限制、知识提取精准度不足、响应缓慢、微调成本高、稳定性差等核心痛点,提出对应解决方案:构建领域术语知识底座适配行业语境,以语义分块+关联图谱突破长文档解析瓶颈,用多轮校验+规则库保障知识可靠性,通过分层部署+多级缓存优化响应速度,采用增量微调+prompt工程降低成本并提升泛化能力,依托全链路监控+自动化运维保障长期稳定。优化后,术语识别准确率、知识逻辑完整性显著提升,单文档初步解析响应缩至3秒内,故障发生率降至1.2%,印证大模型落地需全链路协同且贴合领域需求。
835 15
|
机器学习/深度学习 存储 TensorFlow
TensorFlow Lite Micro:嵌入式TinyML系统上的机器学习推理框架——论文深度解析
TensorFlow Lite Micro(TFLM)是专为嵌入式系统设计的轻量级机器学习推理框架,适用于仅有几十KB内存的微控制器。它通过极简架构、模块化设计和内存优化策略,在资源受限设备上高效运行TinyML模型,广泛应用于关键词检测、传感器分析、预测性维护等领域。TFLM支持跨平台部署,并允许硬件厂商提供定制优化,兼顾灵活性与性能。
2902 6
|
编解码 关系型数据库 计算机视觉
Opencv学习笔记(十一):opencv通过mp4保存为H.264视频
本文介绍了如何在OpenCV中通过使用cisco开源的openh264库来解决不支持H.264编码的问题,并提供了完整的代码示例。
1763 0
Opencv学习笔记(十一):opencv通过mp4保存为H.264视频