首页 > 系统相关 >windows api录音pcm

windows api录音pcm

时间:2023-08-08 15:58:36浏览次数:58  
标签:pFile windows i1 api buffer pcm waveform whdr

pcm.h

#pragma once
#include <cstdio>
#include <cstdint>
#include <Windows.h>
#pragma comment(lib,"winmm.lib")
class pcm
{
public:
	pcm();
	~pcm();

	void startRecording();
	void endRecording();

private:

	struct WavPCMFileHeader
	{
		struct RIFF
		{
			const    char rift[4] = { 'R','I', 'F', 'F' };
			uint32_t fileLength;
			const    char wave[4] = { 'W','A', 'V', 'E' };
		}riff;

		struct Format
		{
			const    char fmt[4] = { 'f','m', 't', ' ' };
			uint32_t blockSize = 16;
			uint16_t formatTag;
			uint16_t channels;
			uint32_t samplesPerSec;
			uint32_t avgBytesPerSec;
			uint16_t blockAlign;
			uint16_t  bitsPerSample;
		}format;

		struct  Data
		{
			const    char data[4] = { 'd','a', 't', 'a' };
			uint32_t dataLength;
		}data;

		WavPCMFileHeader() {}

		WavPCMFileHeader(int nCh, int  nSampleRate, int  bitsPerSample, int dataSize)
		{
			riff.fileLength = 36 + dataSize;
			format.formatTag = 1;
			format.channels = nCh;
			format.samplesPerSec = nSampleRate;
			format.avgBytesPerSec = nSampleRate * nCh * bitsPerSample / 8;
			format.blockAlign = nCh * bitsPerSample / 8;
			format.bitsPerSample = bitsPerSample;
			data.dataLength = dataSize;
		}
	};

	HWAVEIN         m_hWaveIn;		        //输入设备
	WAVEFORMATEX    m_waveform;	            //定义音频流格式
	BYTE*			m_pBuffer1;				//输入音频缓冲区(单声道)
	WAVEHDR         m_whdr_i1;				//输入音频头

	FILE*			m_pFile = nullptr;
	uint32_t		m_iTotalDataLength = 0;

	void initRecord();
};

pcm.cpp

#include "pcm.h"

pcm::pcm()
{
	initRecord();
}

void pcm::initRecord()
{
	// 设置音频流格式
	m_waveform.nSamplesPerSec = 16000;							// 采样率
	m_waveform.wBitsPerSample = 16;								// 采样精度
	m_waveform.nChannels = 1;									// 声道个数
	m_waveform.cbSize = 0;										// 额外空间	
	m_waveform.wFormatTag = WAVE_FORMAT_PCM;					// 音频格式
	m_waveform.nBlockAlign = 2;									// 块对齐
	m_waveform.nAvgBytesPerSec = 32000;							// 传输速率

	//最大60秒
	int buffer_len = 16000 * 16 * 60;

	m_pBuffer1 = new BYTE[buffer_len];
	memset(m_pBuffer1, 0, buffer_len);   // 内存置0

	// 设置音频头
	m_whdr_i1.lpData = (LPSTR)m_pBuffer1;			// 指向buffer
	m_whdr_i1.dwBufferLength = buffer_len;			// buffer大小
	m_whdr_i1.dwBytesRecorded = 0;					// buffer存放大小
	m_whdr_i1.dwUser = 0;
	m_whdr_i1.dwFlags = 0;
	m_whdr_i1.dwLoops = 1;
}

void pcm::startRecording()
{
	MMRESULT mRet = waveInOpen(&m_hWaveIn, WAVE_MAPPER, &m_waveform, (DWORD_PTR)nullptr, NULL, CALLBACK_FUNCTION);
	waveInPrepareHeader(m_hWaveIn, &m_whdr_i1, sizeof(WAVEHDR));//准备buffer
	waveInAddBuffer(m_hWaveIn, &m_whdr_i1, sizeof(WAVEHDR));    //添加buffer
	waveInStart(m_hWaveIn);
}

void pcm::endRecording()
{
	waveInReset(m_hWaveIn);
	waveInClose(m_hWaveIn);

	//创建时预留头部信息
	if (!m_pFile)
	{
		m_iTotalDataLength = 0;
		fopen_s(&m_pFile, "sound.pcm", "wb+");
		//预留头部位置
		fseek(static_cast<FILE*>(m_pFile), sizeof(WavPCMFileHeader), SEEK_SET);
	}

	//写入声音数据
	fwrite(m_pBuffer1, 1, m_whdr_i1.dwBytesRecorded, static_cast<FILE*>(m_pFile));
	m_iTotalDataLength += m_whdr_i1.dwBytesRecorded;


	//关闭时写入.wav文件头部信息
	if (m_pFile)
	{
		if (m_iTotalDataLength > 0)
		{
			fseek(static_cast<FILE*>(m_pFile), 0, SEEK_SET);
			WavPCMFileHeader h(1, 16000, 16, m_iTotalDataLength);
			fwrite(&h, 1, sizeof(h), static_cast<FILE*>(m_pFile));
		}
		fclose(static_cast<FILE*>(m_pFile));
		m_pFile = nullptr;
	}
}

pcm::~pcm()
{
	if (m_pFile != nullptr)
	{
		delete m_pFile;
	}
	if (m_pBuffer1 != nullptr)
	{
		delete[]m_pBuffer1;
	}
}

main函数调用:

#include <iostream>
#include "pcm.h"

int main()
{
	pcm* p = new pcm();
	int i;
	std::cin >> i;
	if (i == 1)
	{
		p->startRecording();
		getchar();
	}
	std::cin >> i;
	if (i == 2)
	{
		p->endRecording();
		getchar();
	}
}

标签:pFile,windows,i1,api,buffer,pcm,waveform,whdr
From: https://www.cnblogs.com/horizonhz/p/17614568.html

相关文章

  • 【GTK】在Windows下安装GTK
    1、下载MSYS2从MSYS2中下载安装包,并暗转MSYS2。2、打开MSYS2shell在MSYS2shell中运行以下命令:>pacman-Smingw-w64-x86_64-gtk4成功截图:......
  • windows下常用的nginx命令
    startnginx:启动nginxnginx.exe-cconf/nginx.conf按照指定配置去启动nginxnginx-t-cconf/nginx.conf :检测nginx是否配置正确nginx-sreload :修改配置后重新加载生效nginx-sstop :快速停止nginx,可能并不保存相关信息.nginx-s quit :完整有序的停止ngi......
  • windows10使用Powershell脚本自动初始化磁盘
    如下为脚本内容:1首先使用get-disk命令检测未被初始化的磁盘,磁盘为被初始化属性会为raw,使用rawdisk变量获取未被初始化的磁盘。2判断rawdisk是否有值,如果有,则存在未被初始化磁盘,条件为真,进行下一步。如果空值,则说明系统没有未被初始化的磁盘,输出:没有找到未格式化的磁盘或RAW参数......
  • 虚拟机 的net模式与 桥接模式, windows可以ping通 虚拟机,但是虚拟机无法ping通 windows
    1第一个问题,net与桥接的模式。    2第二个问题,虚拟机ping不通PC,但是PC可以ping通虚拟机。  ......
  • 【HarmonyOS】【续集】实现从视频提取音频并保存到pcm文件功能(API6 Java)
    【关键字】视频提取类Extractor、视频编解码、保存pcm文件、getAudioTime 【背景和问题】上篇中介绍了从视频提取音频并保存到pcm文件功能,请参考文档:https://developer.huawei.com/consumer/cn/forum/topic/0209125665541017202?fid=0101591351254000314,解码步骤使用的是普通......
  • windows下cmake C++库打包成C方式导出
    背景windows下当前的一个项目使用的编译器是mingw,想要使用一个使用msvc编译出来的C++库。方法重新创建一个库,这个使用extern"C"方式导出函数,在函数中调用msvc编译出来的库。项目文件文件结构|--CMakeLists.txt|--floor_calibration||--include|||--floor_c......
  • Midjourney API 申请和接入小白教程
    MidjourneyAPI为开发者提供了快速接入Midjourney平台的能力,它允许开发者通过简单的代码调用来访问Midjourney平台上的生成高质量的图像能力。本文将提供一份MidjourneyAPI的入门教程,以帮助开发者快速了解如何申请和接入该API。申请APIKey申请MidjourneyAPI的第一......
  • C# 读取带CheckBox复选框控件的表格-并集成到Windows Service里面
    最近的项目要求读取xls文件内的单元格,并且单元格旁边会有复选框标识类型。搜了下只有java的POI有例子,NOPI看项目文档好像是没有实现读取控件的功能。java实现POI POI如何解析出excel中复选框是否被选中https://blog.csdn.net/qq_29832217/article/details/104413475 C#导......
  • Apipost接口自动化测试入门
    今天我们来聊一聊接口自动化测试。以往我们都是以以代码的形式编写自动化测试脚本做自动化测试,网上也有非常多的攻略,那么在不会代码的情况下该怎么做接口自动化呢,今天给大家介绍Apipost自动化测试模块,不用写代码也能做接口自动化!点击左侧菜单栏「自动化测试」按钮进入自动化测试......
  • Asp.Net WebApi防重提交
     一、添加过滤器///<summary>///重复提交///</summary>publicclassReSubmitAttribute:ActionFilterAttribute{///<summary>///操作成功提示消息///</summary>publicstringSuccessMsg=null;......