zl程序教程

您现在的位置是:首页 >  后端

当前栏目

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

方法 使用 获取 音频 录音 WindowsAPI
2023-06-13 09:15:43 时间

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

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

#include<Windows.h>
#include"mmsystem.h"
#pragmacomment(lib,"winmm.lib")

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

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

UINTwaveInGetNumDevs(VOID);

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

MMRESULTwaveInGetDevCaps(
UINT_PTRuDeviceID,
LPWAVEINCAPSpwic,
UINTcbwic
);
//uDeviceID音频输入设备标识,也可以为一个打开的音频输入设备的句柄.
//个人认为如果上一步获得了多个设备,可以用索引标识每一个设备.
//
//pwic对WAVEINCAPS结构体的一个指针,包含设备的音频特性.
//
//cbwicWAVEINCAPS结构体的大小,使用sizeof即可.
//
//MMRESULT函数执行的结果
//MMSYSERR_NOERROR表示执行成功
//MMSYSERR_BADDEVICEID索引越界
//MMSYSERR_NODRIVER没有就绪的设备
//MMSYSERR_NOMEM不能分配或者锁定内存

介绍WAVEINCAPS结构体的含义:

typedefstruct{
WORDwMid;//音频设备制造商定义的驱动程序标识
WORDwPid;//音频输入设备的产品标识
MMVERSIONvDriverVersion;//驱动程序版本号
TCHARszPname[MAXPNAMELEN];//制造商名称
DWORDdwFormats;//支持的格式,参见MSDN
WORDwChannels;//支持的声道数
WORDwReserved1;//保留参数
}WAVEINCAPS;

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

MMRESULTwaveInOpen(
LPHWAVEINphwi,//接收打开的音频输入设备标识的HWAVEIN结构的指针
UINT_PTRuDeviceID,//指定一个需要打开的设备标识.可以使用WAVE_MAPPER选择一个按指定录音格式录音的设备
LPWAVEFORMATEXpwfx,//一个所需的格式进行录音的WAVEFORMATEX结构的指针
DWORD_PTRdwCallback,//指向一个回调函数、事件句柄、窗口句柄、线程标识,对录音事件进行处理.
DWORD_PTRdwCallbackInstance,//传给回调机制的参数
DWORDfdwOpen//打开设备的方法标识,指定回调的类型.参见CSDN
);

介绍WAVEFORMATEX结构体的含义:

typedefstruct{
WORDwFormatTag;//波形声音的格式,单声道双声道使用WAVE_FORMAT_PCM.当包含在WAVEFORMATEXTENSIBLE结构中时,使用WAVE_FORMAT_EXTENSIBLE.
WORDnChannels;//声道数量
DWORDnSamplesPerSec;//采样率.wFormatTag为WAVE_FORMAT_PCM时,有8.0kHz,11.025kHz,22.05kHz,和44.1kHz.
DWORDnAvgBytesPerSec;//每秒的采样字节数.通过nSamplesPerSec*nChannels*wBitsPerSample/8计算
WORDnBlockAlign;//每次采样的字节数.通过nChannels*wBitsPerSample/8计算
WORDwBitsPerSample;//采样位数.wFormatTag为WAVE_FORMAT_PCM时,为8或者16
WORDcbSize;//wFormatTag为WAVE_FORMAT_PCM时,忽略此参数
}WAVEFORMATEX;

介绍dwCallback回调函数格式:

voidCALLBACKwaveInProc(
HWAVEINhwi,//回调此函数的设备句柄
UINTuMsg,//波形声音输入信息,标识关闭(WIM_CLOSE)、缓冲区满(WIM_DATA)、打开(WIM_OPEN).
DWORD_PTRdwInstance,//用户在waveInOpen指定的数据
DWORD_PTRdwParam1,//(LPWAVEHDR)dwParam1,用户指定的缓冲区
DWORD_PTRdwParam2
);

4.waveInPrepareHeader:为音频输入设备准备一个缓冲区

MMRESULTwaveInPrepareHeader(
HWAVEINhwi,//音频输入设备句柄
LPWAVEHDRpwh,//指向WAVEHDR结构的指针,标识准备的缓冲区
UINTcbwh//WAVEHDR结构的大小,使用sizeof即可
);

介绍WAVEHDR结构:

typedefstructwavehdr_tag{
LPSTRlpData;//指向波形格式的缓冲区
DWORDdwBufferLength;//缓冲区的大小
DWORDdwBytesRecorded;//当前存储了多少数据
DWORD_PTRdwUser;//用户数据
DWORDdwFlags;//为缓冲区提供的信息,在waveInPrepareHeader函数中使用WHDR_PREPARED
DWORDdwLoops;//输出时使用,标识播放次数
structwavehdr_tag*lpNext;//reserved
DWORD_PTRreserved;//reserved
}WAVEHDR,*LPWAVEHDR;

5.waveInAddBuffer:将缓冲区发送给设备,若缓冲区填满,则不起作用。(参数同上)

MMRESULTwaveInAddBuffer(
HWAVEINhwi,
LPWAVEHDRpwh,
UINTcbwh
);

6.waveInStart:开始进行录制

MMRESULTwaveInStart(
HWAVEINhwi//设备句柄
);

7.waveInClose:关闭设备

MRESULTwaveInClose(
HWAVEINhwi//设备句柄
);

三、完整实例代码如下:

//Run.c文件
#include<Windows.h>
#include<stdio.h>
#include"mmsystem.h"
#pragmacomment(lib,"winmm.lib")
voidPlayMusi();
voidWaveInitFormat(LPWAVEFORMATEXm_WaveFormat,WORDnCh,DWORDnSampleRate,WORDBitsPerSample);
DWORDCALLBACKMicCallback(HWAVEINhwavein,UINTuMsg,DWORDdwInstance,DWORDdwParam1,DWORDdwParam2);
voidRecordWave();

voidmain()
{
//PlayMusi();
RecordWave();
while(1);
}
voidRecordWave()
{
intcount=waveInGetNumDevs();//1
printf("\n音频输入数量:%d\n",count);

WAVEINCAPSwaveIncaps;
MMRESULTmmResult=waveInGetDevCaps(0,&waveIncaps,sizeof(WAVEINCAPS));//2
printf("\n音频输入设备:%s\n",waveIncaps.szPname);

if(MMSYSERR_NOERROR==mmResult)
{
HWAVEINphwi;
WAVEFORMATEXpwfx;
WaveInitFormat(&pwfx,1,8000,8);
printf("\n请求打开音频输入设备");
printf("\n采样参数:单声道8kHz8bit\n");
mmResult=waveInOpen(&phwi,WAVE_MAPPER,&pwfx,(DWORD)(MicCallback),NULL,CALLBACK_FUNCTION);//3

if(MMSYSERR_NOERROR==mmResult)
{
WAVEHDRpwh1;
charbuffer1[10240];
pwh1.lpData=buffer1;
pwh1.dwBufferLength=10240;
pwh1.dwUser=1;
pwh1.dwFlags=0;
mmResult=waveInPrepareHeader(phwi,&pwh1,sizeof(WAVEHDR));//4
printf("\n准备缓冲区1");

WAVEHDRpwh2;
charbuffer2[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");
}
}
}

}
}
DWORDCALLBACKMicCallback(HWAVEINhwavein,UINTuMsg,DWORDdwInstance,DWORDdwParam1,DWORDdwParam2)
{
switch(uMsg)
{
caseWIM_OPEN:
printf("\n设备已经打开...\n");
break;

caseWIM_DATA:
printf("\n缓冲区%d存满...\n",((LPWAVEHDR)dwParam1)->dwUser);
waveInAddBuffer(hwavein,(LPWAVEHDR)dwParam1,sizeof(WAVEHDR));
break;

caseWIM_CLOSE:
printf("\n设备已经关闭...\n");
break;
default:
break;
}
return0;
}
voidWaveInitFormat(LPWAVEFORMATEXm_WaveFormat,WORDnCh,DWORDnSampleRate,WORDBitsPerSample)
{
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;
}
voidPlayMusi()
{
interror=mciSendString("openC:\\Users\\Angel\\Desktop\\有多少爱可以重来.mp3aliasmyDivece",NULL,0,NULL);
if(error==0)
{
mciSendString("playmyDivece",NULL,0,NULL);//播放
}
}