设置采集音频格式
- WAVEFORMATEX waveform; //采集音频的格式,结构体
- waveform.wFormatTag = WAVE_FORMAT_PCM;//声音格式为PCM
- waveform.nSamplesPerSec = 44100;//采样率
- waveform.wBitsPerSample = 16;//采样比特,16bits/次
- waveform.nChannels = 1;//采样声道数,2声道
- waveform.nAvgBytesPerSec = 16000;//每秒的数据率,就是每秒能采集多少字节的数据
- waveform.nBlockAlign = 2;//一个块的大小,采样bit的字节数乘以声道数
- waveform.cbSize = 0;//一般为0
创建线程
handle = CreateThread(NULL, 0, AudioInThreadProc, this, 0, &threadid);
打开音频设备
MMRESULT mmRet = waveInOpen(&m_hWaveIn, WAVE_MAPPER, &m_waveFormat, (DWORD_PTR)threadid, (DWORD_PTR)this, CALLBACK_THREAD);
WAVE_MAPPER系统自动匹配合适设备
MMRESULT waveInOpen(
LPHWAVEINphwi,指向打开的声音设备的标识句柄。在fdwOpen参数指定为
WAVE_FORMAT_QUERY时这个参数可以为空
UINTuDeviceID, 要打开设备的标识符
LPWAVEFORMATEXpwfx, 指向一个WAVEFORMATEX结构,它标识用于记录波形音频数据所需的格式。您可以waveInOpen返回后立即释放此结构。
DWORDdwCallback, 指针指向一个固定的回调函数,事件句柄,句柄到窗口或线程波形音频录制过程中被调用来处理与记录的进度消息的标识符。如果没有回调功能是必需的,则该值可以是零。
DWORDdwCallbackInstance,传给回调机制的数据类型,此参数并不用于窗口回调
DWORDfdwOpenz指明dwCallBack传入的数据类型,比如时间句柄或者函数指针
);
准备数据空间
for (i = 0; i < PCM_BUF_COUNT; i++)
{
m_pWaveHdr->lpData = (LPSTR)m_pData;
m_pWaveHdr->dwBufferLength = BUFFER_SIZE;
m_pWaveHdr->dwBytesRecorded = 0;
m_pWaveHdr->dwFlags = 0;
m_pWaveHdr->dwUser = (DWORD_PTR)this;
MMRESULT mmRet = waveInPrepareHeader(hIn, m_pWaveHdr, sizeof(WAVEHDR));
if (MMSYSERR_NOERROR != mmRet)
{
return false;
}
MMRESULT mmRet = waveInAddBuffer(hIn, m_pWaveHdr, sizeof(WAVEHDR));
if (MMSYSERR_NOERROR != mmRet)
{
return false;
}
}
为音频输入设备提供缓冲区
MMRESULT waveInPrepareHeader(
HWAVEINhwi, 声音输入设备句柄
LPWAVEHDRpwh, 指向WAVEHDR结构,标识要准备的缓冲区。
UINTcbwhWAVEHDR结构的大小
);
发送一个输入缓冲区给定的波形音频输入设备。当缓冲区被填满后,通知应用程序。
MMRESULT waveInAddBuffer(
HWAVEINhwi, 声音输入设备句柄
LPWAVEHDRpwh, 指向WAVEHDR结构,标识要准备的缓冲区。
UINTcbwhWAVEHDR结构的大小
);
开始录音
mmRet = waveInStart(m_hWaveIn);
MMRESULT waveInStart(
HWAVEINhwi 设备句柄
);
数据接收线程
DWORD __stdcall AudioGatherdlg::AudioInThreadProc(LPVOID lpParameter)
{
MSG msg;
MMRESULT mmRet;
while (GetMessage(&msg, 0, 0, 0))
{
switch (msg.message)
{
case MM_WIM_OPEN:
cout << "MM_WIM_OPEN " << endl;
break;
case MM_WIM_CLOSE:
cout << "MM_WIM_CLOSE " << endl;
break;
case MM_WIM_DATA: //缓冲区满后调用
*pWaveIn->pHdr = (WAVEHDR*)msg.lParam;
mmRet=waveInUnprepareHeader((HWAVEIN)msg.wParam, *pWaveIn->pHdr, sizeof(WAVEHDR));
mmRet=waveInPrepareHeader((HWAVEIN)msg.wParam, (*pWaveIn->pHdr), sizeof(WAVEHDR));
mmRet=waveInAddBuffer((HWAVEIN)msg.wParam, (*pWaveIn->pHdr), sizeof(WAVEHDR));
break;
}
}
return msg.wParam;
}
停止录音并关闭设备
MMRESULT mmRet = waveInStop(m_hWaveIn);
if (mmRet != MMSYSERR_NOERROR)
{
return false;
}
mmRet = waveInReset(m_hWaveIn);
if (mmRet != MMSYSERR_NOERROR)
{
return false;
}
mmRet = waveInClose(m_hWaveIn);
if (mmRet != MMSYSERR_NOERROR)
{
return false;
}
MMRESULT waveInStop(
HWAVEINhwi 设备句柄
);
MMRESULT waveInReset(
HWAVEINhwi 设备句柄
);
MMRESULT waveInClose(
HWAVEINhwi 设备句柄
);