本文实例介绍了使用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获取录音音频的更多相关文章

  1. 使用WindowsAPI获取录音音频的方法

    这篇文章主要介绍了使用WindowsAPI获取录音音频的方法,非常实用的功能,需要的朋友可以参考下 本文实例介绍了使用winmm.h进行音频流的获取的方法,具体步骤如下: 一.首先需要包含以下引用对象 ...

  2. 使用WindowsAPI播放PCM音频

    这一篇文章同上一篇<使用WindowsAPI获取录音音频>原理具有相似之处,不再详细介绍函数与结构体的参数 1. waveOutGetNumDevs 2. waveOutGetDevCap ...

  3. mfc小工具开发之定时闹钟之---时间获取和音频播放

    1.这里的音频文件是指*.wav格式的音频,参考了飞雪的音频文件,版本号: 飞雪桌面日历 v2.84.1025 绿色版 http://www.piaodown.com/down/soft/18512. ...

  4. H5录音音频可视化-实时波形频谱绘制、频率直方图

    这段时间给GitHub Recorder开源库添加了两个新的音频可视化功能,比以前单一的动态波形显示丰富了好多(下图后两行是不是比第一行看起来丰满些):趁热打铁写了一个音频可视化相关扩展测试代码,下面 ...

  5. JS指定音频audio在某个时间点进行播放,获取当前音频audio的长度,音频时长格式转化

    前言: 今天接到一个需求,需要获取某个.mp3音频文件的时间长度和指定音频audio在某个时间点进行播放(比如说这个视频有4分钟,我要让它默认从第2秒的时候开始播放),这里当然想到了H5中的audio ...

  6. AudioRecord类获取录音音量分贝数

    转自:http://www.jb51.net/article/64806.htm   public class AudioRecordDemo {     private static final S ...

  7. Java 获取amr音频格式的音频长度

    import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; public class GetAm ...

  8. php实例-正则获取网站音频地址的实例(Listen to this 1)

    主要用到了:file_get_contents();preg_match_all(); 这2个函数 查看地址:http://git.oschina.net/xiaoz6/phpExample

  9. lua获取喜马拉雅音频地址

    参考此文http://blog.csdn.net/zjg555543/article/details/39177971 在Linux下可以直接运行 #!/usr/bin/lua5. --需要luacu ...

随机推荐

  1. 关于利用ajax时,设置访问延时的方法

    在实际开发中应使用后端的延时方法,一般为sleep,可以设置延时几秒后返回给前端请求的数据 众所周知,在js中,并不存在例如C++或者JAVA.PHP中的sleep延时方法, 目前仅有的所谓延时方法S ...

  2. WICED™ <SMART> Software Development Kit

    WICED™ Software Development Kit The WICED™ SDK includes the tools and software needed to create Wi-F ...

  3. Spring构造方法注入类型歧义

    在Spring框架中,当一个类包含多个构造函数带的参数相同,它总是会造成构造函数注入参数类型歧义的问题. 问题 让我们来看看这个客户 bean 实例.它包含两个构造方法,均接受3个不同的数据类型参数. ...

  4. 介绍:一款Mathematica的替代开源软件Mathetics

    Mathetics软件 1 以Python语言实现该系统 2 软件使用的语法与Mathematica同样 3 下载:http://www.mathics.org/ 4 手冊:http://www.ma ...

  5. FAQ:如何修改领域模型?

    问答部分 问: 如何修改领域模型? 答: 一般来说我们有两种选择,这两种选择也是两种价值观的体现(乐观和悲观). 第一种:使用UI传递过来的DTO在应用层重建Domain Model,然后执行修改,D ...

  6. 2014 百度之星 题解 1004 Labyrinth

    Problem Description 度度熊是一仅仅喜欢探险的熊,一次偶然落进了一个m*n矩阵的迷宫,该迷宫仅仅能从矩阵左上角第一个方格開始走,仅仅有走到右上角的第一个格子才算走出迷宫,每一次仅仅能 ...

  7. OpenJudge 8782 乘积最大——S.B.S

    8782:乘积最大 总时间限制: 1000ms 内存限制:  65536kB 描述 今年是国际数学联盟确定的“2000——世界数学年”,又恰逢我国著名数学家华罗庚先生诞辰90周年.在华罗庚先生的家乡江 ...

  8. Perl &amp; Python编写CGI

    近期偶然玩了一下CGI,收集点资料写篇在这里留档. 如今想做HTTP Cache回归測试了,为了模拟不同的响应头及数据大小.就须要一个CGI按须要传回指定的响应头和内容.这是从老外的測试页面学习到的经 ...

  9. Spark Streaming中空batches处理的两种方法(转)

    原文链接:Spark Streaming中空batches处理的两种方法 Spark Streaming是近实时(near real time)的小批处理系统.对给定的时间间隔(interval),S ...

  10. RS布局问题之块的不完美之完美

    早上一来,便传来喜讯...说我们做的报表太美.客户不敢看----于是便开启征程,亲自尝试了一把,如下面的操作,首次运行报表,在不考虑UI美观度的情况下,报表还是 在预测范围内显示的 那么接下来我们选择 ...