windows 桌面采集音频

news2024/12/26 2:20:47

头文件:

#ifndef __CAPTURE_AUDIO__
#define __CAPTURE_AUDIO__

#include <functional>
#include <windows.h>
#pragma comment(lib, "winmm.lib")

class CaptureAudio
{
public:
	CaptureAudio();
	~CaptureAudio();

public:
	bool Init(const std::function<void(unsigned char* pPcmAudioData, long nLen)>& pFunc);
	void Uninit();

private:
	bool Capture();

private:
	static unsigned int __stdcall Process(void* args);

private:
	unsigned char* m_pAudioData = nullptr;

private:
	HANDLE m_threadRecv = INVALID_HANDLE_VALUE;
	HANDLE m_threadEvent = INVALID_HANDLE_VALUE;

private:
	WAVEHDR m_wHdr; //采集音频时包含数据缓存的结构体
	HWAVEIN m_hWaveIn;//输入设备

private:
	std::function<void(unsigned char* pPcmAudioData, long nLen)> m_pFunc;
};

#endif

源文件:

#include "CaptureAudio.h"
#include <chrono>
#include <thread>

using namespace std;

CaptureAudio::CaptureAudio()
{
	while (!m_pAudioData) {
		try{
			m_pAudioData = new unsigned char[1024 * 1024];
		}
		catch (...){}
	}
}
CaptureAudio::~CaptureAudio()
{
	if (m_pAudioData) {
		delete[]m_pAudioData;
		m_pAudioData = nullptr;
	}
}


bool CaptureAudio::Init(const std::function<void(unsigned char* pPcmAudioData, long nLen)>& pFunc)
{
	UINT nDev = waveInGetNumDevs();
	if (nDev == 0) {
		return false;
	}


	WAVEFORMATEX waveform; //采集音频的格式,结构体
	waveform.wFormatTag = WAVE_FORMAT_PCM;//声音格式为PCM
	waveform.nSamplesPerSec = 48000;//采样率,16000次/秒
	waveform.wBitsPerSample = 16;//采样比特,16bits/次
	waveform.nChannels = 1;//采样声道数,2声道
	waveform.nAvgBytesPerSec = 16000;//每秒的数据率,就是每秒能采集多少字节的数据
	waveform.nBlockAlign = 2;//一个块的大小,采样bit的字节数乘以声道数
	waveform.cbSize = 0;//一般为0
	MMRESULT hResults = waveInOpen(&m_hWaveIn, WAVE_MAPPER, &waveform, (DWORD_PTR)0, (DWORD_PTR)this, CALLBACK_NULL);//使用waveInOpen函数开启音频采集
	if (hResults != MMSYSERR_NOERROR) {
		return false;
	}

	m_threadEvent = CreateEvent(NULL, true, false, L"");
	m_threadRecv = (HANDLE)_beginthreadex(NULL, 0, Process, this, 0, NULL);

	m_pFunc = pFunc;
	return true;
}

void CaptureAudio::Uninit()
{
	if (m_threadRecv != INVALID_HANDLE_VALUE && m_threadEvent != INVALID_HANDLE_VALUE) {
		SetEvent(m_threadEvent);
		WaitForSingleObject(m_threadRecv, INFINITE);
		CloseHandle(m_threadRecv);
		CloseHandle(m_threadEvent);

		m_threadRecv = INVALID_HANDLE_VALUE;
		m_threadEvent = INVALID_HANDLE_VALUE;
	}

	waveInUnprepareHeader(m_hWaveIn, &m_wHdr, sizeof(WAVEHDR));
	waveInStop(m_hWaveIn);
	waveInClose(m_hWaveIn);
}

bool CaptureAudio::Capture()
{
	waveInUnprepareHeader(m_hWaveIn, &m_wHdr, sizeof(WAVEHDR));

	memset(m_pAudioData, 0, 1024 * 1024);
	m_wHdr.lpData = (LPSTR)m_pAudioData;
	m_wHdr.dwBufferLength = 1024 * 1024;
	m_wHdr.dwBytesRecorded = 0;
	m_wHdr.dwUser = 0;
	m_wHdr.dwFlags = WHDR_DONE;
	m_wHdr.dwLoops = 1;
	waveInPrepareHeader(m_hWaveIn, &m_wHdr, sizeof(WAVEHDR));//准备一个波形数据块头用于录音
	waveInAddBuffer(m_hWaveIn, &m_wHdr, sizeof(WAVEHDR));//指定波形数据块为录音输入缓存
	MMRESULT hResults = waveInStart(m_hWaveIn);//开始录音
	if (hResults != MMSYSERR_NOERROR) {
		return false;
	}
	std::this_thread::sleep_for(std::chrono::milliseconds(100));

	waveInReset(m_hWaveIn);

	if (m_pFunc) {
		m_pFunc(m_pAudioData, m_wHdr.dwBytesRecorded);
	}

	return true;
}

unsigned int CaptureAudio::Process(void* args)
{
	CaptureAudio* pThis = (CaptureAudio*)args;

	while (true) {
		if (WaitForSingleObject(pThis->m_threadEvent, 0) == WAIT_OBJECT_0) {
			break;
		}
		pThis->Capture();
	}
	return 0;
}

生成的文件pcm:

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2180214.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

云计算Openstack Glance

OpenStack Glance&#xff08;或称为Glance&#xff0c;但通常OpenStack官方文档中使用的是“Glance”作为项目代号&#xff09;是OpenStack的镜像服务组件&#xff0c;为创建虚拟机提供镜像服务。以下是对OpenStack Glance的详细解析&#xff1a; 一、基本功能 Glance主要提…

【HTML并不简单】笔记2-你不知道的a元素属性:target、download、ping、referrerpolicy和href

文章目录 target属性download属性ping属性referrerpolicyhref细节自动绝对地址锚点定位无障碍访问为何base元素无人问津实现链接元素a的嵌套 《HTML并不简单&#xff1a;Web前端开发精进秘籍》张鑫旭 笔记 target属性 有场景如下&#xff1a; 在线写作工具经常会有预览功能&a…

源2.0-M32大模型适配AutoGPTQ工具及量化推理教程

AutoGTPQ简介 AutoGPTQ‌是一个开源工具包&#xff0c;专注于简化大规模语言模型(LLMs)的量化过程。它基于高效的GPTQ算法开发&#xff0c;主要使用Python编程语言&#xff0c;并依托PyTorch框架来实现量化功能。AutoGPTQ的设计目标是为开发者和研究人员提供一个易于使用的API接…

【Golang】关于Go语言数学计算、随机数生成模块--math

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

多功能声学气膜馆:承载梦想与希望的舞台—轻空间

在9月29日上午&#xff0c;苏州大学应用技术学院的2024级新生开学典礼暨开学第一课在轻空间建造的多功能声学气膜馆内盛大举行。这一盛典不仅见证了2849名新生的入学&#xff0c;也展示了气膜馆的独特魅力与优越功能。 卓越的声学表现 声学气膜馆采用高性能材料&#xff0c;确保…

Linux-基础实操篇-组管理和权限管理(上)

Linux 组基本介绍 在 linux 中的每个用户必须属于一个组&#xff0c;不能独立于组外。在 linux 中每个文件 有所有者、所在组、其它组的概念。 用户和组的基本概念&#xff1a; 用户名&#xff1a;用来识别用户的名称&#xff0c;可以是字母、数字组成的字符串&#xff0…

解决DHCP服务异常导致设备无法获取IP地址的方法

DHCP在网络环境中会自动为网络中的设备分配IP地址和其他关键网络参数&#xff0c;可以简化网络配置过程。但是&#xff0c;如果DHCP服务出现异常时&#xff0c;设备可能无法正常获取IP地址&#xff0c;会影响到网络通信。 本文讲述一些办法可以有效解决DHCP服务异常导致设备无法…

YAML管理接口框架配置的最佳实践!!

YAML 文件在接口框架中作为配置管理的语言&#xff0c;以其简洁、直观的语法&#xff0c;迅速成为开发者的宠儿。然而&#xff0c;如何高效地管理和组织接口框架的配置&#xff0c;往往是一个容易被忽视的难题。你是否曾因为冗长的配置文件而感到头疼&#xff1f;今天&#xff…

干冰清洗机的工作原理

干冰清洗机的工作原理主要基于干冰的物理特性&#xff0c;特别是其升华过程。以下是干冰清洗机工作原理的详细解释&#xff1a; 一、干冰的制备 制冰系统&#xff1a;干冰清洗机内部配备有制冰系统&#xff0c;该系统将液态二氧化碳&#xff08;CO₂&#xff09;快速冷却并压…

HTTP协议讲解,请求报文与响应报文都是什么?网络控制台查看HTTP请求

目录 一. HTTP解析 二. 请求报文 2.1 请求行 2.1.1 请求类型 2.1.2 请求URL路径 2.1.3 发送的HTTP请求的版本 2.2 请求头 2.2.1 Host&#xff1a;主要用来实现虚拟主机技术 2.2.2 Cookie&#xff1a;一种让浏览器帮忙携带信息的手段 2.2.3 Content—type&#xff1a;…

揭秘分布式定时任务在人工智能RPA机器人中的应用|实在RPA研究

一、引言 在人工智能技术不断突破的今天&#xff0c;RPA智能机器人已经渗透到各行各业&#xff0c;成为企 业提升效率、降低成本的重要工具。而在机器人高效运作的背后&#xff0c;分布式定时任务发挥着 不可替代的作用。本文将深入探讨分布式定时任务在人工智能机器人中的应用…

leetcode-链表篇3

leetcode-61 给你一个链表的头节点 head &#xff0c;旋转链表&#xff0c;将链表每个节点向右移动 k 个位置。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], k 2 输出&#xff1a;[4,5,1,2,3]示例 2&#xff1a; 输入&#xff1a;head [0,1,2], k 4 输出&#x…

opencv - Fourier Transform 傅里叶变换

目标 在本节中&#xff0c;我们将学习 使用 OpenCV 查找图像的傅里叶变换利用 Numpy 中可用的 FFT 函数傅里叶变换的一些应用我们将看到以下函数&#xff1a;cv.dft()、cv.idft() 等 理论 傅里叶变换用于分析各种滤波器的频率特性。对于图像&#xff0c;2D 离散傅里叶变换 …

优选驾考系统小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;驾校管理&#xff0c;驾考文章管理&#xff0c;驾照类型管理&#xff0c;报名入口管理&#xff0c;学员报名管理&#xff0c;练车预约管理&#xff0c;考试场地管理 微信端账号功能包括&#xff1a;系…

【羊毛资源】华为云开发者云主机免费申请使用指南

本文内容均来自个人笔记并重新梳理&#xff0c;如有错误欢迎指正&#xff01; 如果对您有帮助&#xff0c;烦请点赞、关注、转发、订阅专栏&#xff01; 专栏订阅入口 | 精选文章 | Kubernetes | Docker | Linux | 羊毛资源 | 工具推荐 | 往期精彩文章 【Docker】&#xff08;全…

【GAN 图像生成】

理论知识学习&#xff1a; PART 1&#xff1a; 生成对抗网络GAN 深度学习模型&#xff0c;用于生成数据 对抗式训练&#xff0c;生成器v判别器 DCGAN>WGAN>StyleGAN技术不断进化 GAN在艺术创作。数据增强领域应用越来越广泛 应用&#xff1a; GAN在图像合成&#x…

生信初学者教程(十二):数据汇总

文章目录 介绍加载R包导入数据汇总表格输出结果总结介绍 在本教程中,汇总了三个肝细胞癌(HCC)的转录组数据集,分别是LIRI-JP,LIHC-US/TCGA-LIHC和GSE14520,以及一个HCC的单细胞数据集GSE149614的临床表型信息。这些数据集为科研人员提供了丰富的基因表达数据和相关的临床…

SqlAlchemy使用教程(七) 异步访问数据库

SqlAlchemy使用教程(一) 原理与环境搭建SqlAlchemy使用教程(二) 入门示例及编程步骤SqlAlchemy使用教程(三) CoreAPI访问与操作数据库详解SqlAlchemy使用教程(四) MetaData 与 SQL Express Language 的使用SqlAlchemy使用教程(五) ORM API 编程入门SqlAlchemy使用教程(六) – O…

Find My储物盒|苹果Find My技术与储物盒结合,智能防丢,全球定位

储物盒是用来存储&#xff0c;收藏东西的器具。储物盒可以帮助用户合理利用有限的空间&#xff0c;通过分类归置物品&#xff0c;避免浪费和混乱。储物盒能够有效地保护存放的物品&#xff0c;防止它们受到灰尘、污渍、损坏和潮湿的影响。储物盒还可以增加空间利用率、方便搬家…

Windows环境下使用Docker配置MySQL数据库

用Docker配置数据库&#xff0c;无论是做开发&#xff0c;还是做生产部署&#xff0c;都非常的方便 它不需要单独安装数据库&#xff0c;也不用担心出现各种环境的配置问题。 本文将分享用Docker配置数据库的步骤&#xff0c;这里用MySQL举例。 其他的数据库如MSSQL&#xf…