使用WindowsAPI获取录音音频的方法
本文实例介绍了使用winmm.h进行音频流的获取的方法,具体步骤如下:
一、首先需要包含以下引用对象
|
1
2
3
|
#include <Windows.h> #include "mmsystem.h" #pragma comment(lib, "winmm.lib") |
二、音频的获取需要调用7个函数
1. waveInGetNumDevs:返回系统中就绪的波形声音输入设备的数量
|
1
|
UINT waveInGetNumDevs(VOID); |
2. waveInGetDevCaps:检查指定波形输入设备的特性
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
MMRESULT waveInGetDevCaps( UINT_PTR uDeviceID, LPWAVEINCAPS pwic, UINT cbwic ); //uDeviceID 音频输入设备标识,也可以为一个打开的音频输入设备的句柄. // 个人认为如果上一步获得了多个设备,可以用索引标识每一个设备. // //pwic 对WAVEINCAPS结构体的一个指针,包含设备的音频特性. // //cbwic WAVEINCAPS结构体的大小,使用sizeof即可. // //MMRESULT 函数执行的结果 // MMSYSERR_NOERROR 表示执行成功 // MMSYSERR_BADDEVICEID 索引越界 // MMSYSERR_NODRIVER 没有就绪的设备 // MMSYSERR_NOMEM 不能分配或者锁定内存 |
介绍WAVEINCAPS结构体的含义:
|
1
2
3
4
5
6
7
8
9
|
typedef struct { WORD wMid; //音频设备制造商定义的驱动程序标识 WORD wPid; //音频输入设备的产品标识 MMVERSION vDriverVersion; //驱动程序版本号 TCHAR szPname[MAXPNAMELEN];//制造商名称 DWORD dwFormats; //支持的格式,参见MSDN WORD wChannels; //支持的声道数 WORD wReserved1; //保留参数 } WAVEINCAPS; |
3. waveInOpen:打开指定的音频输入设备,进行录音
|
1
2
3
4
5
6
7
8
|
MMRESULT waveInOpen( LPHWAVEIN phwi, //接收打开的音频输入设备标识的HWAVEIN结构的指针 UINT_PTR uDeviceID, //指定一个需要打开的设备标识.可以使用WAVE_MAPPER选择一个按指定录音格式录音的设备 LPWAVEFORMATEX pwfx, //一个所需的格式进行录音的WAVEFORMATEX结构的指针 DWORD_PTR dwCallback, //指向一个回调函数、事件句柄、窗口句柄、线程标识,对录音事件进行处理. DWORD_PTR dwCallbackInstance, //传给回调机制的参数 DWORD fdwOpen //打开设备的方法标识,指定回调的类型.参见CSDN ); |
介绍WAVEFORMATEX结构体的含义:
|
1
2
3
4
5
6
7
8
9
|
typedef struct { WORD wFormatTag; //波形声音的格式,单声道双声道使用WAVE_FORMAT_PCM.当包含在WAVEFORMATEXTENSIBLE结构中时,使用WAVE_FORMAT_EXTENSIBLE. WORD nChannels; //声道数量 DWORD nSamplesPerSec; //采样率.wFormatTag为WAVE_FORMAT_PCM时,有8.0kHz,11.025kHz,22.05kHz,和44.1kHz. DWORD nAvgBytesPerSec; //每秒的采样字节数.通过nSamplesPerSec * nChannels * wBitsPerSample / 8计算 WORD nBlockAlign; //每次采样的字节数.通过nChannels * wBitsPerSample / 8计算 WORD wBitsPerSample; //采样位数.wFormatTag为WAVE_FORMAT_PCM时,为8或者16 WORD cbSize; //wFormatTag为WAVE_FORMAT_PCM时,忽略此参数 } WAVEFORMATEX; |
介绍dwCallback回调函数格式:
|
1
2
3
4
5
6
7
|
void CALLBACK waveInProc( HWAVEIN hwi, //回调此函数的设备句柄 UINT uMsg, //波形声音输入信息,标识关闭(WIM_CLOSE)、缓冲区满(WIM_DATA)、打开(WIM_OPEN). DWORD_PTR dwInstance, //用户在waveInOpen指定的数据 DWORD_PTR dwParam1, //(LPWAVEHDR)dwParam1,用户指定的缓冲区 DWORD_PTR dwParam2 ); |
4. waveInPrepareHeader:为音频输入设备准备一个缓冲区
|
1
2
3
4
5
|
MMRESULT waveInPrepareHeader( HWAVEIN hwi, //音频输入设备句柄 LPWAVEHDR pwh,//指向WAVEHDR结构的指针,标识准备的缓冲区 UINT cbwh //WAVEHDR结构的大小,使用sizeof即可 ); |
介绍WAVEHDR结构:
|
1
2
3
4
5
6
7
8
9
10
|
typedef struct wavehdr_tag { LPSTR lpData; //指向波形格式的缓冲区 DWORD dwBufferLength; //缓冲区的大小 DWORD dwBytesRecorded; //当前存储了多少数据 DWORD_PTR dwUser; //用户数据 DWORD dwFlags; //为缓冲区提供的信息,在waveInPrepareHeader函数中使用WHDR_PREPARED DWORD dwLoops; //输出时使用,标识播放次数 struct wavehdr_tag * lpNext;//reserved DWORD_PTR reserved; //reserved } WAVEHDR, *LPWAVEHDR; |
5. waveInAddBuffer:将缓冲区发送给设备,若缓冲区填满,则不起作用。(参数同上)
|
1
2
3
4
5
|
MMRESULT waveInAddBuffer( HWAVEIN hwi, LPWAVEHDR pwh, UINT cbwh ); |
6. waveInStart:开始进行录制
|
1
2
3
|
MMRESULT waveInStart( HWAVEIN hwi //设备句柄 ); |
7. waveInClose:关闭设备
|
1
2
3
|
MRESULT waveInClose( HWAVEIN hwi //设备句柄 ); |
三、完整实例代码如下:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
//Run.c文件 #include <Windows.h> #include <stdio.h> #include "mmsystem.h" #pragma comment(lib, "winmm.lib") void PlayMusi(); void WaveInitFormat(LPWAVEFORMATEX m_WaveFormat, WORD nCh,DWORD nSampleRate,WORD BitsPerSample); DWORD CALLBACK MicCallback(HWAVEIN hwavein, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2); void RecordWave(); void main() { //PlayMusi(); RecordWave(); while(1); } void RecordWave() { int count = waveInGetNumDevs();//1 printf("\n音频输入数量:%d\n",count); WAVEINCAPS waveIncaps; MMRESULT mmResult = waveInGetDevCaps(0,&waveIncaps,sizeof(WAVEINCAPS));//2 printf("\n音频输入设备:%s\n",waveIncaps.szPname); if(MMSYSERR_NOERROR==mmResult) { HWAVEIN phwi; WAVEFORMATEX pwfx; WaveInitFormat(&pwfx,1,8000,8); printf("\n请求打开音频输入设备"); printf("\n采样参数:单声道 8kHz 8bit\n"); mmResult=waveInOpen(&phwi,WAVE_MAPPER,&pwfx,(DWORD)(MicCallback),NULL,CALLBACK_FUNCTION);//3 if(MMSYSERR_NOERROR==mmResult) { WAVEHDR pwh1; char buffer1[10240]; pwh1.lpData=buffer1; pwh1.dwBufferLength=10240; pwh1.dwUser=1; pwh1.dwFlags=0; mmResult=waveInPrepareHeader(phwi,&pwh1,sizeof(WAVEHDR));//4 printf("\n准备缓冲区1"); WAVEHDR pwh2; char buffer2[10240]; pwh2.lpData=buffer2; pwh2.dwBufferLength=10240; pwh2.dwUser=2; pwh2.dwFlags=0; mmResult=waveInPrepareHeader(phwi,&pwh2,sizeof(WAVEHDR));//4 printf("\n准备缓冲区2\n"); if(MMSYSERR_NOERROR==mmResult) { mmResult=waveInAddBuffer(phwi,&pwh1,sizeof(WAVEHDR));//5 printf("\n将缓冲区1加入音频输入设备"); mmResult=waveInAddBuffer(phwi,&pwh2,sizeof(WAVEHDR));//5 printf("\n将缓冲区2加入音频输入设备\n"); if(MMSYSERR_NOERROR==mmResult) { mmResult=waveInStart(phwi);//6 printf("\n请求开始录音\n"); } } } } } DWORD CALLBACK MicCallback(HWAVEIN hwavein, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2) { switch(uMsg) { case WIM_OPEN: printf("\n设备已经打开...\n"); break; case WIM_DATA: printf("\n缓冲区%d存满...\n",((LPWAVEHDR)dwParam1)->dwUser); waveInAddBuffer (hwavein, (LPWAVEHDR)dwParam1, sizeof (WAVEHDR)) ; break; case WIM_CLOSE: printf("\n设备已经关闭...\n"); break; default: break; } return 0; } void WaveInitFormat(LPWAVEFORMATEX m_WaveFormat, WORD nCh,DWORD nSampleRate,WORD BitsPerSample) { m_WaveFormat->wFormatTag = WAVE_FORMAT_PCM; m_WaveFormat->nChannels = nCh; m_WaveFormat->nSamplesPerSec = nSampleRate; m_WaveFormat->nAvgBytesPerSec = nSampleRate * nCh * BitsPerSample/8; m_WaveFormat->nBlockAlign = m_WaveFormat->nChannels * BitsPerSample/8; m_WaveFormat->wBitsPerSample = BitsPerSample; m_WaveFormat->cbSize = 0; } void PlayMusi() { int error = mciSendString("open C:\\Users\\Angel\\Desktop\\有多少爱可以重来.mp3 alias myDivece", NULL, 0, NULL); if (error == 0) { mciSendString("play myDivece", NULL, 0, NULL); //播放 } } |
使用WindowsAPI获取录音音频的方法的更多相关文章
- 使用WindowsAPI获取录音音频
本文实例介绍了使用winmm.h进行音频流的获取的方法,具体步骤如下: 一.首先需要包含以下引用对象 ? 1 2 3 #include <Windows.h> #include " ...
- 使用WindowsAPI实现播放PCM音频的方法
这篇文章主要介绍了使用WindowsAPI实现播放PCM音频的方法,很实用的一个功能,需要的朋友可以参考下 本文介绍了使用WindowsAPI实现播放PCM音频的方法,同前面一篇使用WindowsAP ...
- 使用WindowsAPI播放PCM音频
这一篇文章同上一篇<使用WindowsAPI获取录音音频>原理具有相似之处,不再详细介绍函数与结构体的参数 1. waveOutGetNumDevs 2. waveOutGetDevCap ...
- 使用ffmpeg实现合并多个音频为一个音频的方法
使用ffmpeg实现合并多个音频为一个音频的方法可以使用ffmpeg的filter功能来进行这个操作,而且效果很好amerge也可以实 使用ffmpeg实现合并多个音频为一个音频的方法 可以使用ffm ...
- [No00006F]总结C#获取当前路径的各种方法
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...
- VMware桥接模式无法自动化获取IP的解决方法
虚拟机桥接无法自动获取IP的解决方法 在虚拟机VM里面装了centos系统,网卡选用桥接方式. 刚开始的时候还能自动获取到IP地址,突然有一天IP消失了,再怎么重启都无法获取IP地址.因为之前是可以获 ...
- C#的path.GetFullPath 获取上级目录实现方法
这篇文章主要介绍了C#的path.GetFullPath 获取上级目录实现方法,包含了具体的C#实现方法以及ASP.net与ASP等的方法对比,非常具有实用价值,需要的朋友可以参考下 本文实例讲述 ...
- 多浏览器兼容用javascript获取url参数的方法比较推荐的一种
多浏览器兼容用javascript获取url参数的方法比较推荐的一种 <script language = javascript> function request(paras){ var ...
- 使用jquery获取url以及jquery获取url参数的方法
使用jquery获取url以及使用jquery获取url参数是我们经常要用到的操作 1.jquery获取url很简单,代码如下 1.window.location.href; 其实只是用到了javas ...
随机推荐
- centos7.0 crontab 的yii计划任务没有执行
*/1 * * * * /www/yii solr/update-article 创建了每分钟执行一次的计划而计划任务没有执行 原因是自己少加了执行用户 */1 * * * * php /www/yi ...
- Python小白的发展之路之Python基础(二)【字符串、列表、集合、文件操作】
列表.元组操作 字符串操作 字典操作 集合操作 文件操作 字符编码与转码 1.列表.元组操作 (1)列表 列表是可变的(mutable)——可以改变列表的内容,这不同于字符串和元组,字符串和元组都是不 ...
- Netty实现java多线程Post请求解析(Map参数类型)—SKY
netty解析Post的键值对 解析时必须加上一个方法,ch.pipeline().addLast(new HttpObjectAggregator(2048)); 放在自己的Handel前面. ht ...
- Hibernate Criteria 查询使用
转载 http://blog.csdn.net/woshisap/article/details/6747466 Hibernate 设计了 CriteriaSpecification 作为 Crit ...
- 九度OJ 1200:最大的两个数 (最值)
时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:2904 解决:761 题目描述: 输入一个四行五列的矩阵,找出每列最大的两个数. 输入: 输入第一行包括一个整数n(1<=n<= ...
- 九度OJ 1181:遍历链表 (链表、排序)
时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:2733 解决:1181 题目描述: 建立一个升序链表并遍历输出. 输入: 输入的每个案例中第一行包括1个整数:n(1<=n<=1 ...
- Redis1 介绍和字典
Redis介绍 redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(列表).set(集合).zset(sor ...
- Cordova+FrameWork7开发简单教程
1: 环境要有:(一个不会搭建环境的程序员,要么学,要么退出编程 ) 环境这里我只说需要什么: 1>AndroidStudio 3.0 (2.几的版本总会出问题.我喜欢用新版本) 2>co ...
- activiti基础--1------------------------生成.bpmn和.png以及部署流程定义
helloworld.dbmn <?xml version="1.0" encoding="UTF-8"?> <definitions xml ...
- error in static/js/xxx.js from UglifyJs Unpected token: punc() [static/js/xxx.js]
出现问题 使用vue+element-ui+webpack开发项目时,Jenkins构建出现报错error in static/js/xxx.js from UglifyJs Unpected tok ...