使用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 //设备句柄); |
三、完整实例代码如下:
//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获取录音音频的方法
这篇文章主要介绍了使用WindowsAPI获取录音音频的方法,非常实用的功能,需要的朋友可以参考下 本文实例介绍了使用winmm.h进行音频流的获取的方法,具体步骤如下: 一.首先需要包含以下引用对象 ...
- 使用WindowsAPI播放PCM音频
这一篇文章同上一篇<使用WindowsAPI获取录音音频>原理具有相似之处,不再详细介绍函数与结构体的参数 1. waveOutGetNumDevs 2. waveOutGetDevCap ...
- mfc小工具开发之定时闹钟之---时间获取和音频播放
1.这里的音频文件是指*.wav格式的音频,参考了飞雪的音频文件,版本号: 飞雪桌面日历 v2.84.1025 绿色版 http://www.piaodown.com/down/soft/18512. ...
- H5录音音频可视化-实时波形频谱绘制、频率直方图
这段时间给GitHub Recorder开源库添加了两个新的音频可视化功能,比以前单一的动态波形显示丰富了好多(下图后两行是不是比第一行看起来丰满些):趁热打铁写了一个音频可视化相关扩展测试代码,下面 ...
- JS指定音频audio在某个时间点进行播放,获取当前音频audio的长度,音频时长格式转化
前言: 今天接到一个需求,需要获取某个.mp3音频文件的时间长度和指定音频audio在某个时间点进行播放(比如说这个视频有4分钟,我要让它默认从第2秒的时候开始播放),这里当然想到了H5中的audio ...
- AudioRecord类获取录音音量分贝数
转自:http://www.jb51.net/article/64806.htm public class AudioRecordDemo { private static final S ...
- Java 获取amr音频格式的音频长度
import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; public class GetAm ...
- php实例-正则获取网站音频地址的实例(Listen to this 1)
主要用到了:file_get_contents();preg_match_all(); 这2个函数 查看地址:http://git.oschina.net/xiaoz6/phpExample
- lua获取喜马拉雅音频地址
参考此文http://blog.csdn.net/zjg555543/article/details/39177971 在Linux下可以直接运行 #!/usr/bin/lua5. --需要luacu ...
随机推荐
- drbd + pacemaker
Centos6.5 X86 64 2014-04-27 # yum -y install corosync pacemaker # -.el6.x86_64.rpm pssh--.el6.x86_64 ...
- iOS学习之sqlite的创建数据库,表,插入查看数据
目录(?)[-] 新建项目sqliteDemo添加使用sqlite的库libsqlite3dylib sqlite 的方法 获取沙盒目录并创建或打开数据库 创建数据表 插入数据 查询数据库并打印数据 ...
- NSDictionary , NSMutableDictionary, NSMutableDictionary 和 NSMutableSet)相当于java的map、set
1 NSDictionary 和 NSMutableDictionary NSDictionary :就是java中的map; 放入对象是键值对 key-value , 同样 秉持了一样的原则,只 ...
- URAL 1099. Work Scheduling (一般图匹配带花树)
1099. Work Scheduling Time limit: 0.5 secondMemory limit: 64 MB There is certain amount of night gua ...
- python接口自动化10-token登录
前言 有些登录不是用cookie来验证的,是用token参数来判断是否登录. token传参有两种一种是放在请求头里,本质上是跟cookie是一样的,只是换个单词而已:另外一种是在url请求参数里,这 ...
- Java并发教程(Oracle官方资料)
计算机的使用者一直以为他们的计算机可以同时做很多事情.他们认为当其他的应用程序在下载文件,管理打印队列或者缓冲音频的时候他们可以继续在文字处理程序上工作.甚至对于单个应用程序,他们任然期待它能在在同一 ...
- bootstrap设计站点中加入�代码高亮插件
这款插件的名字叫做google-code-prettify 使用该插件之前的效果: 使用插件之后的效果: 接下来说步骤: (1)下载两个文件 http://codecloud.sinaapp.com/ ...
- [Linux] ubuntu下查看CHM的软件
本文旨在介绍linux下的常见chm阅读软件及其安装,并针对一些问题给出解决方法. 一.CHMSEE 这个比较常见了,呵呵. 安装: sudo apt-get install chmsee 之后在应用 ...
- Single Number and Single Number II
[] Given an array of integers, every element appears twice except for one. Find that single one. [] ...
- Java:Object类详解
Java的一些特性会让初学者感到困惑,但在有经验的开发者眼中,却是合情合理的.例如,新手可能不会理解Object类.这篇文章分成三个部分讲跟Object类及其方法有关的问题. 上帝类 问:什么是Obj ...