C++ 采集音频流(PCM裸流)实现录音功能(双缓存版本)
来源:互联网 发布:手机直播软件 编辑:程序博客网 时间:2024/05/17 07:15
上一次要用到音频已经是好几年前的事情了(毕竟本人是搞图象处理的)。当时写了一篇总结博客,没想到很多人看了,其中还有些在下载的地方和博客中问了些问题,虽然很想作答,但因为实在是忘了所以就没说什么。
最近又有项目要用到录制音频的功能,索性就把之前留下的双缓存坑填了。其实原理跟之前的差不多,最大的不同在于用到了回调函数。另外,本篇的代码基本上是参考这篇博客的,本人只修改了一部分,如有雷同,绝非偶然。
下面直接上代码,然后最后有整个工程的下载。
头文件和链接库如下:
#include<mmsystem.h>#include<mmreg.h>#pragma comment(lib, "winmm.lib")
变量和函数声明如下:
bool win;//采集数据标志位FILE *f;//存储采集到的音频文件HWAVEIN hWaveIn; //输入设备WAVEFORMATEX waveform; //采集音频的格式,结构体BYTE *pBuffer1, *pBuffer2;//采集音频时的数据缓存WAVEHDR wHdr1, wHdr2; //采集音频时包含数据缓存的结构体static DWORD CALLBACK MicCallback(HWAVEIN hWaveIn,UINT uMsg,DWORD dwInstance,DWORD dwParam1,DWORD dwParam2);//消息回调函数
初始化并开始录音的代码如下:
fopen_s(&f, "录音测试.pcm", "wb");//打开录音文件win = true;waveform.wFormatTag = WAVE_FORMAT_PCM;//声音格式为PCMwaveform.nSamplesPerSec = 8000;//采样率,16000次/秒waveform.wBitsPerSample = 16;//采样比特,16bits/次waveform.nChannels = 1;//采样声道数,1声道waveform.nAvgBytesPerSec = 16000 * 4;//每秒的数据率,就是每秒能采集多少字节的数据waveform.nBlockAlign = 2;//一个块的大小,采样bit的字节数乘以声道数waveform.cbSize = 0;//一般为0//使用waveInOpen函数开启音频采集MMRESULT mmr = waveInOpen(&hWaveIn, WAVE_MAPPER, &waveform, (DWORD)(MicCallback), DWORD(this), CALLBACK_FUNCTION);if (mmr != MMSYSERR_NOERROR) return;//建立两个数组(这里可以建立多个数组)用来缓冲音频数据DWORD bufsize = 8 * 1024;pBuffer1 = new BYTE[bufsize];pBuffer2 = new BYTE[bufsize];wHdr1.lpData = (LPSTR)pBuffer1;wHdr1.dwBufferLength = bufsize;wHdr1.dwBytesRecorded = 0;wHdr1.dwUser = 0;wHdr1.dwFlags = 0;wHdr1.dwLoops = 1;wHdr1.lpNext = NULL;wHdr1.reserved = 0;//将建立好的wHdr1做为备用waveInPrepareHeader(hWaveIn, &wHdr1, sizeof(WAVEHDR));wHdr2.lpData = (LPSTR)pBuffer2;wHdr2.dwBufferLength = bufsize;wHdr2.dwBytesRecorded = 0;wHdr2.dwUser = 0;wHdr2.dwFlags = 0;wHdr2.dwLoops = 1;wHdr2.lpNext = NULL;wHdr2.reserved = 0;//将建立好的wHdr2做为备用waveInPrepareHeader(hWaveIn, &wHdr2, sizeof(WAVEHDR));//将两个wHdr添加到waveIn中去waveInAddBuffer(hWaveIn, &wHdr1, sizeof(WAVEHDR));waveInAddBuffer(hWaveIn, &wHdr2, sizeof(WAVEHDR));//开始音频采集waveInStart(hWaveIn);
回调函数如下:
DWORD CALLBACK CPCMCollectProgramDouBufDlg::MicCallback(HWAVEIN hwavein, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2){ //这个CIMAADPCMDlg就是你的音频采集类 CPCMCollectProgramDouBufDlg*pWnd = (CPCMCollectProgramDouBufDlg*)dwInstance; switch (uMsg) { case WIM_OPEN: TRACE("WIM_OPEN\n"); break; case WIM_DATA: TRACE("WIM_DATA\n"); //采集到的数据做处理 //((PWAVEHDR)dwParam1)->lpData是采集到的数据指针 //((PWAVEHDR)dwParam1)->dwBytesRecorded是采集到的数据长度 //将采集到的数据写入文件中 fwrite(((PWAVEHDR)dwParam1)->lpData, ((PWAVEHDR)dwParam1)->dwBytesRecorded, 1, pWnd->f); //处理完了之后还要再把这个缓冲数组加回去 //pWnd->win代表是否继续采集,因为当停止采集的时候,只有当所有的 //缓冲数组都腾出来之后才能close,所以需要停止采集时就不要再waveInAddBuffer了 if (pWnd->win) waveInAddBuffer(hwavein, (PWAVEHDR)dwParam1, sizeof(WAVEHDR)); break; case WIM_CLOSE: TRACE("WIM_CLOSE\n"); break; default: break; } return 0;}
关闭代码如下:
win = false;Sleep(2000);//在这里可以等待一定的时间,确保所有缓冲数组全都退出来了//也可以在WIM_DATA消息处理中加个计数器,计算全部buffer都//退出来了,就可以调用下面的close了waveInClose(hWaveIn);fclose(f);
如果是初学者看不懂,可以直接下载整个工程慢慢研究。
地址在这
录制出来的PCM文件如果不知道怎么播放出来,请移步这里。
阅读全文
1 0
- C++ 采集音频流(PCM裸流)实现录音功能(双缓存版本)
- C++ 采集音频流(PCM裸流)实现录音功能
- C++ 采集音频流(PCM裸流)实现录音功能
- C++ 采集音频流(PCM裸流)实现录音功能
- 【iOS录音与播放】实现利用音频队列,通过缓存进行对声音的采集与播放
- 【iOS录音与播放】实现利用音频队列,通过缓存进行对声音的采集与播放
- 【iOS录音与播放】实现利用音频队列,通过缓存进行对声音的采集与播放
- 【iOS录音与播放】实现利用音频队列,通过缓存进行对声音的采集与播放
- iOS实现音频采集到缓存
- iOS实现音频采集到缓存
- c语言实现录音功能
- windows音频PCM采集及简单编码
- 使用C语言实现pcm格式音频音量的调整
- 使用C语言实现pcm格式音频的声道分离
- Android多媒体功能的实现上(音频,视频,相机,录音)
- C++ 播放音频流(PCM裸流)
- C++ 播放音频流(PCM裸流)
- C++ 播放音频流(PCM裸流)
- QT-单例程序 重新启动
- linux下nginx和tomcat负载均衡配置
- 深度网络模型压缩DEEP COMPRESSION
- linux 根据 进程名 获取 对应 PID 来 判断 使用 内存情况
- Build the App--cordova编译app
- C++ 采集音频流(PCM裸流)实现录音功能(双缓存版本)
- mongodb总结
- 获取NSAttributedString属性的方法
- 第一篇博客
- JQ单选框,选择后按钮出现图片
- The type java.util.Map$Entry cannot be resolved问题的解决
- Logback联动ELK
- Glide与圆形图片CircleImageView的问题
- Apache是世界使用排名第一的Web服务器软件