当前位置:  编程技术>c/c++/嵌入式

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

    来源: 互联网  发布时间:2014-10-27

    本文导语:  本文实例介绍了使用winmm.h进行音频流的获取的方法,具体步骤如下: 一、首先需要包含以下引用对象 #include #include "mmsystem.h" #pragma comment(lib, "winmm.lib") 二、音频的获取需要调用7个函数 1. waveInGetNumDevs:返回系统中就绪...

本文实例介绍了使用winmm.h进行音频流的获取的方法,具体步骤如下:

一、首先需要包含以下引用对象

#include 
#include "mmsystem.h"
#pragma comment(lib, "winmm.lib")

二、音频的获取需要调用7个函数

1. waveInGetNumDevs:返回系统中就绪的波形声音输入设备的数量

UINT waveInGetNumDevs(VOID);

2. waveInGetDevCaps:检查指定波形输入设备的特性

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结构体的含义:

typedef struct { 
  WORD   wMid;        //音频设备制造商定义的驱动程序标识
  WORD   wPid;        //音频输入设备的产品标识
  MMVERSION vDriverVersion;    //驱动程序版本号
  TCHAR   szPname[MAXPNAMELEN];//制造商名称
  DWORD   dwFormats;      //支持的格式,参见MSDN
  WORD   wChannels;      //支持的声道数
  WORD   wReserved1;      //保留参数
} WAVEINCAPS;

3. waveInOpen:打开指定的音频输入设备,进行录音

MMRESULT waveInOpen(
 LPHWAVEIN    phwi,        //接收打开的音频输入设备标识的HWAVEIN结构的指针
 UINT_PTR    uDeviceID,      //指定一个需要打开的设备标识.可以使用WAVE_MAPPER选择一个按指定录音格式录音的设备
 LPWAVEFORMATEX pwfx,        //一个所需的格式进行录音的WAVEFORMATEX结构的指针 
 DWORD_PTR   dwCallback,    //指向一个回调函数、事件句柄、窗口句柄、线程标识,对录音事件进行处理.
 DWORD_PTR   dwCallbackInstance, //传给回调机制的参数
 DWORD     fdwOpen      //打开设备的方法标识,指定回调的类型.参见CSDN
);

介绍WAVEFORMATEX结构体的含义:

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回调函数格式:

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:为音频输入设备准备一个缓冲区

MMRESULT waveInPrepareHeader(
 HWAVEIN hwi,  //音频输入设备句柄
 LPWAVEHDR pwh,//指向WAVEHDR结构的指针,标识准备的缓冲区
 UINT cbwh    //WAVEHDR结构的大小,使用sizeof即可
);

介绍WAVEHDR结构:

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:将缓冲区发送给设备,若缓冲区填满,则不起作用。(参数同上)

MMRESULT waveInAddBuffer(
 HWAVEIN hwi, 
 LPWAVEHDR pwh, 
 UINT cbwh 
); 

6. waveInStart:开始进行录制

MMRESULT waveInStart(
 HWAVEIN hwi //设备句柄
);

7. waveInClose:关闭设备

MRESULT waveInClose(
 HWAVEIN hwi //设备句柄
);

三、完整实例代码如下:

//Run.c文件
#include 
#include 
#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音频输入数量:%dn",count);

 WAVEINCAPS waveIncaps;
 MMRESULT mmResult = waveInGetDevCaps(0,&waveIncaps,sizeof(WAVEINCAPS));//2
 printf("n音频输入设备:%sn",waveIncaps.szPname);

 if(MMSYSERR_NOERROR==mmResult)
 {
 HWAVEIN phwi;
 WAVEFORMATEX pwfx;
 WaveInitFormat(&pwfx,1,8000,8);
 printf("n请求打开音频输入设备");
 printf("n采样参数:单声道 8kHz 8bitn");
 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准备缓冲区2n");

  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); //播放
 }
}


    
 
 
 
本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • linux不用命令方式读文件获取网络流量,如何使用C函数调用获取网络流量信息?
  • 急,,,怎样获取远程系统的CPU和内存使用率
  • curl不使用文件存取cookie php使用curl获取cookie示例
  • 怎么写个CGI程序获取远程linux主机的信息,如cpu使用率,内存使用等?
  • 如何获取客户端浏览器所使用的语言,特别是要区分简繁体!
  • 使用ps命令,如何使用系统命令根据进程名称获取进程和子进程的ID?除了ps,还有其它系统命令的办法吗?谢谢。
  • 使用Jquery获取带特殊符号的ID 标签的方法
  • sql server 使用ntile获取数据的例子
  • c语言在unix系统下,如何获取cpu使用率
  • php开源软件 iis7站长之家
  • 怎样使用FTP递归获取文件夹下的所有文件及子文件夹?
  • [求助]如何获取一个程序所使用的系统调用和参数?
  • jquery使用$(element).is()来判断获取的tagName
  • ASP.NET使用Subtract方法获取两个日期之间的天数
  • 哪位编程高手知道如何编程实现获取进程的内存使用量信息(linux)
  • 多网卡多IP情况下如何通过脚本获取当前登录终端使用的ip?
  • 使用标准SAX解析XML文档如何获取文档编码信息及约束它的dtd文件路径.
  • linux中,获取系统的CPU、内存、硬盘使用情况该用什么函数?
  • 如何使用c语言获取当前系统的时间,就是那个秒数?
  • 请问,怎样通过程序方式,获取AIX系统当前的CPU, 内存使用情况?
  • C++ I/O 成员 tellg():使用输入流读取流指针
  • 在测试memset函数的执行效率时,分为使用Cash和不使用Cash辆种方式,该如何控制是否使用缓存?
  • C++ I/O 成员 tellp():使用输出流读取流指针
  • 求ibm6000的中文使用手册 !从来没用过服务器,现在急需使用它,不知如何使用! 急!!!!!
  • Python不使用print而直接输出二进制字符串
  • 请问:在使用oracle数据库作开发时,是使用pro*c作开发好些,还是使用库函数如oci等好一些啊?或者它们有什么区别或者优缺点啊?
  • Office 2010 Module模式下使用VBA Addressof
  • 急求结果!!假设一个有两个元素的信号量集S,表示了一个磁带驱动器系统,其中进程1使用磁带机A,进程2同时使用磁带机A和B,进程3使用磁带机B。
  • windows下tinyxml.dll下载安装使用(c++解析XML库)
  • c#中SAPI使用总结——SpVoice的使用方法
  • tcmalloc内存泄露优化c++开源库下载,安装及使用介绍


  • 站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3